Rollup merge of #157131 - pbkx:issue-144888-ui-test, r=petrochenkov

Add regression test for issue #144888

Issue rust-lang/rust#144888 is labeled E-needs-test for an ICE involving `unhandled node Crate(Mod)`.

This adds a focused UI regression test for the reduced example. The test is compile-fail, checks the current non-ICE diagnostics, and avoids the unrelated missing-main diagnostic by compiling as a library.

Fixes rust-lang/rust#144888.
diff --git a/Cargo.lock b/Cargo.lock
index 8938c49..a3f7b3a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4756,6 +4756,7 @@
 name = "rustc_target"
 version = "0.0.0"
 dependencies = [
+ "arrayvec",
  "bitflags",
  "object 0.37.3",
  "rustc_abi",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 8ab80c7..733a195 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -1,6 +1,7 @@
 use std::collections::BTreeSet;
 use std::fmt::{self, Write};
 use std::ops::Deref;
+use std::range::RangeInclusive;
 use std::{cmp, iter};
 
 use rustc_hashes::Hash64;
@@ -631,11 +632,13 @@ struct VariantLayoutInfo {
             let all_indices = variants.indices();
             let needs_disc =
                 |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
-            let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
-                ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
+            let niche_variants = RangeInclusive {
+                start: all_indices.clone().find(|v| needs_disc(*v)).unwrap(),
+                last: all_indices.rev().find(|v| needs_disc(*v)).unwrap(),
+            };
 
             let count =
-                (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1;
+                (niche_variants.last.index() as u128 - niche_variants.start.index() as u128) + 1;
 
             // Use the largest niche in the largest variant.
             let niche = variant_layouts[largest_variant_index].largest_niche?;
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 5e1a95d..166c8be 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -40,7 +40,8 @@
 #[cfg(feature = "nightly")]
 use std::iter::Step;
 use std::num::{NonZeroUsize, ParseIntError};
-use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, Sub};
+use std::range::RangeInclusive;
 use std::str::FromStr;
 
 use bitflags::bitflags;
@@ -1958,7 +1959,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
 }
 
 // NOTE: This struct is generic over the VariantIdx for rust-analyzer usage.
-#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
 #[cfg_attr(feature = "nightly", derive(StableHash))]
 pub enum TagEncoding<VariantIdx: Idx> {
     /// The tag directly stores the discriminant, but possibly with a smaller layout
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 8accaa8..5ea6201 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -124,7 +124,7 @@ pub(crate) fn lower_delegation(
         // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356)
         let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id)
         {
-            self.get_sig_id(delegation_info.resolution_node, span)
+            self.get_sig_id(delegation_info.resolution_id, span)
         } else {
             self.dcx().span_delayed_bug(
                 span,
@@ -230,22 +230,12 @@ fn create_new_attrs(
             .collect::<Vec<_>>()
     }
 
-    fn get_sig_id(&self, mut node_id: NodeId, span: Span) -> Result<DefId, ErrorGuaranteed> {
-        let mut visited: FxHashSet<NodeId> = Default::default();
+    fn get_sig_id(&self, mut def_id: DefId, span: Span) -> Result<DefId, ErrorGuaranteed> {
+        let mut visited: FxHashSet<DefId> = Default::default();
         let mut path: SmallVec<[DefId; 1]> = Default::default();
 
         loop {
-            visited.insert(node_id);
-
-            let Some(def_id) = self.get_resolution_id(node_id) else {
-                return Err(self.tcx.dcx().span_delayed_bug(
-                    span,
-                    format!(
-                        "LoweringContext: couldn't resolve node {:?} in delegation item",
-                        node_id
-                    ),
-                ));
-            };
+            visited.insert(def_id);
 
             path.push(def_id);
 
@@ -255,8 +245,8 @@ fn get_sig_id(&self, mut node_id: NodeId, span: Span) -> Result<DefId, ErrorGuar
             if let Some(local_id) = def_id.as_local()
                 && let Some(delegation_info) = self.resolver.delegation_info(local_id)
             {
-                node_id = delegation_info.resolution_node;
-                if visited.contains(&node_id) {
+                def_id = delegation_info.resolution_id;
+                if visited.contains(&def_id) {
                     // We encountered a cycle in the resolution, or delegation callee refers to non-existent
                     // entity, in this case emit an error.
                     return Err(match visited.len() {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 87e1d9a..ce20aaf 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1549,7 +1549,7 @@ fn lower_label(
     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
         let target_id = match destination {
             Some((id, _)) => {
-                if let Some(loop_id) = self.resolver.get_label_res(id) {
+                if let Some(loop_id) = self.owner.get_label_res(id) {
                     let local_id = self.ident_and_label_to_local_id[&loop_id];
                     let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };
                     Ok(loop_hir_id)
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e38415c..70f55d6 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1192,50 +1192,34 @@ fn lower_trait_impl_header(
         })
     }
 
-    fn resolve_pin_drop_sugar_impl_item(
+    fn check_pin_drop_sugar_impl_item(
         &self,
         i: &AssocItem,
         ident: Ident,
-        span: Span,
-    ) -> (Ident, Result<DefId, ErrorGuaranteed>) {
-        let trait_item_def_id = self
-            .get_partial_res(i.id)
-            .and_then(|r| r.expect_full_res().opt_def_id())
-            .ok_or_else(|| {
-                self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented")
-            });
-
-        let is_pin_drop_sugar = match &i.kind {
-            AssocItemKind::Fn(fn_kind) => fn_kind.is_pin_drop_sugar(),
-            _ => false,
-        };
-        let def_id = match trait_item_def_id {
-            Ok(def_id) => def_id,
-            Err(guar) => return (ident, Err(guar)),
-        };
-        if !is_pin_drop_sugar {
-            return (ident, Ok(def_id));
+        trait_item: Result<DefId, ErrorGuaranteed>,
+    ) -> Ident {
+        if let AssocItemKind::Fn(fn_kind) = &i.kind
+            && fn_kind.is_pin_drop_sugar()
+        {
+            if let Ok(trait_item) = trait_item
+                && self
+                    .tcx
+                    .lang_items()
+                    .drop_trait()
+                    .is_none_or(|drop_trait| self.tcx.parent(trait_item) != drop_trait)
+            {
+                self.dcx()
+                    .struct_span_err(
+                        i.span,
+                        "method `drop` with `&pin mut self` is only supported for the `Drop` trait",
+                    )
+                    .with_span_label(i.span, "not a `Drop::pin_drop` implementation")
+                    .emit();
+            }
+            return Ident::new(sym::pin_drop, ident.span);
         }
 
-        let is_drop_pin_drop = self
-            .tcx
-            .lang_items()
-            .drop_trait()
-            .is_some_and(|drop_trait| self.tcx.parent(def_id) == drop_trait);
-        if is_drop_pin_drop {
-            // Associated item collection still derives the impl item's name from HIR.
-            return (Ident::new(sym::pin_drop, ident.span), Ok(def_id));
-        }
-
-        let guar = self
-            .dcx()
-            .struct_span_err(
-                i.span,
-                "method `drop` with `&pin mut self` is only supported for the `Drop` trait",
-            )
-            .with_span_label(i.span, "not a `Drop::pin_drop` implementation")
-            .emit();
-        (ident, Err(guar))
+        ident
     }
 
     fn lower_impl_item(
@@ -1356,8 +1340,14 @@ fn lower_impl_item(
 
         let span = self.lower_span(i.span);
         let (effective_ident, impl_kind) = if is_in_trait_impl {
-            let (effective_ident, trait_item_def_id) =
-                self.resolve_pin_drop_sugar_impl_item(i, ident, span);
+            let trait_item_def_id = self
+                .get_partial_res(i.id)
+                .and_then(|r| r.expect_full_res().opt_def_id())
+                .ok_or_else(|| {
+                    self.dcx()
+                        .span_delayed_bug(span, "could not resolve trait item being implemented")
+                });
+            let effective_ident = self.check_pin_drop_sugar_impl_item(i, ident, trait_item_def_id);
             (effective_ident, ImplItemImplKind::Trait { defaultness, trait_item_def_id })
         } else {
             (ident, ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) })
@@ -1928,11 +1918,11 @@ fn lower_generics<T>(
 
         // Introduce extra lifetimes if late resolution tells us to.
         let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
-        params.extend(extra_lifetimes.into_iter().filter_map(|&(ident, node_id, res)| {
+        params.extend(extra_lifetimes.into_iter().map(|&(ident, node_id, kind)| {
             self.lifetime_res_to_generic_param(
                 ident,
                 node_id,
-                res,
+                kind,
                 hir::GenericParamSource::Generics,
             )
         }));
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index a916ee1..4045f08 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -55,7 +55,7 @@
 use rustc_hir::lints::DelayedLint;
 use rustc_hir::{
     self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
-    LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr,
+    LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -293,16 +293,6 @@ fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>> {
         self.import_res_map.get(&id).copied().unwrap_or_default()
     }
 
-    /// Obtains resolution for a label with the given `NodeId`.
-    fn get_label_res(&self, id: NodeId) -> Option<NodeId> {
-        self.label_res_map.get(&id).copied()
-    }
-
-    /// Obtains resolution for a lifetime with the given `NodeId`.
-    fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
-        self.lifetimes_res_map.get(&id).copied()
-    }
-
     /// Obtain the list of lifetimes parameters to add to an item.
     ///
     /// Extra lifetime parameters should only be added in places that can appear
@@ -310,7 +300,7 @@ fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
     ///
     /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
     /// should appear at the enclosing `PolyTraitRef`.
-    fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] {
+    fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] {
         self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..])
     }
 
@@ -321,10 +311,6 @@ fn delegation_info(&self, id: LocalDefId) -> Option<&DelegationInfo> {
     fn owner_def_id(&self, id: NodeId) -> LocalDefId {
         self.owners[&id].def_id
     }
-
-    fn lifetime_elision_allowed(&self, id: NodeId) -> bool {
-        self.lifetime_elision_allowed.contains(&id)
-    }
 }
 
 /// How relaxed bounds `?Trait` should be treated.
@@ -542,7 +528,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
     let ast_index = index_crate(&resolver, &krate);
     let mut owners = IndexVec::from_fn_n(
         |_| hir::MaybeOwner::Phantom,
-        tcx.definitions_untracked().def_index_count(),
+        tcx.definitions_untracked().num_definitions(),
     );
 
     let mut lowerer = item::ItemLowerer {
@@ -948,43 +934,30 @@ fn lifetime_res_to_generic_param(
         &mut self,
         ident: Ident,
         node_id: NodeId,
-        res: LifetimeRes,
+        kind: MissingLifetimeKind,
         source: hir::GenericParamSource,
-    ) -> Option<hir::GenericParam<'hir>> {
-        let (name, kind) = match res {
-            LifetimeRes::Param { .. } => {
-                (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
-            }
-            LifetimeRes::Fresh { param, kind, .. } => {
-                // Late resolution delegates to us the creation of the `LocalDefId`.
-                let _def_id = self.create_def(
-                    param,
-                    Some(kw::UnderscoreLifetime),
-                    DefKind::LifetimeParam,
-                    ident.span,
-                );
-                debug!(?_def_id);
+    ) -> hir::GenericParam<'hir> {
+        // Late resolution delegates to us the creation of the `LocalDefId`.
+        let _def_id = self.create_def(
+            node_id,
+            Some(kw::UnderscoreLifetime),
+            DefKind::LifetimeParam,
+            ident.span,
+        );
+        debug!(?_def_id);
 
-                (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind))
-            }
-            LifetimeRes::Static { .. } | LifetimeRes::Error(..) => return None,
-            res => panic!(
-                "Unexpected lifetime resolution {:?} for {:?} at {:?}",
-                res, ident, ident.span
-            ),
-        };
         let hir_id = self.lower_node_id(node_id);
         let def_id = self.local_def_id(node_id);
-        Some(hir::GenericParam {
+        hir::GenericParam {
             hir_id,
             def_id,
-            name,
+            name: hir::ParamName::Fresh,
             span: self.lower_span(ident.span),
             pure_wrt_drop: false,
-            kind: hir::GenericParamKind::Lifetime { kind },
+            kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided(kind) },
             colon_span: None,
             source,
-        })
+        }
     }
 
     /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR
@@ -1005,7 +978,7 @@ fn lower_lifetime_binder(
         debug!(?extra_lifetimes);
         let extra_lifetimes: Vec<_> = extra_lifetimes
             .iter()
-            .filter_map(|&(ident, node_id, res)| {
+            .map(|&(ident, node_id, res)| {
                 self.lifetime_res_to_generic_param(
                     ident,
                     node_id,
@@ -1625,7 +1598,7 @@ fn lower_ty_direct_lifetime(
 
             None => {
                 let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
-                    self.resolver.get_lifetime_res(t.id)
+                    self.owner.get_lifetime_res(t.id)
                 {
                     assert_eq!(start.plus(1), end);
                     start
@@ -1866,7 +1839,9 @@ fn lower_fn_decl(
                     _ => hir::ImplicitSelfKind::None,
                 }
             }))
-            .set_lifetime_elision_allowed(self.resolver.lifetime_elision_allowed(fn_node_id))
+            .set_lifetime_elision_allowed(
+                self.owner.id == fn_node_id && self.owner.lifetime_elision_allowed,
+            )
             .set_c_variadic(c_variadic);
 
         self.arena.alloc(hir::FnDecl { inputs, output, fn_decl_kind })
@@ -2032,7 +2007,7 @@ fn new_named_lifetime(
         source: LifetimeSource,
         syntax: LifetimeSyntax,
     ) -> &'hir hir::Lifetime {
-        let res = if let Some(res) = self.resolver.get_lifetime_res(id) {
+        let res = if let Some(res) = self.owner.get_lifetime_res(id) {
             match res {
                 LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),
                 LifetimeRes::Fresh { param, .. } => {
@@ -2118,13 +2093,12 @@ fn lower_generic_param_kind(
                 // AST resolution emitted an error on those parameters, so we lower them using
                 // `ParamName::Error`.
                 let ident = self.lower_ident(param.ident);
-                let param_name = if let Some(LifetimeRes::Error(..)) =
-                    self.resolver.get_lifetime_res(param.id)
-                {
-                    ParamName::Error(ident)
-                } else {
-                    ParamName::Plain(ident)
-                };
+                let param_name =
+                    if let Some(LifetimeRes::Error(..)) = self.owner.get_lifetime_res(param.id) {
+                        ParamName::Error(ident)
+                    } else {
+                        ParamName::Plain(ident)
+                    };
                 let kind =
                     hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
 
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index ef60dc6..f5a306a 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -17,7 +17,7 @@
 };
 use super::{
     AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
-    LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
+    LifetimeRes, LoweringContext, ParamMode,
 };
 
 impl<'hir> LoweringContext<'_, 'hir> {
@@ -422,7 +422,7 @@ fn maybe_insert_elided_lifetimes_in_path(
         segment_ident_span: Span,
         generic_args: &mut GenericArgsCtor<'hir>,
     ) {
-        let (start, end) = match self.resolver.get_lifetime_res(segment_id) {
+        let (start, end) = match self.owner.get_lifetime_res(segment_id) {
             Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),
             None => return,
             Some(res) => {
diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
index e72533f..05e1557 100644
--- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
@@ -91,7 +91,7 @@ fn parse_unstable(
 
     for param in list.mixed() {
         let param_span = param.span();
-        if let Some(ident) = param.meta_item().and_then(|i| i.path().word()) {
+        if let Some(ident) = param.meta_item_no_args().and_then(|i| i.path().word()) {
             res.push(ident.name);
         } else {
             cx.emit_err(session_diagnostics::ExpectsFeatures {
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 41abb48..94cc2cf 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -26,7 +26,7 @@ impl SingleAttributeParser for OptimizeParser {
     fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
         let single = cx.expect_single_element_list(args, cx.attr_span)?;
 
-        let res = match single.meta_item().and_then(|i| i.path().word().map(|i| i.name)) {
+        let res = match single.meta_item_no_args().and_then(|i| i.path().word().map(|i| i.name)) {
             Some(sym::size) => OptimizeAttr::Size,
             Some(sym::speed) => OptimizeAttr::Speed,
             Some(sym::none) => OptimizeAttr::DoNotOptimize,
@@ -80,7 +80,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
         let mut fail_incorrect_argument =
             |span| cx.adcx().expected_specific_argument(span, &[sym::on, sym::off]);
 
-        let Some(arg) = arg.meta_item() else {
+        let Some(arg) = arg.meta_item_no_args() else {
             fail_incorrect_argument(arg.span());
             return None;
         };
@@ -373,7 +373,7 @@ impl AttributeParser for UsedParser {
                         return;
                     };
 
-                    match l.meta_item().and_then(|i| i.path().word_sym()) {
+                    match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
                         Some(sym::compiler) => {
                             if !cx.features().used_with_arg() {
                                 feature_err(
diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
index 3b6dd7a..e0adbb0 100644
--- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
@@ -1,3 +1,4 @@
+use rustc_ast::LitKind;
 use rustc_hir::attrs::{DeprecatedSince, Deprecation};
 use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER};
 
@@ -76,6 +77,38 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
                 // ok
             }
             ArgParser::List(list) => {
+                // If the argument list contains a single string literal:
+                // check whether it may be a version and suggest since field
+                // otherwise, suggest using NameValue syntax
+                if let Some(elem) = list.as_single()
+                    && let Some(lit) = elem.as_lit()
+                    && let LitKind::Str(text, _) = lit.kind
+                {
+                    let mut adcx = cx.adcx();
+
+                    match parse_since(text, true) {
+                        DeprecatedSince::Future | DeprecatedSince::RustcVersion(_) => {
+                            adcx.push_suggestion(
+                                String::from("try specifying a deprecated since version"),
+                                elem.span(),
+                                format!("since = {}", lit.kind),
+                            );
+                        }
+                        _ => {
+                            if let Some(span) = args.span() {
+                                adcx.push_suggestion(
+                                    String::from("try using `=` instead"),
+                                    span,
+                                    format!(" = {}", lit.kind),
+                                );
+                            }
+                        }
+                    };
+
+                    adcx.expected_not_literal(elem.span());
+                    return None;
+                }
+
                 for param in list.mixed() {
                     let Some(param) = param.meta_item() else {
                         cx.adcx().expected_not_literal(param.span());
@@ -133,18 +166,11 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
         }
 
         let since = if let Some(since) = since {
-            if since.as_str() == "TBD" {
-                DeprecatedSince::Future
-            } else if !is_rustc {
-                DeprecatedSince::NonStandard(since)
-            } else if since.as_str() == VERSION_PLACEHOLDER {
-                DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
-            } else if let Some(version) = parse_version(since) {
-                DeprecatedSince::RustcVersion(version)
-            } else {
+            let since = parse_since(since, is_rustc);
+            if matches!(since, DeprecatedSince::Err) {
                 cx.emit_err(InvalidSince { span: cx.attr_span });
-                DeprecatedSince::Err
             }
+            since
         } else if is_rustc {
             cx.emit_err(MissingSince { span: cx.attr_span });
             DeprecatedSince::Err
@@ -163,3 +189,17 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
         })
     }
 }
+
+fn parse_since(since: Symbol, is_rustc: bool) -> DeprecatedSince {
+    if since.as_str() == "TBD" {
+        DeprecatedSince::Future
+    } else if !is_rustc {
+        DeprecatedSince::NonStandard(since)
+    } else if since.as_str() == VERSION_PLACEHOLDER {
+        DeprecatedSince::RustcVersion(RustcVersion::CURRENT)
+    } else if let Some(version) = parse_version(since) {
+        DeprecatedSince::RustcVersion(version)
+    } else {
+        DeprecatedSince::Err
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
index e783e49..4379563 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
@@ -17,6 +17,7 @@ impl AttributeParser for OnConstParser {
         |this, cx, args| {
             if !cx.features().diagnostic_on_const() {
                 // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
+                args.ignore_args();
                 return;
             }
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
index b3c6c93..f08d983 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
@@ -20,6 +20,7 @@ impl OnMoveParser {
     fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser, mode: Mode) {
         if !cx.features().diagnostic_on_move() {
             // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
+            args.ignore_args();
             return;
         }
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
index 4c32780..43d2ead 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
@@ -18,6 +18,7 @@ fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser,
             && !features.diagnostic_on_unknown()
         {
             // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
+            args.ignore_args();
             return;
         }
         let span = cx.attr_span;
diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs
index 535f67f..f31af01 100644
--- a/compiler/rustc_attr_parsing/src/attributes/doc.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs
@@ -190,6 +190,8 @@ fn parse_single_test_doc_attr_item(
 
                 // FIXME: convert list into a Vec of `AttributeKind` because current code is awful.
                 for attr in list.mixed() {
+                    // Arguments of `attr` are checked via the span, so can be safely ignored
+                    attr.ignore_args();
                     self.attribute.test_attrs.push(attr.span());
                 }
             }
diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
index 622f7e1..ebf7272 100644
--- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
@@ -14,7 +14,8 @@ impl SingleAttributeParser for RustcDummyParser {
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
     const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
 
-    fn convert(_: &mut AcceptContext<'_, '_>, _: &ArgParser) -> Option<AttributeKind> {
+    fn convert(_: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
+        args.ignore_args();
         Some(AttributeKind::RustcDummy)
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index aee0537..9363ae2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -39,7 +39,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
             ArgParser::List(list) => {
                 let l = cx.expect_single(list)?;
 
-                match l.meta_item().and_then(|i| i.path().word_sym()) {
+                match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
                     Some(sym::always) => {
                         Some(AttributeKind::Inline(InlineAttr::Always, cx.attr_span))
                     }
diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
index 6f239a8..a42a77d 100644
--- a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
@@ -21,7 +21,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
         const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32];
         let maybe_meta_item = cx.expect_single_element_list(args, cx.attr_span)?;
 
-        let Some(meta_item) = maybe_meta_item.meta_item() else {
+        let Some(meta_item) = maybe_meta_item.meta_item_no_args() else {
             cx.adcx().expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS);
             return None;
         };
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index 067590d..ff0ab27 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -145,7 +145,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
                     cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
                     return None;
                 };
-                match l.meta_item().and_then(|i| i.path().word_sym()) {
+                match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
                     Some(sym::local_inner_macros) => true,
                     _ => {
                         cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
index 9b27dd3..ae0c167 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
@@ -6,7 +6,7 @@
 #[doc(hidden)]
 pub(super) use rustc_hir::{MethodKind, Target};
 #[doc(hidden)]
-pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
+pub(super) use rustc_span::{Ident, Span, Symbol, sym};
 #[doc(hidden)]
 pub(super) use thin_vec::ThinVec;
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 0ba32c6..e3d5ba8 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -1,18 +1,20 @@
 use rustc_abi::{Align, Size};
 use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
-use rustc_hir::attrs::{IntType, ReprAttr};
+use rustc_hir::attrs::IntType::{SignedInt, UnsignedInt};
+use rustc_hir::attrs::ReprAttr;
 
 use super::prelude::*;
-use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
+use crate::session_diagnostics;
 
 /// Parse #[repr(...)] forms.
 ///
-/// Valid repr contents: any of the primitive integral type names (see
-/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
-/// the same discriminant size that the corresponding C enum would or C
-/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
-/// concerns to the only non-ZST field.
-// FIXME(jdonszelmann): is a vec the right representation here even? isn't it just a struct?
+/// Valid repr contents:
+/// * any of the primitive integral type names to specify enum discriminant type
+/// * `Rust`, to use the default `Rust` layout of the type
+/// * `C`, to use the same layout for the type that C would use
+/// * `align(...)`, to change the alignment requirements of the type
+/// * `packed`, to remove padding
+/// * `transparent`, to delegate representation concerns to the only non-ZST field.
 pub(crate) struct ReprParser;
 
 impl CombineAttributeParser for ReprParser {
@@ -20,7 +22,6 @@ impl CombineAttributeParser for ReprParser {
     const PATH: &[Symbol] = &[sym::repr];
     const CONVERT: ConvertFn<Self::Item> =
         |items, first_span| AttributeKind::Repr { reprs: items, first_span };
-    // FIXME(jdonszelmann): never used
     const TEMPLATE: AttributeTemplate = template!(
         List: &["C", "Rust", "transparent", "align(...)", "packed(...)", "<integer type>"],
         "https://doc.rust-lang.org/reference/type-layout.html#representations"
@@ -30,29 +31,24 @@ fn extend(
         cx: &mut AcceptContext<'_, '_>,
         args: &ArgParser,
     ) -> impl IntoIterator<Item = Self::Item> {
-        let mut reprs = Vec::new();
-
         let Some(list) = cx.expect_list(args, cx.attr_span) else {
-            return reprs;
+            return vec![];
         };
 
         if list.is_empty() {
             let attr_span = cx.attr_span;
             cx.adcx().warn_empty_attribute(attr_span);
-            return reprs;
+            return vec![];
         }
 
+        let mut reprs = Vec::new();
         for param in list.mixed() {
-            if let Some(_) = param.as_lit() {
-                cx.emit_err(session_diagnostics::ReprIdent { span: cx.attr_span });
+            let Some(item) = param.meta_item() else {
+                cx.adcx().expected_identifier(param.span());
                 continue;
-            }
-
-            reprs.extend(
-                param.meta_item().and_then(|mi| parse_repr(cx, &mi)).map(|r| (r, param.span())),
-            );
+            };
+            reprs.extend(parse_repr(cx, &item).map(|r| (r, param.span())));
         }
-
         reprs
     }
 
@@ -61,122 +57,69 @@ fn extend(
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
 }
 
-macro_rules! int_pat {
-    () => {
-        sym::i8
-            | sym::u8
-            | sym::i16
-            | sym::u16
-            | sym::i32
-            | sym::u32
-            | sym::i64
-            | sym::u64
-            | sym::i128
-            | sym::u128
-            | sym::isize
-            | sym::usize
-    };
-}
-
-fn int_type_of_word(s: Symbol) -> Option<IntType> {
-    use IntType::*;
-
-    match s {
-        sym::i8 => Some(SignedInt(IntTy::I8)),
-        sym::u8 => Some(UnsignedInt(UintTy::U8)),
-        sym::i16 => Some(SignedInt(IntTy::I16)),
-        sym::u16 => Some(UnsignedInt(UintTy::U16)),
-        sym::i32 => Some(SignedInt(IntTy::I32)),
-        sym::u32 => Some(UnsignedInt(UintTy::U32)),
-        sym::i64 => Some(SignedInt(IntTy::I64)),
-        sym::u64 => Some(UnsignedInt(UintTy::U64)),
-        sym::i128 => Some(SignedInt(IntTy::I128)),
-        sym::u128 => Some(UnsignedInt(UintTy::U128)),
-        sym::isize => Some(SignedInt(IntTy::Isize)),
-        sym::usize => Some(UnsignedInt(UintTy::Usize)),
-        _ => None,
-    }
-}
-
-fn parse_repr(cx: &AcceptContext<'_, '_>, param: &MetaItemParser) -> Option<ReprAttr> {
+fn parse_repr(cx: &mut AcceptContext<'_, '_>, param: &MetaItemParser) -> Option<ReprAttr> {
     use ReprAttr::*;
 
-    // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
-    // structure.
-    let (name, ident_span) = if let Some(ident) = param.path().word() {
-        (Some(ident.name), ident.span)
-    } else {
-        (None, DUMMY_SP)
-    };
+    macro_rules! no_args {
+        ($constructor: expr) => {{
+            cx.expect_no_args(param.args())?;
+            Some($constructor)
+        }};
+    }
 
-    let args = param.args();
-
-    match (name, args) {
-        (Some(sym::align), ArgParser::NoArgs) => {
-            cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span });
-            None
+    match param.path().word_sym() {
+        Some(sym::align) => {
+            let l = cx.expect_list(param.args(), param.span())?;
+            parse_repr_align(cx, l, AlignKind::Align)
         }
-        (Some(sym::align), ArgParser::List(l)) => {
-            parse_repr_align(cx, l, param.span(), AlignKind::Align)
-        }
-
-        (Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)),
-        (Some(sym::packed), ArgParser::List(l)) => {
-            parse_repr_align(cx, l, param.span(), AlignKind::Packed)
-        }
-
-        (Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => {
-            cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
-                span: param.span(),
-                // FIXME(jdonszelmann) can just be a string in the diag type
-                repr_arg: name,
-                cause: IncorrectReprFormatGenericCause::from_lit_kind(
-                    param.span(),
-                    &l.value_as_lit().kind,
-                    name,
-                ),
-            });
-            None
-        }
-
-        (Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust),
-        (Some(sym::C), ArgParser::NoArgs) => Some(ReprC),
-        (Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd),
-        (Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent),
-        (Some(name @ int_pat!()), ArgParser::NoArgs) => {
-            // int_pat!() should make sure it always parses
-            Some(ReprInt(int_type_of_word(name).unwrap()))
-        }
-
-        (
-            Some(
-                name @ sym::Rust
-                | name @ sym::C
-                | name @ sym::simd
-                | name @ sym::transparent
-                | name @ int_pat!(),
-            ),
-            ArgParser::NameValue(_),
-        ) => {
-            cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name });
-            None
-        }
-        (
-            Some(
-                name @ sym::Rust
-                | name @ sym::C
-                | name @ sym::simd
-                | name @ sym::transparent
-                | name @ int_pat!(),
-            ),
-            ArgParser::List(_),
-        ) => {
-            cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name });
-            None
-        }
-
+        Some(sym::packed) => match param.args() {
+            ArgParser::NoArgs => Some(ReprPacked(Align::ONE)),
+            ArgParser::List(l) => parse_repr_align(cx, l, AlignKind::Packed),
+            ArgParser::NameValue(_) => {
+                cx.adcx().expected_list_or_no_args(param.span());
+                None
+            }
+        },
+        Some(sym::Rust) => no_args!(ReprRust),
+        Some(sym::C) => no_args!(ReprC),
+        Some(sym::simd) => no_args!(ReprSimd),
+        Some(sym::transparent) => no_args!(ReprTransparent),
+        Some(sym::i8) => no_args!(ReprInt(SignedInt(IntTy::I8))),
+        Some(sym::u8) => no_args!(ReprInt(UnsignedInt(UintTy::U8))),
+        Some(sym::i16) => no_args!(ReprInt(SignedInt(IntTy::I16))),
+        Some(sym::u16) => no_args!(ReprInt(UnsignedInt(UintTy::U16))),
+        Some(sym::i32) => no_args!(ReprInt(SignedInt(IntTy::I32))),
+        Some(sym::u32) => no_args!(ReprInt(UnsignedInt(UintTy::U32))),
+        Some(sym::i64) => no_args!(ReprInt(SignedInt(IntTy::I64))),
+        Some(sym::u64) => no_args!(ReprInt(UnsignedInt(UintTy::U64))),
+        Some(sym::i128) => no_args!(ReprInt(SignedInt(IntTy::I128))),
+        Some(sym::u128) => no_args!(ReprInt(UnsignedInt(UintTy::U128))),
+        Some(sym::isize) => no_args!(ReprInt(SignedInt(IntTy::Isize))),
+        Some(sym::usize) => no_args!(ReprInt(UnsignedInt(UintTy::Usize))),
         _ => {
-            cx.emit_err(session_diagnostics::UnrecognizedReprHint { span: param.span() });
+            cx.adcx().expected_specific_argument(
+                param.span(),
+                &[
+                    sym::align,
+                    sym::packed,
+                    sym::Rust,
+                    sym::C,
+                    sym::simd,
+                    sym::transparent,
+                    sym::i8,
+                    sym::u8,
+                    sym::i16,
+                    sym::u16,
+                    sym::i32,
+                    sym::u32,
+                    sym::i64,
+                    sym::u64,
+                    sym::i128,
+                    sym::u128,
+                    sym::isize,
+                    sym::usize,
+                ],
+            );
             None
         }
     }
@@ -188,44 +131,17 @@ enum AlignKind {
 }
 
 fn parse_repr_align(
-    cx: &AcceptContext<'_, '_>,
+    cx: &mut AcceptContext<'_, '_>,
     list: &MetaItemListParser,
-    param_span: Span,
     align_kind: AlignKind,
 ) -> Option<ReprAttr> {
-    use AlignKind::*;
-
     let Some(align) = list.as_single() else {
-        match align_kind {
-            Packed => {
-                cx.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
-                    span: param_span,
-                });
-            }
-            Align => {
-                cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
-                    span: param_span,
-                });
-            }
-        }
-
+        cx.adcx().expected_single_argument(list.span, list.len());
         return None;
     };
 
     let Some(lit) = align.as_lit() else {
-        match align_kind {
-            Packed => {
-                cx.emit_err(session_diagnostics::IncorrectReprFormatPackedExpectInteger {
-                    span: align.span(),
-                });
-            }
-            Align => {
-                cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger {
-                    span: align.span(),
-                });
-            }
-        }
-
+        cx.adcx().expected_integer_literal(align.span());
         return None;
     };
 
@@ -235,12 +151,8 @@ fn parse_repr_align(
             AlignKind::Align => ReprAttr::ReprAlign(literal),
         }),
         Err(message) => {
-            cx.emit_err(session_diagnostics::InvalidReprGeneric {
+            cx.emit_err(session_diagnostics::InvalidAlignmentValue {
                 span: lit.span,
-                repr_arg: match align_kind {
-                    Packed => "packed".to_string(),
-                    Align => "align".to_string(),
-                },
                 error_part: message,
             });
             None
@@ -294,10 +206,7 @@ fn parse(&mut self, cx: &mut AcceptContext<'_, '_>, args: &ArgParser) {
         };
 
         let Some(lit) = align.as_lit() else {
-            cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger {
-                span: align.span(),
-            });
-
+            cx.adcx().expected_integer_literal(align.span());
             return;
         };
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs
index 8d50706..4adbcbb 100644
--- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs
@@ -98,7 +98,7 @@ fn extend(
 
         let mut result = Vec::new();
         for item in items.mixed() {
-            let Some(arg) = item.meta_item() else {
+            let Some(arg) = item.meta_item_no_args() else {
                 cx.adcx().expected_not_literal(item.span());
                 continue;
             };
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
index 8a64855..3192f9c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
@@ -43,7 +43,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
 
         let mut errored = false;
         for argument in inputs {
-            let Some(meta) = argument.meta_item() else {
+            let Some(meta) = argument.meta_item_no_args() else {
                 cx.adcx().expected_identifier(argument.span());
                 return None;
             };
@@ -820,7 +820,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
             ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
             ArgParser::List(list) => {
                 let item = cx.expect_single(list)?;
-                let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
+                let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
                     cx.adcx().expected_identifier(item.span());
                     return None;
                 };
@@ -878,7 +878,7 @@ fn extend(
             cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
         }
         let item = cx.expect_single_element_list(args, cx.attr_span)?;
-        let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
+        let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
             cx.adcx().expected_identifier(item.span());
             return None;
         };
diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
index 7ffeb3d..eeee6ef 100644
--- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
@@ -123,7 +123,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<Attribute
         let mut fail_incorrect_argument =
             |span| cx.adcx().expected_specific_argument(span, &[sym::assert_eq, sym::debug]);
 
-        let Some(arg) = arg.meta_item() else {
+        let Some(arg) = arg.meta_item_no_args() else {
             fail_incorrect_argument(args.span);
             return None;
         };
@@ -173,7 +173,7 @@ impl SingleAttributeParser for TestRunnerParser {
     fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
         let single = cx.expect_single_element_list(args, cx.attr_span)?;
 
-        let Some(meta) = single.meta_item() else {
+        let Some(meta) = single.meta_item_no_args() else {
             cx.adcx().expected_not_literal(single.span());
             return None;
         };
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 750fe10..8da222e 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -4,6 +4,8 @@
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::sync::LazyLock;
+#[cfg(debug_assertions)]
+use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_ast::{AttrStyle, MetaItemLit, Safety};
 use rustc_data_structures::sync::{DynSend, DynSync};
@@ -405,6 +407,8 @@ fn emit_lint_inner(
         kind: EmitAttribute,
         span: impl Into<MultiSpan>,
     ) {
+        #[cfg(debug_assertions)]
+        self.has_lint_been_emitted.store(true, Ordering::Relaxed);
         if !matches!(
             self.should_emit,
             ShouldEmit::ErrorsAndLints { .. } | ShouldEmit::EarlyFatal { also_emit_lints: true }
@@ -744,6 +748,11 @@ pub struct SharedContext<'p, 'sess> {
     pub(crate) target: rustc_hir::Target,
 
     pub(crate) emit_lint: &'p mut dyn FnMut(LintId, MultiSpan, EmitAttribute),
+
+    /// This atomic bool keeps track of whether any lint has been emitted.
+    /// This is used for the arguments-used check.
+    #[cfg(debug_assertions)]
+    pub(crate) has_lint_been_emitted: AtomicBool,
 }
 
 /// Context given to every attribute parser during finalization.
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index 4a0ad63..7af0225 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -1,4 +1,6 @@
 use std::convert::identity;
+#[cfg(debug_assertions)]
+use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_ast as ast;
 use rustc_ast::token::DocFragmentKind;
@@ -228,6 +230,8 @@ pub fn parse_single_args<T, I>(
                 target_span,
                 target,
                 emit_lint: &mut emit_lint,
+                #[cfg(debug_assertions)]
+                has_lint_been_emitted: AtomicBool::new(false),
             },
             attr_span,
             inner_span,
@@ -285,11 +289,6 @@ pub fn parse_attribute_list(
         mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute),
     ) -> Vec<Attribute> {
         let mut attributes = Vec::new();
-        // We store the attributes we intend to discard at the end of this function in order to
-        // check they are applied to the right target and error out if necessary. In practice, we
-        // end up dropping only derive attributes and derive helpers, both being fully processed
-        // at macro expansion.
-        let mut dropped_attributes = Vec::new();
         let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
         let mut early_parsed_state = EarlyParsedState::default();
 
@@ -342,11 +341,12 @@ pub fn parse_attribute_list(
 
                     let parts =
                         n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
+                    let inner_span = lower_span(n.item.span());
 
                     if let Some(accept) = ATTRIBUTE_PARSERS.accepters.get(parts.as_slice()) {
                         self.check_attribute_safety(
                             &attr_path,
-                            lower_span(n.item.span()),
+                            inner_span,
                             n.item.unsafety,
                             accept.safety,
                             &mut emit_lint,
@@ -399,9 +399,11 @@ pub fn parse_attribute_list(
                                 target_span,
                                 target,
                                 emit_lint: &mut emit_lint,
+                                #[cfg(debug_assertions)]
+                                has_lint_been_emitted: AtomicBool::new(false),
                             },
                             attr_span,
-                            inner_span: lower_span(n.item.span()),
+                            inner_span,
                             attr_style: attr.style,
                             parsed_description: ParsedDescription::Attribute,
                             template: &accept.template,
@@ -412,8 +414,10 @@ pub fn parse_attribute_list(
                         (accept.accept_fn)(&mut cx, &args);
                         finalizers.push(accept.finalizer);
 
-                        if !matches!(cx.should_emit, ShouldEmit::Nothing) {
-                            Self::check_target(&accept.allowed_targets, target, &mut cx);
+                        Self::check_target(&accept.allowed_targets, &mut cx);
+                        #[cfg(debug_assertions)]
+                        if !cx.shared.has_lint_been_emitted.load(Ordering::Relaxed) {
+                            cx.shared.cx.check_args_used(&attr, &args)
                         }
                     } else {
                         let attr = AttrItem {
@@ -427,7 +431,7 @@ pub fn parse_attribute_list(
 
                         self.check_attribute_safety(
                             &attr_path,
-                            lower_span(n.item.span()),
+                            inner_span,
                             n.item.unsafety,
                             AttributeSafety::Normal,
                             &mut emit_lint,
@@ -436,23 +440,11 @@ pub fn parse_attribute_list(
                         if !matches!(self.should_emit, ShouldEmit::Nothing)
                             && target == Target::Crate
                         {
-                            self.check_invalid_crate_level_attr_item(&attr, n.item.span());
+                            self.check_invalid_crate_level_attr_item(&attr, inner_span);
                         }
 
-                        let attr = Attribute::Unparsed(Box::new(attr));
-
-                        if self.tools.is_some_and(|tools| {
-                            tools.iter().any(|tool| tool.name == parts[0])
-                            // FIXME: this can be removed once #152369 has been merged.
-                            // https://github.com/rust-lang/rust/pull/152369
-                            || [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn]
-                                .contains(&parts[0])
-                        }) {
-                            attributes.push(attr);
-                        } else {
-                            dropped_attributes.push(attr);
-                        }
-                    }
+                        attributes.push(Attribute::Unparsed(Box::new(attr)));
+                    };
                 }
             }
         }
@@ -460,7 +452,14 @@ pub fn parse_attribute_list(
         early_parsed_state.finalize_early_parsed_attributes(&mut attributes);
         for f in &finalizers {
             if let Some(attr) = f(&mut FinalizeContext {
-                shared: SharedContext { cx: self, target_span, target, emit_lint: &mut emit_lint },
+                shared: SharedContext {
+                    cx: self,
+                    target_span,
+                    target,
+                    emit_lint: &mut emit_lint,
+                    #[cfg(debug_assertions)]
+                    has_lint_been_emitted: AtomicBool::new(false),
+                },
                 all_attrs: &attr_paths,
             }) {
                 attributes.push(Attribute::Parsed(attr));
@@ -468,12 +467,32 @@ pub fn parse_attribute_list(
         }
 
         if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate {
-            self.check_invalid_where_predicate_attrs(attributes.iter().chain(&dropped_attributes));
+            self.check_invalid_where_predicate_attrs(attributes.iter());
         }
 
         attributes
     }
 
+    #[cfg(debug_assertions)]
+    /// Checks whether all `ArgParser`s were observed by an attribute parser at least once
+    /// This check exists because otherwise it is too easy to accidentally ignore the arguments of an attribute
+    fn check_args_used(&self, attr: &ast::Attribute, args: &ArgParser) {
+        if let ArgParser::List(items) = args {
+            for item in items.mixed() {
+                if let crate::parser::MetaItemOrLitParser::MetaItemParser(item) = item {
+                    if !item.are_args_checked() {
+                        self.dcx().span_delayed_bug(
+                            item.span(),
+                            "attribute args were not properly checked",
+                        );
+                        return;
+                    }
+                    self.check_args_used(attr, item.args());
+                }
+            }
+        }
+    }
+
     /// Returns whether there is a parser for an attribute with this name
     pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
         /// The list of attributes that are parsed attributes,
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 15a9eb9..8204008 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -5,6 +5,8 @@
 
 use std::borrow::Borrow;
 use std::fmt::{Debug, Display};
+#[cfg(debug_assertions)]
+use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_ast::token::{self, Delimiter, MetaVarKind};
 use rustc_ast::tokenstream::TokenStream;
@@ -87,7 +89,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 #[must_use]
 pub enum ArgParser {
     NoArgs,
@@ -209,13 +211,26 @@ pub fn as_no_args(&self) -> Result<(), Span> {
             Self::NameValue(args) => Err(args.args_span()),
         }
     }
+
+    /// Explicitly ignore the arguments, disarming the arguments-used check
+    pub fn ignore_args(&self) {
+        #[cfg(debug_assertions)]
+        match self {
+            ArgParser::List(list) => {
+                for item in list.mixed() {
+                    item.ignore_args();
+                }
+            }
+            _ => {}
+        }
+    }
 }
 
 /// Inside lists, values could be either literals, or more deeply nested meta items.
 /// This enum represents that.
 ///
 /// Choose which one you want using the provided methods.
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub enum MetaItemOrLitParser {
     MetaItemParser(MetaItemParser),
     Lit(MetaItemLit),
@@ -253,6 +268,26 @@ pub fn meta_item(&self) -> Option<&MetaItemParser> {
             MetaItemOrLitParser::Lit(_) => None,
         }
     }
+
+    /// Returns some if this `MetaItemOrLitParser` is a `MetaItem` with no arguments
+    pub fn meta_item_no_args(&self) -> Option<&MetaItemParser> {
+        let meta_item = self.meta_item()?;
+        match meta_item.args().as_no_args() {
+            Ok(_) => Some(meta_item),
+            Err(_) => None,
+        }
+    }
+
+    /// Explicitly ignore the arguments, disarming the arguments-used check
+    pub fn ignore_args(&self) {
+        #[cfg(debug_assertions)]
+        match self {
+            MetaItemOrLitParser::MetaItemParser(meta_item) => {
+                meta_item.ignore_args();
+            }
+            MetaItemOrLitParser::Lit(_) => {}
+        }
+    }
 }
 
 // FIXME(scrabsha): once #155696 is merged, update this and mention the higher-level APIs.
@@ -270,10 +305,14 @@ pub fn meta_item(&self) -> Option<&MetaItemParser> {
 ///   `= value` part
 ///
 /// The syntax of MetaItems can be found at <https://doc.rust-lang.org/reference/attributes.html>
-#[derive(Clone)]
 pub struct MetaItemParser {
     path: OwnedPathParser,
     args: ArgParser,
+
+    /// Whether the `args` of this meta item have been looked at.
+    /// This is tracked because if the arguments of a `MetaItemParser` are ignored, this is probably a mistake
+    #[cfg(debug_assertions)]
+    args_checked: AtomicBool,
 }
 
 impl Debug for MetaItemParser {
@@ -310,6 +349,8 @@ pub fn path(&self) -> &OwnedPathParser {
 
     /// Gets just the args parser, without caring about the path.
     pub fn args(&self) -> &ArgParser {
+        #[cfg(debug_assertions)]
+        self.args_checked.store(true, Ordering::Relaxed);
         &self.args
     }
 
@@ -322,6 +363,16 @@ pub fn args(&self) -> &ArgParser {
     pub fn word_is(&self, sym: Symbol) -> Option<&ArgParser> {
         self.path().word_is(sym).then(|| self.args())
     }
+
+    /// Explicitly ignore the arguments, disarming the arguments-used check
+    pub fn ignore_args(&self) {
+        self.args().ignore_args();
+    }
+
+    #[cfg(debug_assertions)]
+    pub fn are_args_checked(&self) -> bool {
+        self.args_checked.load(Ordering::Relaxed)
+    }
 }
 
 #[derive(Clone)]
@@ -545,7 +596,12 @@ fn parse_meta_item(&mut self) -> PResult<'sess, MetaItemParser> {
             ArgParser::NoArgs
         };
 
-        Ok(MetaItemParser { path: PathParser(path), args })
+        Ok(MetaItemParser {
+            path: PathParser(path),
+            args,
+            #[cfg(debug_assertions)]
+            args_checked: AtomicBool::new(false),
+        })
     }
 
     fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser> {
@@ -670,7 +726,7 @@ fn parse(
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub struct MetaItemListParser {
     sub_parsers: ThinVec<MetaItemOrLitParser>,
     pub span: Span,
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index ea5c907..9faf060 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -1,6 +1,5 @@
 use std::num::IntErrorKind;
 
-use rustc_ast as ast;
 use rustc_errors::codes::*;
 use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -183,126 +182,6 @@ pub(crate) struct MissingIssue {
     pub span: Span,
 }
 
-// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
-// It is more similar to `IncorrectReprFormatGeneric`.
-#[derive(Diagnostic)]
-#[diag("incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all", code = E0552)]
-pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
-    #[primary_span]
-    pub span: Span,
-}
-#[derive(Diagnostic)]
-#[diag("incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument", code = E0552)]
-pub(crate) struct IncorrectReprFormatPackedExpectInteger {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("invalid representation hint: `{$name}` does not take a parenthesized argument list", code = E0552)]
-pub(crate) struct InvalidReprHintNoParen {
-    #[primary_span]
-    pub span: Span,
-
-    pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag("invalid representation hint: `{$name}` does not take a value", code = E0552)]
-pub(crate) struct InvalidReprHintNoValue {
-    #[primary_span]
-    pub span: Span,
-
-    pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag("invalid `repr(align)` attribute: `align` needs an argument", code = E0589)]
-pub(crate) struct InvalidReprAlignNeedArg {
-    #[primary_span]
-    #[suggestion(
-        "supply an argument here",
-        code = "align(...)",
-        applicability = "has-placeholders"
-    )]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)]
-pub(crate) struct InvalidReprGeneric {
-    #[primary_span]
-    pub span: Span,
-
-    pub repr_arg: String,
-    pub error_part: String,
-}
-
-#[derive(Diagnostic)]
-#[diag("incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses", code = E0693)]
-pub(crate) struct IncorrectReprFormatAlignOneArg {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("incorrect `repr(align)` attribute format: `align` expects a literal integer as argument", code = E0693)]
-pub(crate) struct IncorrectReprFormatExpectInteger {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("incorrect `repr({$repr_arg})` attribute format", code = E0693)]
-pub(crate) struct IncorrectReprFormatGeneric {
-    #[primary_span]
-    pub span: Span,
-
-    pub repr_arg: Symbol,
-
-    #[subdiagnostic]
-    pub cause: Option<IncorrectReprFormatGenericCause>,
-}
-
-#[derive(Subdiagnostic)]
-pub(crate) enum IncorrectReprFormatGenericCause {
-    #[suggestion(
-        "use parentheses instead",
-        code = "{name}({value})",
-        applicability = "machine-applicable"
-    )]
-    Int {
-        #[primary_span]
-        span: Span,
-        name: Symbol,
-        value: u128,
-    },
-
-    #[suggestion(
-        "use parentheses instead",
-        code = "{name}({value})",
-        applicability = "machine-applicable"
-    )]
-    Symbol {
-        #[primary_span]
-        span: Span,
-        name: Symbol,
-        value: Symbol,
-    },
-}
-
-impl IncorrectReprFormatGenericCause {
-    pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option<Self> {
-        match *kind {
-            ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => {
-                Some(Self::Int { span, name, value: value.get() })
-            }
-            ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }),
-            _ => None,
-        }
-    }
-}
-
 #[derive(Diagnostic)]
 #[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)]
 pub(crate) struct RustcPromotablePairing {
@@ -485,26 +364,6 @@ pub(crate) struct InvalidAlignmentValue {
 }
 
 #[derive(Diagnostic)]
-#[diag("meta item in `repr` must be an identifier", code = E0565)]
-pub(crate) struct ReprIdent {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("unrecognized representation hint", code = E0552)]
-#[help(
-    "valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`"
-)]
-#[note(
-    "for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>"
-)]
-pub(crate) struct UnrecognizedReprHint {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag("item annotated with `#[unstable_feature_bound]` should not be stable")]
 #[help(
     "if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`"
@@ -849,6 +708,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
             }
             AttributeParseErrorReason::ExpectedIdentifier => {
                 diag.span_label(self.span, "expected a valid identifier here");
+                diag.code(E0565);
             }
         }
 
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index fe4d72b..db86504 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -7,7 +7,6 @@
 use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
 use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym};
 
-use crate::AttributeParser;
 use crate::context::AcceptContext;
 use crate::errors::{
     InvalidAttrAtCrateLevel, InvalidTargetLint, ItemFollowingInnerAttr,
@@ -15,6 +14,7 @@
 };
 use crate::session_diagnostics::InvalidTarget;
 use crate::target_checking::Policy::Allow;
+use crate::{AttributeParser, ShouldEmit};
 
 #[derive(Debug)]
 pub(crate) enum AllowedTargets {
@@ -90,17 +90,20 @@ pub(crate) enum Policy {
 impl<'sess> AttributeParser<'sess> {
     pub(crate) fn check_target(
         allowed_targets: &AllowedTargets,
-        target: Target,
         cx: &mut AcceptContext<'_, 'sess>,
     ) {
-        // For crate-level attributes we emit a specific set of lints to warn
-        // people about accidentally not using them on the crate.
-        if let &AllowedTargets::AllowList(&[Allow(Target::Crate)]) = allowed_targets {
-            Self::check_crate_level(target, cx);
+        if matches!(cx.should_emit, ShouldEmit::Nothing) {
             return;
         }
 
-        if matches!(cx.attr_path.segments.as_ref(), [sym::repr]) && target == Target::Crate {
+        // For crate-level attributes we emit a specific set of lints to warn
+        // people about accidentally not using them on the crate.
+        if let &AllowedTargets::AllowList(&[Allow(Target::Crate)]) = allowed_targets {
+            Self::check_crate_level(cx);
+            return;
+        }
+
+        if matches!(cx.attr_path.segments.as_ref(), [sym::repr]) && cx.target == Target::Crate {
             // The allowed targets of `repr` depend on its arguments. They can't be checked using
             // the `AttributeParser` code.
             let span = cx.attr_span;
@@ -119,11 +122,12 @@ pub(crate) fn check_target(
                 .emit();
         }
 
-        match allowed_targets.is_allowed(target) {
+        match allowed_targets.is_allowed(cx.target) {
             AllowedResult::Allowed => {}
             AllowedResult::Warn => {
                 let allowed_targets = allowed_targets.allowed_targets();
-                let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+                let (applied, only) =
+                    allowed_targets_applied(allowed_targets, cx.target, cx.features);
                 let name = cx.attr_path.clone();
 
                 let lint = if name.segments[0] == sym::deprecated
@@ -134,7 +138,7 @@ pub(crate) fn check_target(
                         Target::Arm,
                         Target::MacroCall,
                     ]
-                    .contains(&target)
+                    .contains(&cx.target)
                 {
                     rustc_session::lint::builtin::USELESS_DEPRECATED
                 } else {
@@ -142,6 +146,7 @@ pub(crate) fn check_target(
                 };
 
                 let attr_span = cx.attr_span;
+                let target = cx.target;
                 cx.emit_lint_with_sess(
                     lint,
                     move |dcx, level, _| {
@@ -161,12 +166,13 @@ pub(crate) fn check_target(
             }
             AllowedResult::Error => {
                 let allowed_targets = allowed_targets.allowed_targets();
-                let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+                let (applied, only) =
+                    allowed_targets_applied(allowed_targets, cx.target, cx.features);
                 let name = cx.attr_path.clone();
                 cx.dcx().emit_err(InvalidTarget {
                     span: cx.attr_span.clone(),
                     name,
-                    target: target.plural_name(),
+                    target: cx.target.plural_name(),
                     only: if only { "only " } else { "" },
                     applied: DiagArgValue::StrListSepByAnd(
                         applied.into_iter().map(Cow::Owned).collect(),
@@ -176,8 +182,8 @@ pub(crate) fn check_target(
         }
     }
 
-    pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess>) {
-        if target == Target::Crate {
+    pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>) {
+        if cx.target == Target::Crate {
             return;
         }
 
@@ -200,6 +206,7 @@ pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess
             })
             .unwrap_or_default();
 
+        let target = cx.target;
         cx.emit_lint(
             rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
             crate::errors::InvalidAttrStyle {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 9a64a063..993f04f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -4023,7 +4023,7 @@ pub(crate) fn report_illegal_reassignment(
             && decl.can_be_made_mutable()
         {
             let mut is_for_loop = false;
-            let mut is_ref_pattern = false;
+            let mut is_immut_ref_pattern = false;
             if let LocalInfo::User(BindingForm::Var(VarBindingForm {
                 opt_match_place: Some((_, match_span)),
                 ..
@@ -4031,55 +4031,52 @@ pub(crate) fn report_illegal_reassignment(
             {
                 if matches!(match_span.desugaring_kind(), Some(DesugaringKind::ForLoop)) {
                     is_for_loop = true;
+                }
 
-                    if let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(self.mir_def_id()) {
-                        struct RefPatternFinder<'tcx> {
-                            tcx: TyCtxt<'tcx>,
-                            binding_span: Span,
-                            is_ref_pattern: bool,
-                        }
-
-                        impl<'tcx> Visitor<'tcx> for RefPatternFinder<'tcx> {
-                            type NestedFilter = OnlyBodies;
-
-                            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-                                self.tcx
-                            }
-
-                            fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
-                                if !self.is_ref_pattern
-                                    && let hir::PatKind::Binding(_, _, ident, _) = pat.kind
-                                    && ident.span == self.binding_span
-                                {
-                                    self.is_ref_pattern =
-                                        self.tcx.hir_parent_iter(pat.hir_id).any(|(_, node)| {
-                                            matches!(
-                                                node,
-                                                hir::Node::Pat(hir::Pat {
-                                                    kind: hir::PatKind::Ref(..),
-                                                    ..
-                                                })
-                                            )
-                                        });
-                                }
-                                hir::intravisit::walk_pat(self, pat);
-                            }
-                        }
-
-                        let mut finder = RefPatternFinder {
-                            tcx: self.infcx.tcx,
-                            binding_span: decl.source_info.span,
-                            is_ref_pattern: false,
-                        };
-
-                        finder.visit_body(body);
-                        is_ref_pattern = finder.is_ref_pattern;
+                if let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(self.mir_def_id()) {
+                    struct RefPatternFinder<'tcx> {
+                        tcx: TyCtxt<'tcx>,
+                        binding_span: Span,
+                        is_immut_ref_pattern: bool,
                     }
+
+                    impl<'tcx> Visitor<'tcx> for RefPatternFinder<'tcx> {
+                        type NestedFilter = OnlyBodies;
+
+                        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                            self.tcx
+                        }
+
+                        fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
+                            if !self.is_immut_ref_pattern
+                                && let hir::PatKind::Binding(_, _, ident, _) = pat.kind
+                                && ident.span == self.binding_span
+                                && matches!(
+                                    self.tcx.parent_hir_node(pat.hir_id),
+                                    hir::Node::Pat(hir::Pat {
+                                        kind: hir::PatKind::Ref(_, _, hir::Mutability::Not),
+                                        ..
+                                    })
+                                )
+                            {
+                                self.is_immut_ref_pattern = true;
+                            }
+                            hir::intravisit::walk_pat(self, pat);
+                        }
+                    }
+
+                    let mut finder = RefPatternFinder {
+                        tcx: self.infcx.tcx,
+                        binding_span: decl.source_info.span,
+                        is_immut_ref_pattern: false,
+                    };
+
+                    finder.visit_body(body);
+                    is_immut_ref_pattern = finder.is_immut_ref_pattern;
                 }
             }
 
-            let (span, message) = if is_for_loop
-                && is_ref_pattern
+            let (span, message) = if is_immut_ref_pattern
                 && let Ok(binding_name) =
                     self.infcx.tcx.sess.source_map().span_to_snippet(decl.source_info.span)
             {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index e80969c..ae2f622 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -881,14 +881,7 @@ fn visit_after_early_terminator_effect(
             TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(loc, (discr, span), state);
             }
-            TerminatorKind::Drop {
-                place,
-                target: _,
-                unwind: _,
-                replace,
-                drop: _,
-                async_fut: _,
-            } => {
+            TerminatorKind::Drop { place, target: _, unwind: _, replace, drop: _ } => {
                 debug!(
                     "visit_terminator_drop \
                      loc: {:?} term: {:?} place: {:?} span: {:?}",
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
index 5a33b2d..9edf710 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
@@ -97,14 +97,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
             TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(location, discr);
             }
-            TerminatorKind::Drop {
-                place: drop_place,
-                target: _,
-                unwind: _,
-                replace,
-                drop: _,
-                async_fut: _,
-            } => {
+            TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace, drop: _ } => {
                 let write_kind =
                     if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
                 self.access_place(
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 13983f3..b1cf754 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1760,9 +1760,11 @@ fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Locat
             let tcx = self.tcx();
             let maybe_uneval = match constant.const_ {
                 Const::Ty(_, ct) => match ct.kind() {
-                    ty::ConstKind::Unevaluated(uv) => {
-                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
-                    }
+                    ty::ConstKind::Unevaluated(uv) => Some(UnevaluatedConst {
+                        def: uv.kind.def_id(),
+                        args: uv.args,
+                        promoted: None,
+                    }),
                     _ => None,
                 },
                 Const::Unevaluated(uv, _) => Some(uv),
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index d5d577d..9e29262 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -42,6 +42,7 @@
 mod global_allocator;
 mod iter;
 mod log_syntax;
+mod offload;
 mod pattern_type;
 mod source_util;
 mod test;
@@ -116,6 +117,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         eii_declaration: eii::eii_declaration,
         eii_shared_macro: eii::eii_shared_macro,
         global_allocator: global_allocator::expand,
+        offload_kernel: offload::expand_kernel,
         test: test::expand_test,
         test_case: test::expand_test_case,
         unsafe_eii: eii::unsafe_eii,
diff --git a/compiler/rustc_builtin_macros/src/offload.rs b/compiler/rustc_builtin_macros/src/offload.rs
new file mode 100644
index 0000000..9dbd2d4
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/offload.rs
@@ -0,0 +1,205 @@
+use rustc_ast::token::{Delimiter, Token, TokenKind};
+use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::{AttrItem, ast};
+use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_session::config::Offload;
+use rustc_span::{Ident, Span, sym};
+use thin_vec::thin_vec;
+
+use crate::errors;
+
+fn compile_for_device(ecx: &mut ExtCtxt<'_>) -> bool {
+    ecx.sess.opts.unstable_opts.offload.contains(&Offload::Device)
+}
+
+fn outer_normal_attr(
+    kind: &Box<rustc_ast::NormalAttr>,
+    id: rustc_ast::AttrId,
+    span: Span,
+) -> rustc_ast::Attribute {
+    let style = rustc_ast::AttrStyle::Outer;
+    let kind = rustc_ast::AttrKind::Normal(kind.clone());
+    rustc_ast::Attribute { kind, id, style, span }
+}
+
+fn extract_fn(
+    item: &Annotatable,
+) -> Option<(ast::Visibility, ast::FnSig, Ident, ast::Generics, Option<Box<ast::Block>>)> {
+    match item {
+        Annotatable::Item(iitem) => match &iitem.kind {
+            ast::ItemKind::Fn(ast::Fn { sig, ident, generics, body, .. }) => {
+                Some((iitem.vis.clone(), sig.clone(), *ident, generics.clone(), body.clone()))
+            }
+            _ => None,
+        },
+        _ => None,
+    }
+}
+
+/// The `offload_kernel` macro expands the function into two separate definitions:
+/// one on the host to handle the call, and one on the device for executing the kernel.
+///
+/// ```
+/// #[offload_kernel]
+/// fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+///     *c = a[0] + b[0];
+/// }
+/// ```
+///
+/// This expands to the host-side function:
+///
+/// ```
+/// #[unsafe(no_mangle)]
+/// #[inline(never)]
+/// fn foo(_: &[f32], _: &[f32], _: *mut f32) {
+///     ::core::panicking::panic("not implemented")
+/// }
+/// ```
+///
+/// And the device-side kernel:
+///
+/// ```
+/// #[rustc_offload_kernel]
+/// #[unsafe(no_mangle)]
+/// unsafe extern "gpu-kernel" fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+///     *c = a[0] + b[0];
+/// }
+/// ```
+pub(crate) fn expand_kernel(
+    ecx: &mut ExtCtxt<'_>,
+    expand_span: Span,
+    _meta_item: &ast::MetaItem,
+    item: Annotatable,
+) -> Vec<Annotatable> {
+    let dcx = ecx.sess.dcx();
+
+    let Some((vis, sig, ident, generics, body)) = extract_fn(&item) else {
+        dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
+        return vec![item];
+    };
+
+    let span = ecx.with_def_site_ctxt(expand_span);
+
+    // device function
+    let mut device_fn = Box::new(ast::Fn {
+        defaultness: ast::Defaultness::Implicit,
+        sig: sig.clone(),
+        ident,
+        generics: generics.clone(),
+        contract: None,
+        body,
+        define_opaque: None,
+        eii_impls: Default::default(),
+    });
+
+    let extern_gpu_kernel = ast::Extern::from_abi(
+        Some(ast::StrLit {
+            symbol: sym::gpu_kernel,
+            suffix: None,
+            symbol_unescaped: sym::gpu_kernel,
+            style: ast::StrStyle::Cooked,
+            span,
+        }),
+        span,
+    );
+    device_fn.sig.header.ext = extern_gpu_kernel;
+    device_fn.sig.header.safety = ast::Safety::Unsafe(span);
+
+    // rustc_offload_kernel attr
+    let rustc_offload_kernel_attr =
+        Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_offload_kernel)));
+    let rustc_offload_kernel = outer_normal_attr(
+        &rustc_offload_kernel_attr,
+        ecx.sess.psess.attr_id_generator.mk_attr_id(),
+        span,
+    );
+
+    // unsafe(no_mangle) attr
+    let unsafe_item = AttrItem {
+        unsafety: ast::Safety::Unsafe(span),
+        path: ast::Path::from_ident(Ident::new(sym::no_mangle, span)),
+        args: ast::AttrItemKind::Unparsed(ast::AttrArgs::Empty),
+        tokens: None,
+    };
+
+    let no_mangle_attr = Box::new(ast::NormalAttr { item: unsafe_item, tokens: None });
+    let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
+    let unsafe_no_mangle = outer_normal_attr(&no_mangle_attr, new_id, span);
+
+    let device_item = {
+        let mut item = ecx.item(
+            span,
+            thin_vec![rustc_offload_kernel, unsafe_no_mangle],
+            ast::ItemKind::Fn(device_fn),
+        );
+        item.vis = vis.clone();
+        Annotatable::Item(item)
+    };
+
+    // unimplemented! body
+    let macro_expr = ecx.expr_macro_call(
+        span,
+        ecx.macro_call(
+            span,
+            ecx.path_global(
+                span,
+                [sym::std, sym::unimplemented].map(|s| Ident::new(s, span)).to_vec(),
+            ),
+            Delimiter::Parenthesis,
+            TokenStream::default(),
+        ),
+    );
+    let stmt = ecx.stmt_expr(macro_expr);
+    let body = ecx.block(span, thin_vec![stmt]);
+
+    // host function
+    let mut host_fn = Box::new(ast::Fn {
+        defaultness: ast::Defaultness::Implicit,
+        sig: sig.clone(),
+        ident,
+        generics: generics.clone(),
+        contract: None,
+        body: Some(body),
+        define_opaque: None,
+        eii_impls: Default::default(),
+    });
+
+    for param in host_fn.sig.decl.inputs.iter_mut() {
+        param.pat = Box::new(ecx.pat_wild(param.pat.span));
+    }
+
+    // inline(never) attr
+    let ts: Vec<TokenTree> = vec![TokenTree::Token(
+        Token::new(TokenKind::Ident(sym::never, false.into()), span),
+        Spacing::Joint,
+    )];
+
+    let never_arg = ast::DelimArgs {
+        dspan: DelimSpan::from_single(span),
+        delim: Delimiter::Parenthesis,
+        tokens: TokenStream::from_iter(ts),
+    };
+
+    let inline_item = ast::AttrItem {
+        unsafety: ast::Safety::Default,
+        path: ast::Path::from_ident(Ident::with_dummy_span(sym::inline)),
+        args: rustc_ast::ast::AttrItemKind::Unparsed(ast::AttrArgs::Delimited(never_arg)),
+        tokens: None,
+    };
+    let inline_never_attr = Box::new(ast::NormalAttr { item: inline_item, tokens: None });
+
+    let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
+    let inline_never = outer_normal_attr(&inline_never_attr, new_id, span);
+
+    let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
+    let unsafe_no_mangle = outer_normal_attr(&no_mangle_attr, new_id, span);
+
+    let host_item = {
+        let mut item =
+            ecx.item(span, thin_vec![unsafe_no_mangle, inline_never], ast::ItemKind::Fn(host_fn));
+        item.vis = vis.clone();
+        Annotatable::Item(item)
+    };
+
+    if compile_for_device(ecx) { vec![device_item] } else { vec![host_item] }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
index 0283263..edbee60 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
@@ -44,9 +44,9 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar
 
 fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[(Size, AbiParam); 2]> {
     if let Some(offset_from_start) = cast.rest_offset {
-        assert!(cast.prefix[1..].iter().all(|p| p.is_none()));
+        assert_eq!(cast.prefix.len(), 1);
         assert_eq!(cast.rest.unit.size, cast.rest.total);
-        let first = cast.prefix[0].unwrap();
+        let first = cast.prefix[0];
         let second = cast.rest.unit;
         return smallvec![
             (Size::ZERO, reg_to_abi_param(first)),
@@ -71,7 +71,6 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar
     let args = cast
         .prefix
         .iter()
-        .flatten()
         .map(|&reg| reg_to_abi_param(reg))
         .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit)));
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 1d90c8e..2edbdb5 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -582,9 +582,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
             | TerminatorKind::CoroutineDrop => {
                 bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
             }
-            TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
+            TerminatorKind::Drop { place, target, unwind, replace: _, drop } => {
                 assert!(
-                    async_fut.is_none() && drop.is_none(),
+                    drop.is_none(),
                     "Async Drop must be expanded or reset to sync before codegen"
                 );
                 let drop_place = codegen_place(fx, *place);
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index a08b0e0..8818e86 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -55,7 +55,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
             if variant_index != untagged_variant {
                 let niche = place.place_field(fx, tag_field);
                 let niche_type = fx.clif_type(niche.layout().ty).unwrap();
-                let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+                let niche_value = variant_index.as_u32() - niche_variants.start.as_u32();
                 let niche_value = (niche_value as u128).wrapping_add(niche_start);
                 let niche_value = match niche_type {
                     types::I128 => {
@@ -133,7 +133,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             dest.write_cvalue(fx, res);
         }
         TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
-            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+            let relative_max = niche_variants.last.as_u32() - niche_variants.start.as_u32();
 
             // We have a subrange `niche_start..=niche_end` inside `range`.
             // If the value of the tag is inside this subrange, it's a
@@ -162,7 +162,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                 // }
                 let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
                 let tagged_discr =
-                    fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
+                    fx.bcx.ins().iconst(cast_to, niche_variants.start.as_u32() as i64);
                 (is_niche, tagged_discr, 0)
             } else {
                 // The special cases don't apply, so we'll have to go with
@@ -184,7 +184,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                     relative_discr,
                     i128::from(relative_max),
                 );
-                (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
+                (is_niche, cast_tag, niche_variants.start.as_u32() as u128)
             };
 
             let tagged_discr = if delta == 0 {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 3781ad7..323fec0 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -35,8 +35,7 @@ fn disable_incr_cache() -> bool {
 }
 
 struct ModuleCodegenResult {
-    module_regular: CompiledModule,
-    module_global_asm: Option<CompiledModule>,
+    module: CompiledModule,
     existing_work_product: Option<(WorkProductId, WorkProduct)>,
 }
 
@@ -80,29 +79,25 @@ pub(crate) fn join(
                 Ok(module_codegen_result) => module_codegen_result,
                 Err(err) => sess.dcx().fatal(err),
             };
-            let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } =
-                module_codegen_result;
+            let ModuleCodegenResult { module, existing_work_product } = module_codegen_result;
 
             if let Some((work_product_id, work_product)) = existing_work_product {
                 work_products.insert(work_product_id, work_product);
             } else {
                 let work_product = if disable_incr_cache {
                     None
-                } else if let Some(module_global_asm) = &module_global_asm {
+                } else if let Some(global_asm_object) = &module.global_asm_object {
                     rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
                         sess,
-                        &module_regular.name,
-                        &[
-                            ("o", module_regular.object.as_ref().unwrap()),
-                            ("asm.o", module_global_asm.object.as_ref().unwrap()),
-                        ],
+                        &module.name,
+                        &[("o", module.object.as_ref().unwrap()), ("asm.o", global_asm_object)],
                         &[],
                     )
                 } else {
                     rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
                         sess,
-                        &module_regular.name,
-                        &[("o", module_regular.object.as_ref().unwrap())],
+                        &module.name,
+                        &[("o", module.object.as_ref().unwrap())],
                         &[],
                     )
                 };
@@ -111,10 +106,7 @@ pub(crate) fn join(
                 }
             }
 
-            modules.push(module_regular);
-            if let Some(module_global_asm) = module_global_asm {
-                modules.push(module_global_asm);
-            }
+            modules.push(module);
         }
 
         self.concurrency_limiter.finished();
@@ -163,29 +155,17 @@ fn emit_cgu(
         debug.emit(&mut product);
     }
 
-    let module_regular = emit_module(
+    let module = emit_module(
         output_filenames,
         prof,
         product.object,
         ModuleKind::Regular,
         name.clone(),
+        global_asm_object_file,
         producer,
     )?;
 
-    Ok(ModuleCodegenResult {
-        module_regular,
-        module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule {
-            name: format!("{name}.asm"),
-            kind: ModuleKind::Regular,
-            object: Some(global_asm_object_file),
-            dwarf_object: None,
-            bytecode: None,
-            assembly: None,
-            llvm_ir: None,
-            links_from_incr_cache: Vec::new(),
-        }),
-        existing_work_product: None,
-    })
+    Ok(ModuleCodegenResult { module, existing_work_product: None })
 }
 
 fn emit_module(
@@ -194,6 +174,7 @@ fn emit_module(
     mut object: cranelift_object::object::write::Object<'_>,
     kind: ModuleKind,
     name: String,
+    global_asm_object: Option<PathBuf>,
     producer_str: &str,
 ) -> Result<CompiledModule, String> {
     if object.format() == cranelift_object::object::BinaryFormat::Elf {
@@ -235,6 +216,7 @@ fn emit_module(
         name,
         kind,
         object: Some(tmp_file),
+        global_asm_object,
         dwarf_object: None,
         bytecode: None,
         assembly: None,
@@ -265,7 +247,7 @@ fn reuse_workproduct_for_cgu(
     }
 
     let obj_out_global_asm =
-        crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm");
+        tcx.output_filenames(()).temp_path_ext_for_cgu("asm.o", cgu.name().as_str());
     let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") {
         let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(tcx.sess, asm_o);
         if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm)
@@ -283,26 +265,21 @@ fn reuse_workproduct_for_cgu(
     };
 
     Ok(ModuleCodegenResult {
-        module_regular: CompiledModule {
+        module: CompiledModule {
             name: cgu.name().to_string(),
             kind: ModuleKind::Regular,
             object: Some(obj_out_regular),
+            global_asm_object: source_file_global_asm.as_ref().map(|_| obj_out_global_asm),
             dwarf_object: None,
             bytecode: None,
             assembly: None,
             llvm_ir: None,
-            links_from_incr_cache: vec![source_file_regular],
+            links_from_incr_cache: if let Some(source_file_global_asm) = source_file_global_asm {
+                vec![source_file_regular, source_file_global_asm]
+            } else {
+                vec![source_file_regular]
+            },
         },
-        module_global_asm: source_file_global_asm.map(|source_file| CompiledModule {
-            name: cgu.name().to_string(),
-            kind: ModuleKind::Regular,
-            object: Some(obj_out_global_asm),
-            dwarf_object: None,
-            bytecode: None,
-            assembly: None,
-            llvm_ir: None,
-            links_from_incr_cache: vec![source_file],
-        }),
         existing_work_product: Some((cgu.work_product_id(), work_product)),
     })
 }
@@ -447,6 +424,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
             product.object,
             ModuleKind::Allocator,
             "allocator_shim".to_owned(),
+            None,
             &crate::debuginfo::producer(tcx.sess),
         ) {
             Ok(allocator_module) => Some(allocator_module),
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 0c5f413..ee7e673 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -12,7 +12,7 @@
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
 };
-use rustc_session::config::{OutputFilenames, OutputType};
+use rustc_session::config::OutputFilenames;
 use rustc_target::asm::InlineAsmArch;
 
 use crate::prelude::*;
@@ -198,10 +198,7 @@ pub(crate) fn compile_global_asm(
         .join("\n");
     global_asm.push('\n');
 
-    let global_asm_object_file = add_file_stem_postfix(
-        config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name),
-        ".asm",
-    );
+    let global_asm_object_file = config.output_filenames.temp_path_ext_for_cgu("asm.o", cgu_name);
 
     // Assemble `global_asm`
     if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
@@ -271,14 +268,3 @@ pub(crate) fn compile_global_asm(
 
     Ok(Some(global_asm_object_file))
 }
-
-pub(crate) fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf {
-    let mut new_filename = path.file_stem().unwrap().to_owned();
-    new_filename.push(postfix);
-    if let Some(extension) = path.extension() {
-        new_filename.push(".");
-        new_filename.push(extension);
-    }
-    path.set_file_name(new_filename);
-    path
-}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 3f02df8..2475a3a 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -886,8 +886,6 @@ fn valid_ui_error_pattern_test(file: &str) -> bool {
         "type-alias-impl-trait/auxiliary/cross_crate_ice.rs",
         "type-alias-impl-trait/auxiliary/cross_crate_ice2.rs",
         "macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs",
-        "imports/ambiguous-1.rs",
-        "imports/ambiguous-4-extern.rs",
         "entry-point/auxiliary/bad_main_functions.rs",
     ]
     .iter()
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 7239a5b..fb243ff 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -46,7 +46,7 @@ fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
             )
         };
 
-        if self.prefix.iter().all(|x| x.is_none()) {
+        if self.prefix.is_empty() {
             // Simplify to a single unit when there is no prefix and size <= unit size
             if self.rest.total <= self.rest.unit.size {
                 return rest_gcc_unit;
@@ -62,7 +62,7 @@ fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
         let mut args: Vec<_> = self
             .prefix
             .iter()
-            .flat_map(|option_reg| option_reg.map(|reg| reg.gcc_type(cx)))
+            .map(|reg| reg.gcc_type(cx))
             .chain((0..rest_count).map(|_| rest_gcc_unit))
             .collect();
 
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index c3bf566..718322a 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -187,7 +187,7 @@ fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
 
         // Simplify to a single unit or an array if there's no prefix.
         // This produces the same layout, but using a simpler type.
-        if self.prefix.iter().all(|x| x.is_none()) {
+        if self.prefix.is_empty() {
             // We can't do this if is_consecutive is set and the unit would get
             // split on the target. Currently, this is only relevant for i128
             // registers.
@@ -199,8 +199,7 @@ fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         }
 
         // Generate a struct type with the prefix and the "rest" arguments.
-        let prefix_args =
-            self.prefix.iter().flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx)));
+        let prefix_args = self.prefix.iter().map(|reg| reg.llvm_type(cx));
         let rest_args = (0..rest_count).map(|_| rest_ll_unit);
         let args: Vec<_> = prefix_args.chain(rest_args).collect();
         cx.type_struct(&args, false)
diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
index 73822eb..0b00932 100644
--- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
@@ -319,25 +319,26 @@ fn new<'ll, 'tcx>(
         geps: [&'ll Value; 3],
         workgroup_dims: &'ll Value,
         thread_dims: &'ll Value,
-    ) -> [(Align, &'ll Value); 13] {
+        dyn_cache: &'ll Value,
+    ) -> [(Align, &'ll str, &'ll Value); 13] {
         let four = Align::from_bytes(4).expect("4 Byte alignment should work");
         let eight = Align::EIGHT;
 
         [
-            (four, cx.get_const_i32(KernelArgsTy::OFFLOAD_VERSION)),
-            (four, cx.get_const_i32(num_args)),
-            (eight, geps[0]),
-            (eight, geps[1]),
-            (eight, geps[2]),
-            (eight, memtransfer_types),
+            (four, "Version", cx.get_const_i32(KernelArgsTy::OFFLOAD_VERSION)),
+            (four, "NumArgs", cx.get_const_i32(num_args)),
+            (eight, "ArgBasePtrs", geps[0]),
+            (eight, "ArgPtrs", geps[1]),
+            (eight, "ArgSizes", geps[2]),
+            (eight, "ArgTypes", memtransfer_types),
             // The next two are debug infos. FIXME(offload): set them
-            (eight, cx.const_null(cx.type_ptr())), // dbg
-            (eight, cx.const_null(cx.type_ptr())), // dbg
-            (eight, cx.get_const_i64(KernelArgsTy::TRIPCOUNT)),
-            (eight, cx.get_const_i64(KernelArgsTy::FLAGS)),
-            (four, workgroup_dims),
-            (four, thread_dims),
-            (four, cx.get_const_i32(0)),
+            (eight, "ArgNames", cx.const_null(cx.type_ptr())), // dbg
+            (eight, "ArgMappers", cx.const_null(cx.type_ptr())), // dbg
+            (eight, "Tripcount", cx.get_const_i64(KernelArgsTy::TRIPCOUNT)),
+            (eight, "Flags", cx.get_const_i64(KernelArgsTy::FLAGS)),
+            (four, "NumTeams", workgroup_dims),
+            (four, "ThreadLimit", thread_dims),
+            (four, "DynCGroupMem", dyn_cache),
         ]
     }
 }
@@ -589,6 +590,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>(
     metadata: &[OffloadMetadata],
     offload_globals: &OffloadGlobals<'ll>,
     offload_dims: &OffloadKernelDims<'ll>,
+    dyn_cache: &'ll Value,
 ) {
     let cx = builder.cx;
     let OffloadKernelGlobals {
@@ -753,14 +755,24 @@ fn generate_mapper_call<'ll, 'tcx>(
         num_args,
         s_ident_t,
     );
-    let values =
-        KernelArgsTy::new(&cx, num_args, memtransfer_kernel, geps, workgroup_dims, thread_dims);
+    let values = KernelArgsTy::new(
+        &cx,
+        num_args,
+        memtransfer_kernel,
+        geps,
+        workgroup_dims,
+        thread_dims,
+        dyn_cache,
+    );
 
     // Step 3)
     // Here we fill the KernelArgsTy, see the documentation above
     for (i, value) in values.iter().enumerate() {
         let ptr = builder.inbounds_gep(tgt_kernel_decl, a5, &[i32_0, cx.get_const_i32(i as u64)]);
-        builder.store(value.1, ptr, value.0);
+        let name = std::ffi::CString::new(value.1).unwrap();
+        llvm::set_value_name(ptr, &name.as_bytes());
+
+        builder.store(value.2, ptr, value.0);
     }
 
     let args = vec![
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 3514fb1..ab3e4b8 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -206,6 +206,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
             })
         });
         llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
+        llvm::set_unnamed_address(g2, llvm::UnnamedAddr::Global);
         llvm::set_initializer(g2, g1);
         g2
     } else if cx.tcx.sess.target.arch == Arch::X86
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index f7fe0eb..86060f0 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -426,7 +426,7 @@ fn compute_discriminant_value<'ll, 'tcx>(
                 DiscrResult::Range(min, max)
             } else {
                 let value = (variant_index.as_u32() as u128)
-                    .wrapping_sub(niche_variants.start().as_u32() as u128)
+                    .wrapping_sub(niche_variants.start.as_u32() as u128)
                     .wrapping_add(niche_start);
                 let value = tag.size(cx).truncate(value);
                 DiscrResult::Value(value)
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a400fcb..1c7b415 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1926,7 +1926,11 @@ fn codegen_offload<'ll, 'tcx>(
     };
 
     let offload_dims = OffloadKernelDims::from_operands(bx, &args[1], &args[2]);
-    let args = get_args_from_tuple(bx, args[3], fn_target);
+    let dyn_cache = match args[3].val {
+        OperandValue::Immediate(val) => val,
+        _ => panic!("unparsable"),
+    };
+    let args = get_args_from_tuple(bx, args[4], fn_target);
     let target_symbol = symbol_name_for_instance_in_crate(tcx, fn_target, LOCAL_CRATE);
 
     let sig = tcx.fn_sig(fn_target.def_id()).skip_binder();
@@ -1958,7 +1962,16 @@ fn codegen_offload<'ll, 'tcx>(
     };
     register_offload(cx);
     let offload_data = gen_define_handling(&cx, &metadata, target_symbol, offload_globals);
-    gen_call_handling(bx, &offload_data, &args, &types, &metadata, offload_globals, &offload_dims);
+    gen_call_handling(
+        bx,
+        &offload_data,
+        &args,
+        &types,
+        &metadata,
+        offload_globals,
+        &offload_dims,
+        &dyn_cache,
+    );
 }
 
 fn get_args_from_tuple<'ll, 'tcx>(
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index d2c8228..d54f914 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -98,8 +98,13 @@ pub fn link_binary(
         }
 
         sess.time("link_binary_check_files_are_writeable", || {
-            for obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) {
-                check_file_is_writeable(obj, sess);
+            for m in &compiled_modules.modules {
+                if let Some(obj) = &m.object {
+                    check_file_is_writeable(obj, sess);
+                }
+                if let Some(obj) = &m.global_asm_object {
+                    check_file_is_writeable(obj, sess);
+                }
             }
         });
 
@@ -202,6 +207,10 @@ pub fn link_binary(
                     ensure_removed(sess.dcx(), obj);
                 }
 
+                if !preserve_objects && let Some(ref obj) = module.global_asm_object {
+                    ensure_removed(sess.dcx(), obj);
+                }
+
                 if !preserve_dwarf_objects && let Some(ref dwo_obj) = module.dwarf_object {
                     ensure_removed(sess.dcx(), dwo_obj);
                 }
@@ -307,6 +316,7 @@ fn link_rlib<'a>(
         .modules
         .iter()
         .filter_map(|m| m.object.as_ref())
+        .chain(compiled_modules.modules.iter().filter_map(|m| m.global_asm_object.as_ref()))
         .map(|obj| obj.file_name().unwrap().to_str().unwrap().to_string())
         .collect();
 
@@ -352,6 +362,10 @@ fn link_rlib<'a>(
             ab.add_file(obj);
         }
 
+        if let Some(obj) = m.global_asm_object.as_ref() {
+            ab.add_file(obj);
+        }
+
         if let Some(dwarf_obj) = m.dwarf_object.as_ref() {
             ab.add_file(dwarf_obj);
         }
@@ -360,9 +374,13 @@ fn link_rlib<'a>(
     match flavor {
         RlibFlavor::Normal => {}
         RlibFlavor::StaticlibBase => {
-            let obj = compiled_modules.allocator_module.as_ref().and_then(|m| m.object.as_ref());
-            if let Some(obj) = obj {
-                ab.add_file(obj);
+            if let Some(m) = &compiled_modules.allocator_module {
+                if let Some(obj) = &m.object {
+                    ab.add_file(obj);
+                }
+                if let Some(obj) = &m.global_asm_object {
+                    ab.add_file(obj);
+                }
             }
         }
     }
@@ -632,8 +650,13 @@ fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
         // Input objs contain .o/.dwo files from the current crate.
         match sess.opts.unstable_opts.split_dwarf_kind {
             SplitDwarfKind::Single => {
-                for input_obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) {
-                    package.add_input_object(input_obj)?;
+                for m in &compiled_modules.modules {
+                    if let Some(input_obj) = &m.object {
+                        package.add_input_object(input_obj)?;
+                    }
+                    if let Some(input_obj) = &m.global_asm_object {
+                        package.add_input_object(input_obj)?;
+                    }
                 }
             }
             SplitDwarfKind::Split => {
@@ -1530,7 +1553,6 @@ fn infer_from(
                     }
                     LinkerFlavor::Bpf => "bpf-linker",
                     LinkerFlavor::Llbc => "llvm-bitcode-linker",
-                    LinkerFlavor::Ptx => "rust-ptx-linker",
                 }),
                 flavor,
             )),
@@ -1571,7 +1593,6 @@ fn adjust_flavor_to_features(
     let linker_flavor = match sess.opts.cg.linker_flavor {
         // The linker flavors that are non-target specific can be directly translated to LinkerFlavor
         Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc),
-        Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx),
         // The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor
         linker_flavor => {
             linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor))
@@ -2243,8 +2264,13 @@ fn add_linked_symbol_object(
 
 /// Add object files containing code from the current crate.
 fn add_local_crate_regular_objects(cmd: &mut dyn Linker, compiled_modules: &CompiledModules) {
-    for obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) {
-        cmd.add_object(obj);
+    for m in &compiled_modules.modules {
+        if let Some(obj) = &m.object {
+            cmd.add_object(obj);
+        }
+        if let Some(obj) = &m.global_asm_object {
+            cmd.add_object(obj);
+        }
     }
 }
 
@@ -2255,10 +2281,13 @@ fn add_local_crate_allocator_objects(
     crate_info: &CrateInfo,
     crate_type: CrateType,
 ) {
-    if needs_allocator_shim_for_linking(&crate_info.dependency_formats, crate_type) {
-        if let Some(obj) =
-            compiled_modules.allocator_module.as_ref().and_then(|m| m.object.as_ref())
-        {
+    if needs_allocator_shim_for_linking(&crate_info.dependency_formats, crate_type)
+        && let Some(m) = &compiled_modules.allocator_module
+    {
+        if let Some(obj) = &m.object {
+            cmd.add_object(obj);
+        }
+        if let Some(obj) = &m.global_asm_object {
             cmd.add_object(obj);
         }
     }
@@ -2764,8 +2793,6 @@ fn add_order_independent_options(
         if crate_info.target_features.len() > 0 {
             cmd.link_arg(&format!("--target-feature={}", &crate_info.target_features.join(",")));
         }
-    } else if flavor == LinkerFlavor::Ptx {
-        cmd.link_args(&["--fallback-arch", &crate_info.target_cpu]);
     } else if flavor == LinkerFlavor::Bpf {
         cmd.link_args(&["--cpu", &crate_info.target_cpu]);
         if let Some(feat) = [sess.opts.cg.target_feature.as_str(), &sess.target.options.features]
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 2155f94..d40340e 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -161,7 +161,6 @@ pub(crate) fn get_linker<'a>(
         LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box<dyn Linker>,
-        LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
     }
 }
 
@@ -283,7 +282,6 @@ pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
     L4Bender<'_>
     AixLinker<'_>
     LlbcLinker<'_>
-    PtxLinker<'_>
     BpfLinker<'_>
     dyn Linker + '_
 }
@@ -1920,83 +1918,6 @@ pub(crate) fn linked_symbols(
     symbols
 }
 
-/// Much simplified and explicit CLI for the NVPTX linker. The linker operates
-/// with bitcode and uses LLVM backend to generate a PTX assembly.
-struct PtxLinker<'a> {
-    cmd: Command,
-    sess: &'a Session,
-}
-
-impl<'a> Linker for PtxLinker<'a> {
-    fn cmd(&mut self) -> &mut Command {
-        &mut self.cmd
-    }
-
-    fn set_output_kind(
-        &mut self,
-        _output_kind: LinkOutputKind,
-        _crate_type: CrateType,
-        _out_filename: &Path,
-    ) {
-    }
-
-    fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
-        panic!("staticlibs not supported")
-    }
-
-    fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
-        self.link_arg("--rlib").link_arg(path);
-    }
-
-    fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
-        self.link_arg("--debug");
-    }
-
-    fn add_object(&mut self, path: &Path) {
-        self.link_arg("--bitcode").link_arg(path);
-    }
-
-    fn optimize(&mut self) {
-        match self.sess.lto() {
-            Lto::Thin | Lto::Fat | Lto::ThinLocal => {
-                self.link_arg("-Olto");
-            }
-
-            Lto::No => {}
-        }
-    }
-
-    fn full_relro(&mut self) {}
-
-    fn partial_relro(&mut self) {}
-
-    fn no_relro(&mut self) {}
-
-    fn gc_sections(&mut self, _keep_metadata: bool) {}
-
-    fn pgo_gen(&mut self) {}
-
-    fn no_crt_objects(&mut self) {}
-
-    fn no_default_libraries(&mut self) {}
-
-    fn control_flow_guard(&mut self) {}
-
-    fn ehcont_guard(&mut self) {}
-
-    fn export_symbols(
-        &mut self,
-        _tmpdir: &Path,
-        _crate_type: CrateType,
-        _symbols: &[(String, SymbolExportKind)],
-    ) {
-    }
-
-    fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
-
-    fn linker_plugin_lto(&mut self) {}
-}
-
 /// The `self-contained` LLVM bitcode linker
 struct LlbcLinker<'a> {
     cmd: Command,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 96c6320..38bde97 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -180,7 +180,7 @@ macro_rules! if_regular {
             ),
             pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None),
             pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
-            debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
+            debug_info_for_profiling: sess.opts.unstable_opts.debuginfo_for_profiling,
             instrument_coverage: if_regular!(sess.instrument_coverage(), false),
 
             sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()),
@@ -474,6 +474,9 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
         if let Some(object_file_path) = &module.object {
             files.push((OutputType::Object.extension(), object_file_path.as_path()));
         }
+        if let Some(global_asm_object_file_path) = &module.global_asm_object {
+            files.push(("asm.o", global_asm_object_file_path.as_path()));
+        }
         if let Some(dwarf_object_file_path) = &module.dwarf_object {
             files.push(("dwo", dwarf_object_file_path.as_path()));
         }
@@ -620,6 +623,10 @@ pub fn produce_final_output_artifacts(
                     ensure_removed(sess.dcx(), path);
                 }
 
+                if let Some(ref path) = module.global_asm_object {
+                    ensure_removed(sess.dcx(), path);
+                }
+
                 if let Some(ref path) = module.dwarf_object {
                     ensure_removed(sess.dcx(), path);
                 }
@@ -924,6 +931,13 @@ fn execute_copy_from_cache_work_item(
     let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
     let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
     let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
+    let global_asm_object =
+        if should_emit_obj && let Some(saved_file) = module.source.saved_files.get("asm.o") {
+            let output_path = cgcx.output_filenames.temp_path_ext_for_cgu("asm.o", &module.name);
+            load_from_incr_comp_dir(output_path, &saved_file)
+        } else {
+            None
+        };
     if should_emit_obj && object.is_none() {
         dcx.emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
     }
@@ -933,6 +947,7 @@ fn execute_copy_from_cache_work_item(
         kind: ModuleKind::Regular,
         name: module.name,
         object,
+        global_asm_object,
         dwarf_object,
         bytecode,
         assembly,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index c7446bd..560cbe9 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -109,6 +109,7 @@ pub fn into_compiled_module(
             name: self.name,
             kind: self.kind,
             object,
+            global_asm_object: None,
             dwarf_object,
             bytecode,
             assembly,
@@ -123,6 +124,7 @@ pub struct CompiledModule {
     pub name: String,
     pub kind: ModuleKind,
     pub object: Option<PathBuf>,
+    pub global_asm_object: Option<PathBuf>,
     pub dwarf_object: Option<PathBuf>,
     pub bytecode: Option<PathBuf>,
     pub assembly: Option<PathBuf>, // --emit=asm
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index b6b95c5..045595f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1585,9 +1585,9 @@ fn codegen_terminator(
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
+            mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop } => {
                 assert!(
-                    async_fut.is_none() && drop.is_none(),
+                    drop.is_none(),
                     "Async Drop must be expanded or reset to sync before codegen"
                 );
                 self.codegen_drop_terminator(
@@ -1737,7 +1737,8 @@ fn codegen_argument(
                     op.store_with_annotation(bx, scratch);
                     (scratch.val.llval, scratch.val.align, true)
                 }
-                _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false),
+                PassMode::Direct(_) => (op.immediate(), arg.layout.align.abi, false),
+                PassMode::Ignore | PassMode::Pair(..) => unreachable!("handled above"),
             },
             Ref(op_place_val) => match arg.mode {
                 PassMode::Indirect { attrs, on_stack, .. } => {
@@ -2233,9 +2234,9 @@ fn load_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 ) -> Bx::Value {
     let cast_ty = bx.cast_backend_type(cast);
     if let Some(offset_from_start) = cast.rest_offset {
-        assert!(cast.prefix[1..].iter().all(|p| p.is_none()));
+        assert_eq!(cast.prefix.len(), 1);
         assert_eq!(cast.rest.unit.size, cast.rest.total);
-        let first_ty = bx.reg_backend_type(&cast.prefix[0].unwrap());
+        let first_ty = bx.reg_backend_type(&cast.prefix[0]);
         let second_ty = bx.reg_backend_type(&cast.rest.unit);
         let first = bx.load(first_ty, ptr, align);
         let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes()));
@@ -2256,9 +2257,8 @@ pub fn store_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     align: Align,
 ) {
     if let Some(offset_from_start) = cast.rest_offset {
-        assert!(cast.prefix[1..].iter().all(|p| p.is_none()));
+        assert_eq!(cast.prefix.len(), 1);
         assert_eq!(cast.rest.unit.size, cast.rest.total);
-        assert!(cast.prefix[0].is_some());
         let first = bx.extract_value(value, 0);
         let second = bx.extract_value(value, 1);
         bx.store(first, ptr, align);
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index abdac4c..d4747c1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -38,8 +38,9 @@ fn eval_unevaluated_mir_constant_to_valtree(
         &self,
         constant: &mir::ConstOperand<'tcx>,
     ) -> Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled> {
+        let tcx = self.cx.tcx();
         let uv = match self.monomorphize(constant.const_) {
-            mir::Const::Unevaluated(uv, _) => uv.shrink(),
+            mir::Const::Unevaluated(uv, _) => uv.shrink(tcx),
             mir::Const::Ty(_, c) => match c.kind() {
                 // A constant that came from a const generic but was then used as an argument to
                 // old-style simd_shuffle (passing as argument instead of as a generic param).
@@ -57,7 +58,7 @@ fn eval_unevaluated_mir_constant_to_valtree(
             other => span_bug!(constant.span, "{other:#?}"),
         };
         let uv = self.monomorphize(uv);
-        self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span)
+        tcx.const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span)
     }
 
     /// process constant containing SIMD shuffle indices & constant vectors
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 4bcf037..0abdef8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -499,9 +499,12 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                     PassMode::Direct(_) => {
                         let llarg = bx.get_param(llarg_idx);
                         llarg_idx += 1;
-                        return local(OperandRef::from_immediate_or_packed_pair(
-                            bx, llarg, arg.layout,
-                        ));
+                        debug_assert!(bx.is_backend_immediate(arg.layout));
+                        return local(OperandRef {
+                            val: OperandValue::Immediate(llarg),
+                            layout: arg.layout,
+                            move_annotation: None,
+                        });
                     }
                     PassMode::Pair(..) => {
                         let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1));
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index bdeface..32a74d7 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -451,7 +451,7 @@ fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_t
         PassMode::Cast { pad_i32, ref cast } => {
             // For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);`
             assert!(!pad_i32, "not currently used by wasm calling convention");
-            assert!(cast.prefix[0].is_none(), "no prefix");
+            assert!(cast.prefix.is_empty(), "no prefix");
             assert_eq!(cast.rest.total, arg_abi.layout.size, "single item");
 
             let wrapped_wasm_type = match cast.rest.unit.kind {
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 83fce5a..68a84eb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -306,6 +306,9 @@ pub fn store_with_annotation<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
 
     /// If this operand is a `Pair`, we return an aggregate with the two values.
     /// For other cases, see `immediate`.
+    ///
+    /// Note: The use of this is discouraged outside cg_llvm, as some other backends
+    /// don't natively support packing multiple things into one like this.
     pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         self,
         bx: &mut Bx,
@@ -324,6 +327,9 @@ pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
     }
 
     /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`.
+    ///
+    /// Note: The use of this is discouraged outside cg_llvm, as some other backends
+    /// don't natively support packing multiple things into one like this.
     pub fn from_immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         llval: V,
@@ -494,7 +500,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                 // `layout_sanity_check` ensures that we only get here for cases where the discriminant
                 // value and the variant index match, since that's all `Niche` can encode.
 
-                let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+                let relative_max = niche_variants.last.as_u32() - niche_variants.start.as_u32();
                 let niche_start_const = bx.cx().const_uint_big(tag_llty, niche_start);
 
                 // We have a subrange `niche_start..=niche_end` inside `range`.
@@ -523,7 +529,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                     // }
                     let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start_const);
                     let tagged_discr =
-                        bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64);
+                        bx.cx().const_uint(cast_to, niche_variants.start.as_u32() as u64);
                     (is_niche, tagged_discr, 0)
                 } else {
                     // Thanks to parameter attributes and load metadata, LLVM already knows
@@ -549,7 +555,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                     {
                         let impossible = niche_start
                             .wrapping_add(u128::from(untagged_variant.as_u32()))
-                            .wrapping_sub(u128::from(niche_variants.start().as_u32()));
+                            .wrapping_sub(u128::from(niche_variants.start.as_u32()));
                         let impossible = bx.cx().const_uint_big(tag_llty, impossible);
                         let ne = bx.icmp(IntPredicate::IntNE, tag, impossible);
                         bx.assume(ne);
@@ -633,7 +639,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                         )
                     };
 
-                    (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
+                    (is_niche, cast_tag, niche_variants.start.as_u32() as u128)
                 };
 
                 let tagged_discr = if delta == 0 {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 53518fd..ebc993f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -500,7 +500,7 @@ pub(super) fn codegen_tag_value<'tcx, V>(
                 // around the `niche`'s type.
                 // The easiest way to do that is to do wrapping arithmetic on `u128` and then
                 // masking off any extra bits that occur because we did the arithmetic with too many bits.
-                let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+                let niche_value = variant_index.as_u32() - niche_variants.start.as_u32();
                 let niche_value = (niche_value as u128).wrapping_add(niche_start);
                 let niche_value = niche_value & niche_layout.size.unsigned_int_max();
 
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 6aa88b8..40ba31d3 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -272,8 +272,7 @@ fn pass_argument<'x, 'y>(
         caller_args: &mut impl Iterator<
             Item = (&'x FnArg<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>),
         >,
-        callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
-        callee_arg_idx: usize,
+        callee_args_abis: &mut impl Iterator<Item = (usize, &'y ArgAbi<'tcx, Ty<'tcx>>)>,
         callee_arg: &mir::Place<'tcx>,
         callee_ty: Ty<'tcx>,
         already_live: bool,
@@ -282,15 +281,10 @@ fn pass_argument<'x, 'y>(
         'tcx: 'x,
         'tcx: 'y,
     {
+        // Get next callee arg.
+        let (callee_arg_idx, callee_abi) = callee_args_abis.next().unwrap();
         assert_eq!(callee_ty, callee_abi.layout.ty);
-        if callee_abi.is_ignore() {
-            // This one is skipped. Still must be made live though!
-            if !already_live {
-                self.storage_live(callee_arg.as_local().unwrap())?;
-            }
-            return interp_ok(());
-        }
-        // Find next caller arg.
+        // Get next caller arg.
         let Some((caller_arg, caller_abi)) = caller_args.next() else {
             throw_ub_format!("calling a function with fewer arguments than it requires");
         };
@@ -348,6 +342,7 @@ pub fn init_stack_frame(
         mut cont: ReturnContinuation,
     ) -> InterpResult<'tcx> {
         let _trace = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty);
+        let def_id = instance.def_id();
 
         // The first order of business is to figure out the callee signature.
         // However, that requires the list of variadic arguments.
@@ -423,10 +418,25 @@ pub fn init_stack_frame(
             "spread_arg: {:?}, locals: {:#?}",
             body.spread_arg,
             body.args_iter()
-                .map(|local| (local, self.layout_of_local(self.frame(), local, None).unwrap().ty,))
+                .map(|local| (local, self.layout_of_local(self.frame(), local, None).unwrap().ty))
                 .collect::<Vec<_>>()
         );
 
+        // Determine whether there is a special VaList argument. This is always the
+        // last argument, and since arguments start at index 1 that's `arg_count`.
+        let va_list_arg = callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count));
+        // Determine whether this is a non-capturing closure. That's relevant as their first
+        // argument can be skipped (and that's the only kind of argument skipping we allow).
+        let is_non_capturing_closure =
+            (matches!(instance.def, ty::InstanceKind::ClosureOnceShim { .. })
+                || self.tcx.is_closure_like(def_id))
+                && {
+                    let arg = &callee_fn_abi.args[0];
+                    matches!(arg.layout.ty.kind(), ty::Closure (_def, closure_args) if {
+                        closure_args.as_closure().upvar_tys().is_empty()
+                    })
+                };
+
         // In principle, we have two iterators: Where the arguments come from, and where
         // they go to.
 
@@ -439,21 +449,13 @@ pub fn init_stack_frame(
             caller_fn_abi.args.len(),
             "mismatch between caller ABI and caller arguments",
         );
-        let mut caller_args = args
-            .iter()
-            .zip(caller_fn_abi.args.iter())
-            .filter(|arg_and_abi| !arg_and_abi.1.is_ignore());
+        let mut caller_args = args.iter().zip(caller_fn_abi.args.iter());
 
         // Now we have to spread them out across the callee's locals,
         // taking into account the `spread_arg`. If we could write
         // this is a single iterator (that handles `spread_arg`), then
-        // `pass_argument` would be the loop body. It takes care to
-        // not advance `caller_iter` for ignored arguments.
+        // `pass_argument` would be the loop body.
         let mut callee_args_abis = callee_fn_abi.args.iter().enumerate();
-        // Determine whether there is a special VaList argument. This is always the
-        // last argument, and since arguments start at index 1 that's `arg_count`.
-        let va_list_arg = callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count));
-
         // During argument passing, we want retagging with protectors.
         M::with_retag_mode(self, RetagMode::FnEntry, |ecx| {
             for local in body.args_iter() {
@@ -466,7 +468,32 @@ pub fn init_stack_frame(
                 // type, but the result gets cached so this avoids calling the instantiation
                 // query *again* the next time this local is accessed.
                 let ty = ecx.layout_of_local(ecx.frame(), local, None)?.ty;
-                if Some(local) == va_list_arg {
+
+                // Some arguments are special: the first (`self`) argument of a non-capturing
+                // closure; the va_list argument; and the spread_arg.
+                if is_non_capturing_closure && local == mir::Local::arg(0) {
+                    assert!(va_list_arg.is_none());
+                    assert!(Some(local) != body.spread_arg);
+                    // This argument might be missing on the caller side. So just initialize it in
+                    // the callee.
+                    let (callee_arg_idx, callee_abi) = callee_args_abis.next().unwrap();
+                    assert!(callee_abi.layout.is_1zst() && callee_abi.is_ignore());
+                    ecx.storage_live(local)?;
+                    // And skip it in the caller, if present. We can tell whether it is present by
+                    // comparing the number of arguments on the caller and callee side.
+                    if caller_fn_abi.args.len() == callee_fn_abi.args.len() {
+                        let (_caller_arg, caller_abi) = caller_args.next().unwrap();
+                        if !caller_abi.layout.is_1zst() {
+                            // The caller gave us some other, non-ignorable argument.
+                            throw_ub!(AbiMismatchArgument {
+                                arg_idx: callee_arg_idx,
+                                caller_ty: caller_abi.layout.ty,
+                                callee_ty: callee_abi.layout.ty
+                            });
+                        }
+                        assert!(caller_abi.is_ignore());
+                    }
+                } else if Some(local) == va_list_arg {
                     // This is the last callee-side argument of a variadic function.
                     // This argument is a VaList holding the remaining caller-side arguments.
                     ecx.storage_live(local)?;
@@ -476,12 +503,7 @@ pub fn init_stack_frame(
 
                     // Consume the remaining arguments by putting them into the variable argument
                     // list.
-                    let varargs = ecx.allocate_varargs(
-                        &mut caller_args,
-                        // "Ignored" arguments aren't actually passed, so the callee should also
-                        // ignore them. (`pass_argument` does this for regular arguments.)
-                        (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()),
-                    )?;
+                    let varargs = ecx.allocate_varargs(&mut caller_args, &mut callee_args_abis)?;
                     // When the frame is dropped, these variable arguments are deallocated.
                     ecx.frame_mut().va_list = varargs.clone();
                     let key = ecx.va_list_ptr(varargs.into());
@@ -507,11 +529,9 @@ pub fn init_stack_frame(
                             &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)],
                             *ecx.tcx,
                         );
-                        let (idx, callee_abi) = callee_args_abis.next().unwrap();
                         ecx.pass_argument(
                             &mut caller_args,
-                            callee_abi,
-                            idx,
+                            &mut callee_args_abis,
                             &dest,
                             field_ty,
                             /* already_live */ true,
@@ -519,11 +539,9 @@ pub fn init_stack_frame(
                     }
                 } else {
                     // Normal argument. Cannot mark it as live yet, it might be unsized!
-                    let (idx, callee_abi) = callee_args_abis.next().unwrap();
                     ecx.pass_argument(
                         &mut caller_args,
-                        callee_abi,
-                        idx,
+                        &mut callee_args_abis,
                         &dest,
                         ty,
                         /* already_live */ false,
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index c50d9db..a1776c6 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -142,8 +142,8 @@ pub fn read_discriminant(
                 let tag_val = tag_val.to_scalar();
                 // Compute the variant this niche value/"tag" corresponds to. With niche layout,
                 // discriminant (encoded in niche/tag) and variant index are the same.
-                let variants_start = niche_variants.start().as_u32();
-                let variants_end = niche_variants.end().as_u32();
+                let variants_start = niche_variants.start.as_u32();
+                let variants_last = niche_variants.last.as_u32();
                 let variant = match tag_val.try_to_scalar_int() {
                     Err(dbg_val) => {
                         // So this is a pointer then, and casting to an int failed.
@@ -151,7 +151,7 @@ pub fn read_discriminant(
                         // The niche must be just 0, and the ptr not null, then we know this is
                         // okay. Everything else, we conservatively reject.
                         let ptr_valid = niche_start == 0
-                            && variants_start == variants_end
+                            && variants_start == variants_last
                             && !self.scalar_may_be_null(tag_val)?;
                         if !ptr_valid {
                             throw_ub!(InvalidTag(dbg_val))
@@ -169,7 +169,7 @@ pub fn read_discriminant(
                         let variant_index_relative =
                             variant_index_relative_val.to_scalar().to_bits(tag_val.layout.size)?;
                         // Check if this is in the range that indicates an actual discriminant.
-                        if variant_index_relative <= u128::from(variants_end - variants_start) {
+                        if variant_index_relative <= u128::from(variants_last - variants_start) {
                             let variant_index_relative = u32::try_from(variant_index_relative)
                                 .expect("we checked that this fits into a u32");
                             // Then computing the absolute variant idx should not overflow any more.
@@ -309,7 +309,7 @@ pub(crate) fn tag_for_variant(
                     niche_variants.contains(&variant_index),
                     "invalid variant index for this enum"
                 );
-                let variants_start = niche_variants.start().as_u32();
+                let variants_start = niche_variants.start.as_u32();
                 let variant_index_relative = variant_index.as_u32().strict_sub(variants_start);
                 // We need to use machine arithmetic when taking into account `niche_start`:
                 // tag_val = variant_index_relative + niche_start_val
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 0718638..b1e3fd7 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -596,9 +596,9 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResul
                 }
             }
 
-            Drop { place, target, unwind, replace: _, drop, async_fut } => {
+            Drop { place, target, unwind, replace: _, drop } => {
                 assert!(
-                    async_fut.is_none() && drop.is_none(),
+                    drop.is_none(),
                     "Async Drop must be expanded or reset to sync in runtime MIR"
                 );
                 let place = self.eval_place(place)?;
diff --git a/compiler/rustc_data_structures/src/stable_hash.rs b/compiler/rustc_data_structures/src/stable_hash.rs
index 07a5e06..79d4512 100644
--- a/compiler/rustc_data_structures/src/stable_hash.rs
+++ b/compiler/rustc_data_structures/src/stable_hash.rs
@@ -527,14 +527,14 @@ fn stable_hash<Hcx: StableHashCtxt>(&self, _: &mut Hcx, hasher: &mut StableHashe
     }
 }
 
-impl<T> StableHash for ::std::ops::RangeInclusive<T>
+impl<T> StableHash for ::std::range::RangeInclusive<T>
 where
     T: StableHash,
 {
     #[inline]
     fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
-        self.start().stable_hash(hcx, hasher);
-        self.end().stable_hash(hcx, hasher);
+        self.start.stable_hash(hcx, hasher);
+        self.last.stable_hash(hcx, hasher);
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index 806d52b..42dbe37 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -257,7 +257,7 @@ pub struct UnordSet<V: Eq + Hash> {
 
 impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
 
-impl<V: Eq + Hash> const Default for UnordSet<V> {
+const impl<V: Eq + Hash> Default for UnordSet<V> {
     #[inline]
     fn default() -> Self {
         Self { inner: FxHashSet::with_hasher(FxBuildHasher) }
@@ -456,7 +456,7 @@ pub struct UnordMap<K: Eq + Hash, V> {
 
 impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
 
-impl<K: Eq + Hash, V> const Default for UnordMap<K, V> {
+const impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
     #[inline]
     fn default() -> Self {
         Self { inner: FxHashMap::with_hasher(FxBuildHasher) }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0552.md b/compiler/rustc_error_codes/src/error_codes/E0552.md
index 0fbc861..c7bd180 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0552.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0552.md
@@ -1,8 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+This error code was replaced by `E0539`.
+
 A unrecognized representation attribute was used.
 
 Erroneous code example:
 
-```compile_fail,E0552
+```compile_fail
 #[repr(D)] // error: unrecognized representation hint
 struct MyStruct {
     my_field: usize
diff --git a/compiler/rustc_error_codes/src/error_codes/E0693.md b/compiler/rustc_error_codes/src/error_codes/E0693.md
index 43e9d17..c9dca8f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0693.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0693.md
@@ -1,8 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+This error code was replaced by `E0539`.
+
 `align` representation hint was incorrectly declared.
 
 Erroneous code examples:
 
-```compile_fail,E0693
+```compile_fail
 #[repr(align=8)] // error!
 struct Align8(i8);
 
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index eaf8edd..63c35ad 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -109,7 +109,7 @@ macro_rules! declare_features {
     /// Allows `cfg(target_feature = "...")`.
     (accepted, cfg_target_feature, "1.27.0", Some(29717)),
     /// Allows `cfg(target_has_atomic_primitive_alignment = "...")`.
-    (accepted, cfg_target_has_atomic_equal_alignment, "CURRENT_RUSTC_VERSION", Some(93822)),
+    (accepted, cfg_target_has_atomic_equal_alignment, "1.97.0", Some(93822)),
     /// Allows `cfg(target_vendor = "...")`.
     (accepted, cfg_target_vendor, "1.33.0", Some(29718)),
     /// Allows implementing `Clone` for closures where possible (RFC 2132).
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 53d5dda..431461e 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -283,7 +283,7 @@ macro_rules! declare_features {
     (removed, string_deref_patterns, "1.94.0", Some(87121), Some("superseded by `deref_patterns`"), 150530),
     (removed, struct_inherit, "1.0.0", None, None),
     /// Allows the use of target_feature when a function is marked inline(always).
-    (removed, target_feature_inline_always, "CURRENT_RUSTC_VERSION", Some(145574),
+    (removed, target_feature_inline_always, "1.97.0", Some(145574),
      Some("removed because of unfixable soundness issues")),
     (removed, test_removed_feature, "1.0.0", None, None),
     /// Allows using items which are missing stability attributes
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index da45596..3884822 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -257,7 +257,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows identifying the `compiler_builtins` crate.
     (internal, compiler_builtins, "1.13.0", None),
     /// Allows skipping `ConstParamTy_` trait implementation checks
-    (internal, const_param_ty_unchecked, "CURRENT_RUSTC_VERSION", None),
+    (internal, const_param_ty_unchecked, "1.97.0", None),
     /// Allows writing custom MIR
     (internal, custom_mir, "1.65.0", None),
     /// Implementation details of externally implementable items
@@ -381,7 +381,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`.
     (unstable, abi_riscv_interrupt, "1.73.0", Some(111889)),
     /// Allows `extern "Swift" fn()`.
-    (unstable, abi_swift, "CURRENT_RUSTC_VERSION", Some(156481)),
+    (unstable, abi_swift, "1.97.0", Some(156481)),
     /// Allows `extern "x86-interrupt" fn()`.
     (unstable, abi_x86_interrupt, "1.17.0", Some(40180)),
     /// Allows additional const parameter types, such as `[u8; 10]` or user defined types
@@ -426,7 +426,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     (unstable, c_variadic, "1.34.0", Some(44930)),
     /// Allows defining c-variadic functions on targets where this feature has not yet
     /// undergone sufficient testing for stabilization.
-    (unstable, c_variadic_experimental_arch, "CURRENT_RUSTC_VERSION", Some(155973)),
+    (unstable, c_variadic_experimental_arch, "1.97.0", Some(155973)),
     /// Allows defining c-variadic naked functions with any extern ABI that is allowed
     /// on c-variadic foreign functions.
     (unstable, c_variadic_naked_functions, "1.93.0", Some(148767)),
@@ -445,7 +445,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows `cfg(target_has_atomic_load_store = "...")`.
     (unstable, cfg_target_has_atomic, "1.60.0", Some(94039)),
     /// Allows `cfg(target_object_format = "...")`.
-    (unstable, cfg_target_object_format, "CURRENT_RUSTC_VERSION", Some(152586)),
+    (unstable, cfg_target_object_format, "1.97.0", Some(152586)),
     /// Allows `cfg(target_thread_local)`.
     (unstable, cfg_target_thread_local, "1.7.0", Some(29594)),
     /// Allows the use of `#[cfg(ub_checks)` to check if UB checks are enabled.
@@ -454,6 +454,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
     (unstable, cfg_version, "1.45.0", Some(64796)),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
     (unstable, cfi_encoding, "1.71.0", Some(89653)),
+    /// The `clflushopt` target feature on x86.
+    (unstable, clflushopt_target_feature, "CURRENT_RUSTC_VERSION", Some(157096)),
     /// Allows `for<...>` on closures and coroutines.
     (unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
     /// Allows `#[track_caller]` on closures and coroutines.
@@ -513,7 +515,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows giving unresolved imports a custom diagnostic message
     (unstable, diagnostic_on_unknown, "1.96.0", Some(152900)),
     /// Allows macros to customize macro argument matcher diagnostics.
-    (unstable, diagnostic_on_unmatch_args, "CURRENT_RUSTC_VERSION", Some(155642)),
+    (unstable, diagnostic_on_unmatch_args, "1.97.0", Some(155642)),
     /// Allows `#[doc(cfg(...))]`.
     (unstable, doc_cfg, "1.21.0", Some(43781)),
     /// Allows `#[doc(masked)]`.
@@ -549,7 +551,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows marking trait functions as `final` to prevent overriding impls
     (unstable, final_associated_functions, "1.95.0", Some(131179)),
     /// fma4 target feature on x86.
-    (unstable, fma4_target_feature, "CURRENT_RUSTC_VERSION", Some(155233)),
+    (unstable, fma4_target_feature, "1.97.0", Some(155233)),
     /// Controlling the behavior of fmt::Debug
     (unstable, fmt_debug, "1.82.0", Some(129709)),
     /// Allows using `#[align(...)]` on function items
@@ -582,7 +584,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Target features on hexagon.
     (unstable, hexagon_target_feature, "1.27.0", Some(150250)),
     /// Allows `impl(crate) trait Foo` restrictions.
-    (unstable, impl_restriction, "CURRENT_RUSTC_VERSION", Some(105077)),
+    (unstable, impl_restriction, "1.97.0", Some(105077)),
     /// Allows `impl Trait` to be used inside associated types (RFC 2515).
     (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
     /// Allows `impl Trait` in bindings (`let`).
@@ -639,7 +641,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
     (unstable, more_qualified_paths, "1.54.0", Some(86935)),
     /// Allows `move(expr)` in closures.
-    (incomplete, move_expr, "CURRENT_RUSTC_VERSION", Some(155050)),
+    (incomplete, move_expr, "1.97.0", Some(155050)),
     /// The `movrs` target feature on x86.
     (unstable, movrs_target_feature, "1.88.0", Some(137976)),
     /// Allows the `multiple_supertrait_upcastable` lint.
@@ -760,7 +762,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
     /// Allows view types.
-    (unstable, view_types, "CURRENT_RUSTC_VERSION", Some(155938)),
+    (unstable, view_types, "1.97.0", Some(155938)),
     /// Target features on wasm.
     (unstable, wasm_target_feature, "1.30.0", Some(150260)),
     /// Allows use of attributes in `where` clauses.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index ad5d6b1..d275d5a 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -991,8 +991,6 @@ pub enum LifetimeRes {
         ///
         /// Creating the associated `LocalDefId` is the responsibility of lowering.
         param: NodeId,
-        /// Id of the introducing place. See `Param`.
-        binder: NodeId,
         /// Kind of elided lifetime
         kind: hir::MissingLifetimeKind,
     },
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 70720c6..8b37ee2 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -20,84 +20,6 @@
 use crate::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
 use crate::def_path_hash_map::DefPathHashMap;
 
-/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
-/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
-/// stores the `DefIndex` of its parent.
-/// There is one `DefPathTable` for each crate.
-#[derive(Debug)]
-pub struct DefPathTable {
-    stable_crate_id: StableCrateId,
-    index_to_key: IndexVec<DefIndex, DefKey>,
-    // We do only store the local hash, as all the definitions are from the current crate.
-    def_path_hashes: IndexVec<DefIndex, Hash64>,
-    def_path_hash_to_index: DefPathHashMap,
-}
-
-impl DefPathTable {
-    fn new(stable_crate_id: StableCrateId) -> DefPathTable {
-        DefPathTable {
-            stable_crate_id,
-            index_to_key: Default::default(),
-            def_path_hashes: Default::default(),
-            def_path_hash_to_index: Default::default(),
-        }
-    }
-
-    fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
-        // Assert that all DefPathHashes correctly contain the local crate's StableCrateId.
-        debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
-        let local_hash = def_path_hash.local_hash();
-
-        let index = self.index_to_key.push(key);
-        debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
-
-        self.def_path_hashes.push(local_hash);
-        debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
-
-        // Check for hash collisions of DefPathHashes. These should be
-        // exceedingly rare.
-        if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) {
-            let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
-            let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
-
-            // Continuing with colliding DefPathHashes can lead to correctness
-            // issues. We must abort compilation.
-            //
-            // The likelihood of such a collision is very small, so actually
-            // running into one could be indicative of a poor hash function
-            // being used.
-            //
-            // See the documentation for DefPathHash for more information.
-            panic!(
-                "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
-                    Compilation cannot continue."
-            );
-        }
-
-        index
-    }
-
-    #[inline(always)]
-    pub fn def_key(&self, index: DefIndex) -> DefKey {
-        self.index_to_key[index]
-    }
-
-    #[instrument(level = "trace", skip(self), ret)]
-    #[inline(always)]
-    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        let hash = self.def_path_hashes[index];
-        DefPathHash::new(self.stable_crate_id, hash)
-    }
-
-    pub fn enumerated_keys_and_path_hashes(
-        &self,
-    ) -> impl Iterator<Item = (DefIndex, &DefKey, DefPathHash)> + ExactSizeIterator {
-        self.index_to_key
-            .iter_enumerated()
-            .map(move |(index, key)| (index, key, self.def_path_hash(index)))
-    }
-}
-
 #[derive(Debug, Default, Clone)]
 pub struct PerParentDisambiguatorState {
     #[cfg(debug_assertions)]
@@ -123,12 +45,13 @@ fn get_or_create(&mut self, parent: LocalDefId) -> &mut PerParentDisambiguatorSt
     }
 }
 
-/// The definition table containing node definitions.
-/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
-/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
 #[derive(Debug)]
 pub struct Definitions {
-    table: DefPathTable,
+    stable_crate_id: StableCrateId,
+    def_id_to_key: IndexVec<LocalDefId, DefKey>,
+    // We do only store the local hash, as all the definitions are from the current crate.
+    def_path_hashes: IndexVec<LocalDefId, Hash64>,
+    def_path_hash_to_index: DefPathHashMap,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -167,7 +90,7 @@ pub(crate) fn compute_stable_hash(&self, parent: DefPathHash) -> DefPathHash {
         // Construct the new DefPathHash, making sure that the `crate_id`
         // portion of the hash is properly copied from the parent. This way the
         // `crate_id` part will be recursively propagated from the root to all
-        // DefPathHashes in this DefPathTable.
+        // DefPathHashes in this Definitions.
         DefPathHash::new(parent.stable_crate_id(), local_hash)
     }
 
@@ -324,23 +247,17 @@ pub enum DefPathData {
 }
 
 impl Definitions {
-    pub fn def_path_table(&self) -> &DefPathTable {
-        &self.table
-    }
-
-    /// Gets the number of definitions.
-    pub fn def_index_count(&self) -> usize {
-        self.table.index_to_key.len()
-    }
-
-    #[inline]
+    #[inline(always)]
     pub fn def_key(&self, id: LocalDefId) -> DefKey {
-        self.table.def_key(id.local_def_index)
+        self.def_id_to_key[id]
     }
 
+    // Log debug version of `local_def_index` (just a number), as tracing of this function
+    // is called too early and cause errors if `LocalDefId` is logged (#157238).
+    #[instrument(level = "trace", skip(self, id), fields(def_index=?id.local_def_index), ret)]
     #[inline(always)]
     pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
-        self.table.def_path_hash(id.local_def_index)
+        DefPathHash::new(self.stable_crate_id, self.def_path_hashes[id])
     }
 
     /// Returns the path from the crate root to `index`. The root
@@ -348,6 +265,7 @@ pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
     /// empty vector for the crate root). For an inlined item, this
     /// will be the path of the item in the external crate (but the
     /// path will begin with the path to the external crate).
+    #[inline]
     pub fn def_path(&self, id: LocalDefId) -> DefPath {
         DefPath::make(LOCAL_CRATE, id.local_def_index, |index| {
             self.def_key(LocalDefId { local_def_index: index })
@@ -375,12 +293,62 @@ pub fn new(stable_crate_id: StableCrateId) -> Definitions {
         let def_path_hash =
             DefPathHash::new(stable_crate_id, Hash64::new(stable_crate_id.as_u64()));
 
+        let mut defs = Definitions {
+            stable_crate_id,
+            def_path_hashes: Default::default(),
+            def_id_to_key: Default::default(),
+            def_path_hash_to_index: Default::default(),
+        };
+
         // Create the root definition.
-        let mut table = DefPathTable::new(stable_crate_id);
-        let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
+        let root = defs.allocate(key, def_path_hash);
         assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
 
-        Definitions { table }
+        defs
+    }
+
+    fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> LocalDefId {
+        // Assert that all DefPathHashes correctly contain the local crate's StableCrateId.
+        debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
+        let local_hash = def_path_hash.local_hash();
+
+        let def_id = self.def_id_to_key.push(key);
+        debug!("def_id_to_key.push() - {key:?} <-> {:?}", def_id.local_def_index);
+
+        self.def_path_hashes.push(local_hash);
+        debug_assert!(self.def_path_hashes.len() == self.def_id_to_key.len());
+
+        // Check for hash collisions of DefPathHashes. These should be
+        // exceedingly rare.
+        if let Some(existing) =
+            self.def_path_hash_to_index.insert(&local_hash, &def_id.local_def_index)
+        {
+            let def_path1 = self.def_path(LocalDefId { local_def_index: existing });
+            let def_path2 = self.def_path(def_id);
+
+            // Continuing with colliding DefPathHashes can lead to correctness
+            // issues. We must abort compilation.
+            //
+            // The likelihood of such a collision is very small, so actually
+            // running into one could be indicative of a poor hash function
+            // being used.
+            //
+            // See the documentation for DefPathHash for more information.
+            panic!(
+                "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
+                    Compilation cannot continue."
+            );
+        }
+
+        def_id
+    }
+
+    pub fn enumerated_keys_and_path_hashes(
+        &self,
+    ) -> impl Iterator<Item = (DefIndex, &DefKey, DefPathHash)> + ExactSizeIterator {
+        self.def_id_to_key
+            .iter_enumerated()
+            .map(move |(def_id, key)| (def_id.local_def_index, key, self.def_path_hash(def_id)))
     }
 
     /// Creates a definition with a parent definition.
@@ -423,13 +391,13 @@ pub fn create_def(
             disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
         };
 
-        let parent_hash = self.table.def_path_hash(parent.local_def_index);
+        let parent_hash = self.def_path_hash(parent);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         debug!("create_def: after disambiguation, key = {:?}", key);
 
         // Create the definition.
-        LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
+        self.allocate(key, def_path_hash)
     }
 
     #[inline(always)]
@@ -439,19 +407,18 @@ pub fn create_def(
     /// if the `DefPathHash` is from a previous compilation session and
     /// the def-path does not exist anymore.
     pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
-        debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id);
-        self.table
-            .def_path_hash_to_index
+        debug_assert!(hash.stable_crate_id() == self.stable_crate_id);
+        self.def_path_hash_to_index
             .get(&hash.local_hash())
             .map(|local_def_index| LocalDefId { local_def_index })
     }
 
     pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
-        &self.table.def_path_hash_to_index
+        &self.def_path_hash_to_index
     }
 
     pub fn num_definitions(&self) -> usize {
-        self.table.def_path_hashes.len()
+        self.def_path_hashes.len()
     }
 }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 59d1b4b..256176f 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2327,6 +2327,13 @@ pub fn is_fn_like(self) -> bool {
         matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
     }
 
+    pub fn is_async_desugaring(self) -> bool {
+        matches!(
+            self,
+            CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _)
+        )
+    }
+
     pub fn to_plural_string(&self) -> String {
         match self {
             CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index f90311c..14759ad 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -776,7 +776,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
                     // need to store default and type of default
                     let ct = tcx.const_param_default(param.def_id).skip_binder();
                     if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
-                        tcx.ensure_ok().type_of(uv.def);
+                        tcx.ensure_ok().type_of(uv.kind.def_id());
                     }
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 644e8dd..a4d6056 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -356,6 +356,7 @@ pub(crate) fn check_intrinsic_type(
                 param(0),
                 Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)),
                 Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)),
+                tcx.types.u32,
                 param(1),
             ],
             param(2),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index dd506dd..f495df3 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1535,9 +1535,11 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id:
                     | ty::ConstKind::Bound(_, _) => unreachable!(),
                     ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,
                     ty::ConstKind::Value(cv) => cv.ty,
-                    ty::ConstKind::Unevaluated(uv) => {
-                        infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).skip_norm_wip()
-                    }
+                    ty::ConstKind::Unevaluated(uv) => infcx
+                        .tcx
+                        .type_of(uv.kind.def_id())
+                        .instantiate(infcx.tcx, uv.args)
+                        .skip_norm_wip(),
                     ty::ConstKind::Param(param_ct) => {
                         param_ct.find_const_ty_from_env(wfcx.param_env)
                     }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index ad46f01..cf29a76 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -435,7 +435,7 @@ fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
         fn visit_const(&mut self, c: ty::Const<'tcx>) {
             if let ty::ConstKind::Unevaluated(uv) = c.kind() {
-                if let Some(local) = uv.def.as_local()
+                if let Some(local) = uv.kind.def_id().as_local()
                     && is_const_param_default(self.tcx, local)
                 {
                     // Do not look into const param defaults,
@@ -449,11 +449,11 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) {
                 }
 
                 // Skip type consts as mGCA doesn't support evaluatable clauses.
-                if self.tcx.is_type_const(uv.def) {
+                if self.tcx.is_type_const(uv.kind.def_id()) {
                     return;
                 }
 
-                let span = self.tcx.def_span(uv.def);
+                let span = self.tcx.def_span(uv.kind.def_id());
                 self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
index a498e97..818c418 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
@@ -515,6 +515,48 @@ fn check_elaborated_projection_mentions_input_lifetimes(
         );
     }
 
+    /// Given the bounds on an object, determines what single region bound (if any) we can
+    /// use to summarize this type.
+    ///
+    /// The basic idea is that we will use the bound the user
+    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
+    /// for region bounds. It may be that we can derive no bound at all, in which case
+    /// we return `None`.
+    #[instrument(level = "debug", skip(self, span), ret)]
+    fn compute_object_lifetime_bound(
+        &self,
+        span: Span,
+        existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+    ) -> Option<ty::Region<'tcx>> // if None, use the default
+    {
+        let tcx = self.tcx();
+
+        // No explicit region bound specified. Therefore, examine trait
+        // bounds and see if we can derive region bounds from those.
+        let derived_region_bounds = traits::wf::object_region_bounds(tcx, existential_predicates);
+
+        // If there are no derived region bounds, then report back that we
+        // can find no region bound. The caller will use the default.
+        if derived_region_bounds.is_empty() {
+            return None;
+        }
+
+        // If any of the derived region bounds are 'static, that is always
+        // the best choice.
+        if derived_region_bounds.iter().any(|r| r.is_static()) {
+            return Some(tcx.lifetimes.re_static);
+        }
+
+        // Determine whether there is exactly one unique region in the set
+        // of derived region bounds. If so, use that. Otherwise, report an
+        // error.
+        let r = derived_region_bounds[0];
+        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
+            self.dcx().emit_err(crate::errors::AmbiguousLifetimeBound { span });
+        }
+        Some(r)
+    }
+
     /// Prohibit or lint against *bare* trait object types depending on the edition.
     ///
     /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5e11819..b8cdd67 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -403,6 +403,141 @@ fn report_assoc_kind_mismatch(
         })
     }
 
+    pub(super) fn report_ambiguous_assoc_item(
+        &self,
+        bound1: ty::PolyTraitRef<'tcx>,
+        bound2: ty::PolyTraitRef<'tcx>,
+        matching_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+        qself: AssocItemQSelf,
+        assoc_tag: ty::AssocTag,
+        assoc_ident: Ident,
+        span: Span,
+        constraint: Option<&hir::AssocItemConstraint<'tcx>>,
+    ) -> ErrorGuaranteed {
+        let tcx = self.tcx();
+
+        let assoc_kind_str = assoc_tag_str(assoc_tag);
+        let qself_str = qself.to_string(tcx);
+        let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
+            span,
+            assoc_kind: assoc_kind_str,
+            assoc_ident,
+            qself: &qself_str,
+        });
+        // Provide a more specific error code index entry for equality bindings.
+        err.code(
+            if let Some(constraint) = constraint
+                && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
+            {
+                E0222
+            } else {
+                E0221
+            },
+        );
+
+        // FIXME(#97583): Print associated item bindings properly (i.e., not as equality
+        // predicates!).
+        // FIXME: Turn this into a structured, translatable & more actionable suggestion.
+        let mut where_bounds = vec![];
+        for bound in [bound1, bound2].into_iter().chain(matching_candidates) {
+            let bound_id = bound.def_id();
+            let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
+                tcx,
+                assoc_ident,
+                assoc_tag,
+                bound_id,
+            );
+            let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id));
+
+            if let Some(bound_span) = bound_span {
+                err.span_label(
+                    bound_span,
+                    format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),),
+                );
+                if let Some(constraint) = constraint {
+                    match constraint.kind {
+                        hir::AssocItemConstraintKind::Equality { term } => {
+                            let term: ty::Term<'_> = match term {
+                                hir::Term::Ty(ty) => self.lower_ty(ty).into(),
+                                hir::Term::Const(ct) => {
+                                    let assoc_item =
+                                        assoc_item.expect("assoc_item should be present");
+                                    let projection_term = bound.map_bound(|trait_ref| {
+                                        let item_segment = hir::PathSegment {
+                                            ident: constraint.ident,
+                                            hir_id: constraint.hir_id,
+                                            res: Res::Err,
+                                            args: Some(constraint.gen_args),
+                                            infer_args: false,
+                                        };
+
+                                        let alias_args = self.lower_generic_args_of_assoc_item(
+                                            constraint.ident.span,
+                                            assoc_item.def_id,
+                                            &item_segment,
+                                            trait_ref.args,
+                                        );
+                                        ty::AliasTerm::new_from_def_id(
+                                            tcx,
+                                            assoc_item.def_id,
+                                            alias_args,
+                                        )
+                                    });
+
+                                    // FIXME(mgca): code duplication with other places we lower
+                                    // the rhs' of associated const bindings
+                                    let ty = projection_term.map_bound(|alias| {
+                                        tcx.type_of(alias.def_id())
+                                            .instantiate(tcx, alias.args)
+                                            .skip_norm_wip()
+                                    });
+                                    let ty = super::bounds::check_assoc_const_binding_type(
+                                        self,
+                                        constraint.ident,
+                                        ty,
+                                        constraint.hir_id,
+                                    );
+
+                                    self.lower_const_arg(ct, ty).into()
+                                }
+                            };
+                            if term.references_error() {
+                                continue;
+                            }
+                            // FIXME(#97583): This isn't syntactically well-formed!
+                            where_bounds.push(format!(
+                                "        T: {trait}::{assoc_ident} = {term}",
+                                trait = bound.print_only_trait_path(),
+                            ));
+                        }
+                        // FIXME: Provide a suggestion.
+                        hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
+                    }
+                } else {
+                    err.span_suggestion_verbose(
+                        span.with_hi(assoc_ident.span.lo()),
+                        "use fully-qualified syntax to disambiguate",
+                        format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            } else {
+                let trait_ = tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
+                err.note(format!(
+                    "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
+                ));
+            }
+        }
+        if !where_bounds.is_empty() {
+            err.help(format!(
+                "consider introducing a new type parameter `T` and adding `where` constraints:\
+                     \n    where\n        T: {qself_str},\n{}",
+                where_bounds.join(",\n"),
+            ));
+        }
+        err.emit()
+    }
+
     pub(crate) fn report_missing_self_ty_for_resolved_path(
         &self,
         trait_def_id: DefId,
@@ -568,7 +703,7 @@ pub(super) fn report_unresolved_type_relative_path(
         }
     }
 
-    pub(super) fn report_ambiguous_assoc_item_path(
+    fn report_ambiguous_assoc_item_path(
         &self,
         span: Span,
         types: &[String],
@@ -1847,7 +1982,59 @@ fn generics_args_err_extend<'a>(
     }
 }
 
-pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
+pub(super) struct AmbiguityBetweenVariantAndAssocItem<'tcx> {
+    pub(super) variant_def_id: DefId,
+    pub(super) item_def_id: DefId,
+    pub(super) span: Span,
+    pub(super) segment_ident: Ident,
+    pub(super) bound_def_id: DefId,
+    pub(super) self_ty: Ty<'tcx>,
+    pub(super) tcx: TyCtxt<'tcx>,
+    pub(super) mode: super::LowerTypeRelativePathMode,
+}
+
+impl<'a, 'tcx> rustc_errors::Diagnostic<'a, ()> for AmbiguityBetweenVariantAndAssocItem<'tcx> {
+    fn into_diag(
+        self,
+        dcx: rustc_errors::DiagCtxtHandle<'a>,
+        level: rustc_errors::Level,
+    ) -> Diag<'a, ()> {
+        let Self {
+            variant_def_id,
+            item_def_id,
+            span,
+            segment_ident,
+            bound_def_id,
+            self_ty,
+            tcx,
+            mode,
+        } = self;
+        let mut lint = Diag::new(dcx, level, "ambiguous associated item");
+
+        let mut could_refer_to = |kind: DefKind, def_id, also| {
+            let note_msg = format!(
+                "`{}` could{} refer to the {} defined here",
+                segment_ident,
+                also,
+                tcx.def_kind_descr(kind, def_id)
+            );
+            lint.span_note(tcx.def_span(def_id), note_msg);
+        };
+
+        could_refer_to(DefKind::Variant, variant_def_id, "");
+        could_refer_to(mode.def_kind_for_diagnostics(), item_def_id, " also");
+
+        lint.span_suggestion(
+            span,
+            "use fully-qualified syntax",
+            format!("<{} as {}>::{}", self_ty, tcx.item_name(bound_def_id), segment_ident),
+            Applicability::MachineApplicable,
+        );
+        lint
+    }
+}
+
+fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
     match assoc_tag {
         ty::AssocTag::Fn => "function",
         ty::AssocTag::Const => "constant",
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 5a86e81..943256c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -26,7 +26,7 @@
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, FatalError, Level, StashKey,
+    Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey,
     struct_span_code_err,
 };
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -36,7 +36,6 @@
 use rustc_infer::traits::DynCompatibilityViolation;
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
 use rustc_middle::ty::{
     self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput,
     Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast,
@@ -47,12 +46,11 @@
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
 use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{self, FulfillmentError};
 use tracing::{debug, instrument};
 
 use crate::check::check_abi;
-use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoFieldOnType};
+use crate::errors::{BadReturnTypeNotation, NoFieldOnType};
 use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -1282,13 +1280,11 @@ fn probe_single_bound_for_assoc_item<I>(
     where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
     {
-        let tcx = self.tcx();
-
         let mut matching_candidates = all_candidates().filter(|r| {
             self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident)
         });
 
-        let Some(bound) = matching_candidates.next() else {
+        let Some(bound1) = matching_candidates.next() else {
             return Err(self.report_unresolved_assoc_item(
                 all_candidates,
                 qself,
@@ -1298,137 +1294,21 @@ fn probe_single_bound_for_assoc_item<I>(
                 constraint,
             ));
         };
-        debug!(?bound);
 
         if let Some(bound2) = matching_candidates.next() {
-            debug!(?bound2);
-
-            let assoc_kind_str = errors::assoc_tag_str(assoc_tag);
-            let qself_str = qself.to_string(tcx);
-            let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
-                span,
-                assoc_kind: assoc_kind_str,
+            return Err(self.report_ambiguous_assoc_item(
+                bound1,
+                bound2,
+                matching_candidates,
+                qself,
+                assoc_tag,
                 assoc_ident,
-                qself: &qself_str,
-            });
-            // Provide a more specific error code index entry for equality bindings.
-            err.code(
-                if let Some(constraint) = constraint
-                    && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
-                {
-                    E0222
-                } else {
-                    E0221
-                },
-            );
-
-            // FIXME(#97583): Print associated item bindings properly (i.e., not as equality
-            // predicates!).
-            // FIXME: Turn this into a structured, translatable & more actionable suggestion.
-            let mut where_bounds = vec![];
-            for bound in [bound, bound2].into_iter().chain(matching_candidates) {
-                let bound_id = bound.def_id();
-                let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
-                    tcx,
-                    assoc_ident,
-                    assoc_tag,
-                    bound_id,
-                );
-                let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id));
-
-                if let Some(bound_span) = bound_span {
-                    err.span_label(
-                        bound_span,
-                        format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),),
-                    );
-                    if let Some(constraint) = constraint {
-                        match constraint.kind {
-                            hir::AssocItemConstraintKind::Equality { term } => {
-                                let term: ty::Term<'_> = match term {
-                                    hir::Term::Ty(ty) => self.lower_ty(ty).into(),
-                                    hir::Term::Const(ct) => {
-                                        let assoc_item =
-                                            assoc_item.expect("assoc_item should be present");
-                                        let projection_term = bound.map_bound(|trait_ref| {
-                                            let item_segment = hir::PathSegment {
-                                                ident: constraint.ident,
-                                                hir_id: constraint.hir_id,
-                                                res: Res::Err,
-                                                args: Some(constraint.gen_args),
-                                                infer_args: false,
-                                            };
-
-                                            let alias_args = self.lower_generic_args_of_assoc_item(
-                                                constraint.ident.span,
-                                                assoc_item.def_id,
-                                                &item_segment,
-                                                trait_ref.args,
-                                            );
-                                            ty::AliasTerm::new_from_def_id(
-                                                tcx,
-                                                assoc_item.def_id,
-                                                alias_args,
-                                            )
-                                        });
-
-                                        // FIXME(mgca): code duplication with other places we lower
-                                        // the rhs' of associated const bindings
-                                        let ty = projection_term.map_bound(|alias| {
-                                            tcx.type_of(alias.def_id())
-                                                .instantiate(tcx, alias.args)
-                                                .skip_norm_wip()
-                                        });
-                                        let ty = bounds::check_assoc_const_binding_type(
-                                            self,
-                                            constraint.ident,
-                                            ty,
-                                            constraint.hir_id,
-                                        );
-
-                                        self.lower_const_arg(ct, ty).into()
-                                    }
-                                };
-                                if term.references_error() {
-                                    continue;
-                                }
-                                // FIXME(#97583): This isn't syntactically well-formed!
-                                where_bounds.push(format!(
-                                    "        T: {trait}::{assoc_ident} = {term}",
-                                    trait = bound.print_only_trait_path(),
-                                ));
-                            }
-                            // FIXME: Provide a suggestion.
-                            hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
-                        }
-                    } else {
-                        err.span_suggestion_verbose(
-                            span.with_hi(assoc_ident.span.lo()),
-                            "use fully-qualified syntax to disambiguate",
-                            format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                } else {
-                    let trait_ =
-                        tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
-                    err.note(format!(
-                        "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
-                    ));
-                }
-            }
-            if !where_bounds.is_empty() {
-                err.help(format!(
-                    "consider introducing a new type parameter `T` and adding `where` constraints:\
-                     \n    where\n        T: {qself_str},\n{}",
-                    where_bounds.join(",\n"),
-                ));
-                let reported = err.emit();
-                return Err(reported);
-            }
-            err.emit();
+                span,
+                constraint,
+            ));
         }
 
-        Ok(bound)
+        Ok(bound1)
     }
 
     /// Lower a [type-relative](hir::QPath::TypeRelative) path in type position to a type.
@@ -1518,7 +1398,14 @@ fn lower_type_relative_const_path(
         )? {
             TypeRelativePath::AssocItem(def_id, args) => {
                 self.require_type_const_attribute(def_id, span)?;
-                let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
+                let ct = Const::new_unevaluated(
+                    tcx,
+                    ty::UnevaluatedConst::new(
+                        tcx,
+                        ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id),
+                        args,
+                    ),
+                );
                 let ct = self.check_param_uses_if_mcg(ct, span, false);
                 Ok(ct)
             }
@@ -1550,54 +1437,6 @@ fn lower_type_relative_path(
         span: Span,
         mode: LowerTypeRelativePathMode,
     ) -> Result<TypeRelativePath<'tcx>, ErrorGuaranteed> {
-        struct AmbiguousAssocItem<'tcx> {
-            variant_def_id: DefId,
-            item_def_id: DefId,
-            span: Span,
-            segment_ident: Ident,
-            bound_def_id: DefId,
-            self_ty: Ty<'tcx>,
-            tcx: TyCtxt<'tcx>,
-            mode: LowerTypeRelativePathMode,
-        }
-
-        impl<'a, 'tcx> Diagnostic<'a, ()> for AmbiguousAssocItem<'tcx> {
-            fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
-                let Self {
-                    variant_def_id,
-                    item_def_id,
-                    span,
-                    segment_ident,
-                    bound_def_id,
-                    self_ty,
-                    tcx,
-                    mode,
-                } = self;
-                let mut lint = Diag::new(dcx, level, "ambiguous associated item");
-
-                let mut could_refer_to = |kind: DefKind, def_id, also| {
-                    let note_msg = format!(
-                        "`{}` could{} refer to the {} defined here",
-                        segment_ident,
-                        also,
-                        tcx.def_kind_descr(kind, def_id)
-                    );
-                    lint.span_note(tcx.def_span(def_id), note_msg);
-                };
-
-                could_refer_to(DefKind::Variant, variant_def_id, "");
-                could_refer_to(mode.def_kind_for_diagnostics(), item_def_id, " also");
-
-                lint.span_suggestion(
-                    span,
-                    "use fully-qualified syntax",
-                    format!("<{} as {}>::{}", self_ty, tcx.item_name(bound_def_id), segment_ident),
-                    Applicability::MachineApplicable,
-                );
-                lint
-            }
-        }
-
         debug!(%self_ty, ?segment.ident);
         let tcx = self.tcx();
 
@@ -1677,7 +1516,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
                 AMBIGUOUS_ASSOCIATED_ITEMS,
                 qpath_hir_id,
                 span,
-                AmbiguousAssocItem {
+                errors::AmbiguityBetweenVariantAndAssocItem {
                     variant_def_id,
                     item_def_id,
                     span,
@@ -2008,6 +1847,7 @@ fn lower_resolved_assoc_const_path(
         trait_segment: Option<&hir::PathSegment<'tcx>>,
         item_segment: &hir::PathSegment<'tcx>,
     ) -> Result<Const<'tcx>, ErrorGuaranteed> {
+        let tcx = self.tcx();
         let (item_def_id, item_args) = self.lower_resolved_assoc_item_path(
             span,
             opt_self_ty,
@@ -2017,8 +1857,12 @@ fn lower_resolved_assoc_const_path(
             ty::AssocTag::Const,
         )?;
         self.require_type_const_attribute(item_def_id, span)?;
-        let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
-        Ok(Const::new_unevaluated(self.tcx(), uv))
+        let uv = ty::UnevaluatedConst::new(
+            tcx,
+            ty::UnevaluatedConstKind::new_from_def_id(tcx, item_def_id),
+            item_args,
+        );
+        Ok(Const::new_unevaluated(tcx, uv))
     }
 
     /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.
@@ -2860,7 +2704,14 @@ fn lower_resolved_const_path(
                 let _ = self
                     .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
                 let args = self.lower_generic_args_of_path_segment(span, did, segment);
-                ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
+                ty::Const::new_unevaluated(
+                    tcx,
+                    ty::UnevaluatedConst::new(
+                        tcx,
+                        ty::UnevaluatedConstKind::new_from_def_id(tcx, did),
+                        args,
+                    ),
+                )
             }
             Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => {
                 assert_eq!(opt_self_ty, None);
@@ -2984,10 +2835,11 @@ fn lower_const_arg_anon(&self, anon: &AnonConst) -> Const<'tcx> {
             Some(v) => v,
             None => ty::Const::new_unevaluated(
                 tcx,
-                ty::UnevaluatedConst {
-                    def: anon.def_id.to_def_id(),
-                    args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()),
-                },
+                ty::UnevaluatedConst::new(
+                    tcx,
+                    ty::UnevaluatedConstKind::Anon { def_id: anon.def_id.to_def_id() },
+                    ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()),
+                ),
             ),
         }
     }
@@ -3738,48 +3590,6 @@ fn validate_late_bound_regions<'cx>(
         }
     }
 
-    /// Given the bounds on an object, determines what single region bound (if any) we can
-    /// use to summarize this type.
-    ///
-    /// The basic idea is that we will use the bound the user
-    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
-    /// for region bounds. It may be that we can derive no bound at all, in which case
-    /// we return `None`.
-    #[instrument(level = "debug", skip(self, span), ret)]
-    fn compute_object_lifetime_bound(
-        &self,
-        span: Span,
-        existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Option<ty::Region<'tcx>> // if None, use the default
-    {
-        let tcx = self.tcx();
-
-        // No explicit region bound specified. Therefore, examine trait
-        // bounds and see if we can derive region bounds from those.
-        let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
-
-        // If there are no derived region bounds, then report back that we
-        // can find no region bound. The caller will use the default.
-        if derived_region_bounds.is_empty() {
-            return None;
-        }
-
-        // If any of the derived region bounds are 'static, that is always
-        // the best choice.
-        if derived_region_bounds.iter().any(|r| r.is_static()) {
-            return Some(tcx.lifetimes.re_static);
-        }
-
-        // Determine whether there is exactly one unique region in the set
-        // of derived region bounds. If so, use that. Otherwise, report an
-        // error.
-        let r = derived_region_bounds[0];
-        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            self.dcx().emit_err(AmbiguousLifetimeBound { span });
-        }
-        Some(r)
-    }
-
     fn construct_const_ctor_value(
         &self,
         ctor_def_id: DefId,
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 23e6b22..174f702 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -8,11 +8,7 @@
 use super::explicit::ExplicitPredicatesMap;
 use super::utils::*;
 
-/// Infer predicates for the items in the crate.
-///
-/// `global_inferred_outlives`: this is initially the empty map that
-///     was generated by walking the items in the crate. This will
-///     now be filled with inferred predicates.
+/// Infer outlives-predicates for the items in the local crate.
 pub(super) fn infer_predicates(
     tcx: TyCtxt<'_>,
 ) -> FxIndexMap<DefId, ty::EarlyBinder<'_, RequiredPredicates<'_>>> {
@@ -154,7 +150,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                     args,
                     required_predicates,
                     explicit_map,
-                    None,
+                    IgnorePredicatesReferencingSelf::No,
                 );
             }
 
@@ -175,7 +171,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                     args,
                     required_predicates,
                     explicit_map,
-                    None,
+                    IgnorePredicatesReferencingSelf::No,
                 );
             }
 
@@ -183,23 +179,27 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 // This corresponds to `dyn Trait<..>`. In this case, we should
                 // use the explicit predicates as well.
                 debug!("Dynamic");
-                if let Some(ex_trait_ref) = obj.principal() {
-                    // Here, we are passing the type `usize` as a
-                    // placeholder value with the function
-                    // `with_self_ty`, since there is no concrete type
-                    // `Self` for a `dyn Trait` at this
-                    // stage. Therefore when checking explicit
-                    // predicates in `check_explicit_predicates` we
-                    // need to ignore checking the explicit_map for
-                    // Self type.
-                    let args = ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().args;
+                if let Some(trait_ref) = obj.principal() {
+                    let args = trait_ref
+                        .with_self_ty(tcx, tcx.types.trait_object_dummy_self)
+                        .skip_binder()
+                        .args;
+                    // We skip predicates that reference the `Self` type parameter since we don't
+                    // want to leak the dummy Self to the predicates map.
+                    //
+                    // While filtering out bounds like `Self: 'a` as in `trait Trait<'a, T>: 'a {}`
+                    // doesn't matter since they can't affect the lifetime / type parameters anyway,
+                    // for bounds like `Self::AssocTy: 'b` which we of course currently also ignore
+                    // (see also #54467) it might conceivably be better to extract the binding
+                    // `AssocTy = U` from the trait object type (which must exist) and thus infer
+                    // an outlives requirement that `U: 'b`.
                     check_explicit_predicates(
                         tcx,
-                        ex_trait_ref.skip_binder().def_id,
+                        trait_ref.def_id(),
                         args,
                         required_predicates,
                         explicit_map,
-                        Some(tcx.types.self_param),
+                        IgnorePredicatesReferencingSelf::Yes,
                     );
                 }
             }
@@ -215,7 +215,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                     args,
                     required_predicates,
                     explicit_map,
-                    None,
+                    IgnorePredicatesReferencingSelf::No,
                 );
             }
 
@@ -244,77 +244,44 @@ fn insert_required_predicates_to_be_wf<'tcx>(
 /// will give us `U: 'static` and `U: Outer`. The latter we
 /// can ignore, but we will want to process `U: 'static`,
 /// applying the instantiation as above.
+#[tracing::instrument(level = "debug", skip(tcx))]
 fn check_explicit_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     args: &[GenericArg<'tcx>],
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
-    ignored_self_ty: Option<Ty<'tcx>>,
+    ignore_preds_refing_self: IgnorePredicatesReferencingSelf,
 ) {
-    debug!(
-        "check_explicit_predicates(def_id={:?}, \
-         args={:?}, \
-         explicit_map={:?}, \
-         required_predicates={:?}, \
-         ignored_self_ty={:?})",
-        def_id, args, explicit_map, required_predicates, ignored_self_ty,
-    );
     let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
-    for (outlives_predicate, &span) in explicit_predicates.as_ref().skip_binder() {
-        debug!("outlives_predicate = {outlives_predicate:?}");
+    for (&predicate @ ty::OutlivesPredicate(arg, _), &span) in
+        explicit_predicates.as_ref().skip_binder()
+    {
+        debug!(?predicate);
 
-        // Careful: If we are inferring the effects of a `dyn Trait<..>`
-        // type, then when we look up the predicates for `Trait`,
-        // we may find some that reference `Self`. e.g., perhaps the
-        // definition of `Trait` was:
-        //
-        // ```
-        // trait Trait<'a, T> where Self: 'a  { .. }
-        // ```
-        //
-        // we want to ignore such predicates here, because
-        // there is no type parameter for them to affect. Consider
-        // a struct containing `dyn Trait`:
-        //
-        // ```
-        // struct MyStruct<'x, X> { field: Box<dyn Trait<'x, X>> }
-        // ```
-        //
-        // The `where Self: 'a` predicate refers to the *existential, hidden type*
-        // that is represented by the `dyn Trait`, not to the `X` type parameter
-        // (or any other generic parameter) declared on `MyStruct`.
-        //
-        // Note that we do this check for self **before** applying `args`. In the
-        // case that `args` come from a `dyn Trait` type, our caller will have
-        // included `Self = usize` as the value for `Self`. If we were
-        // to apply the args, and not filter this predicate, we might then falsely
-        // conclude that e.g., `X: 'x` was a reasonable inferred requirement.
-        //
-        // Another similar case is where we have an inferred
-        // requirement like `<Self as Trait>::Foo: 'b`. We presently
-        // ignore such requirements as well (cc #54467)-- though
-        // conceivably it might be better if we could extract the `Foo
-        // = X` binding from the object type (there must be such a
-        // binding) and thus infer an outlives requirement that `X:
-        // 'b`.
-        if let Some(self_ty) = ignored_self_ty
-            && let GenericArgKind::Type(ty) = outlives_predicate.0.kind()
-            && ty.walk().any(|arg| arg == self_ty.into())
+        if let IgnorePredicatesReferencingSelf::Yes = ignore_preds_refing_self
+            && arg.walk().any(|arg| arg == tcx.types.self_param.into())
         {
-            debug!("skipping self ty = {ty:?}");
+            debug!("ignoring predicate since it references `Self`");
             continue;
         }
 
-        let predicate =
-            explicit_predicates.rebind(*outlives_predicate).instantiate(tcx, args).skip_norm_wip();
-        debug!("predicate = {predicate:?}");
-        insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
+        let predicate @ ty::OutlivesPredicate(arg, region) =
+            explicit_predicates.rebind(predicate).instantiate(tcx, args).skip_norm_wip();
+        debug!(?predicate);
+
+        insert_outlives_predicate(tcx, arg, region, span, required_predicates);
     }
 }
 
-/// Check the inferred predicates declared on the type.
+#[derive(Debug)]
+enum IgnorePredicatesReferencingSelf {
+    Yes,
+    No,
+}
+
+/// Check the inferred predicates of the type.
 ///
 /// ### Example
 ///
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 7a25b5e..4bd3dc8 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1881,7 +1881,7 @@ pub(crate) fn coerce_inner<'a>(
 
                 if let Some(expr) = expression {
                     if let hir::ExprKind::Loop(
-                        _,
+                        block,
                         _,
                         loop_src @ (hir::LoopSource::While | hir::LoopSource::ForLoop),
                         _,
@@ -1894,6 +1894,14 @@ pub(crate) fn coerce_inner<'a>(
                         };
 
                         err.note(format!("{loop_type} evaluate to unit type `()`"));
+                        if loop_src == hir::LoopSource::While
+                            && let Some(pat) = irrefutable_if_let_expr(block)
+                        {
+                            err.span_label(
+                                pat.span,
+                                "this pattern always matches, consider using `loop` instead",
+                            );
+                        }
                     }
 
                     fcx.emit_coerce_suggestions(
@@ -2043,7 +2051,10 @@ fn report_return_mismatched_types<'infcx>(
                     err.span_label(cond_expr.span, "expected this to be `()`");
                 }
                 if expr.can_have_side_effects() {
-                    fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
+                    // Don't suggest semicolon after if expressions as it does not fix the issue
+                    if !matches!(cond_expr.kind, hir::ExprKind::If(..)) {
+                        fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
+                    }
                 }
             }
         }
@@ -2126,6 +2137,24 @@ pub(crate) fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
     }
 }
 
+fn irrefutable_if_let_expr<'hir>(block: &hir::Block<'hir>) -> Option<&'hir hir::Pat<'hir>> {
+    let hir::ExprKind::If(cond, _, _) = block.expr?.kind else {
+        return None;
+    };
+    let hir::ExprKind::Let(let_expr) = cond.kind else {
+        return None;
+    };
+    simple_irrefutable_pattern(let_expr.pat).then_some(let_expr.pat)
+}
+
+fn simple_irrefutable_pattern(pat: &hir::Pat<'_>) -> bool {
+    match pat.kind {
+        hir::PatKind::Wild | hir::PatKind::Binding(_, _, _, None) => true,
+        hir::PatKind::Tuple(pats, _) => pats.iter().all(simple_irrefutable_pattern),
+        _ => false,
+    }
+}
+
 /// Recursively visit goals to decide whether an unsizing is possible.
 /// `Break`s when it isn't, and an error should be raised.
 /// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 3d2d617..9b928e8 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -184,7 +184,7 @@ fn instantiate_var<R: PredicateEmittingRelation<Self>>(
 
                 relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
             } else {
-                let Some(source_alias) = source_term.to_alias_term(self.tcx) else {
+                let Some(source_alias) = source_term.to_alias_term() else {
                     bug!("generalized `{source_term:?} to infer, not an alias");
                 };
                 match source_alias.kind(self.tcx) {
@@ -207,7 +207,7 @@ fn instantiate_var<R: PredicateEmittingRelation<Self>>(
                     }
                     ty::AliasTermKind::InherentConst { .. }
                     | ty::AliasTermKind::FreeConst { .. }
-                    | ty::AliasTermKind::UnevaluatedConst { .. } => {
+                    | ty::AliasTermKind::AnonConst { .. } => {
                         return Err(TypeError::CyclicConst(source_term.expect_const()));
                     }
                 }
@@ -701,6 +701,7 @@ fn consts(
         c: ty::Const<'tcx>,
         c2: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        let tcx = self.cx();
         assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
 
         match c.kind() {
@@ -741,7 +742,7 @@ fn consts(
                             {
                                 variable_table.union(vid, new_var_id);
                             }
-                            Ok(ty::Const::new_var(self.cx(), new_var_id))
+                            Ok(ty::Const::new_var(tcx, new_var_id))
                         }
                     }
                 }
@@ -755,19 +756,18 @@ fn consts(
                 // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
                 // path), as doing this new No path breaks some GCE things. I expect GCE to be
                 // ripped out soon so this shouldn't matter soon.
-                StructurallyRelateAliases::No if !self.cx().features().generic_const_exprs() => {
-                    self.generalize_alias_term(ty::AliasTerm::from_unevaluated_const(self.cx(), uv))
-                        .map(|v| v.expect_const())
+                StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => {
+                    self.generalize_alias_term(uv.into()).map(|v| v.expect_const())
                 }
                 _ => {
-                    let ty::UnevaluatedConst { def, args } = uv;
+                    let ty::UnevaluatedConst { kind, args, .. } = uv;
                     let args = self.relate_with_variance(
                         ty::Invariant,
                         ty::VarianceDiagInfo::default(),
                         args,
                         args,
                     )?;
-                    Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
+                    Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(tcx, kind, args)))
                 }
             },
             ty::ConstKind::Placeholder(placeholder) => {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 0837e77..0498d83 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -782,8 +782,8 @@ macro_rules! tracked {
     );
     tracked!(crate_attr, vec!["abc".to_string()]);
     tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
-    tracked!(debug_info_for_profiling, true);
     tracked!(debug_info_type_line_numbers, true);
+    tracked!(debuginfo_for_profiling, true);
     tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden));
     tracked!(dep_info_omit_d_target, true);
     tracked!(direct_access_external_data, Some(true));
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index caa41fd..8f908cf 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4529,28 +4529,21 @@
     ///
     /// ### Example
     ///
-    /// ```rust,compile_fail
-    /// #![deny(ambiguous_glob_imports)]
-    /// pub fn foo() -> u32 {
-    ///     use sub::*;
-    ///     C
-    /// }
+    /// ```rust,ignore (needs extern crate)
+    /// // library crate `my_library`
+    /// mod mod1 { pub const C: u32 = 1; }
+    /// mod mod2 { pub const C: u32 = 2; }
+    /// pub use mod1::*;
+    /// pub use mod2::*;
     ///
-    /// mod sub {
-    ///     mod mod1 { pub const C: u32 = 1; }
-    ///     mod mod2 { pub const C: u32 = 2; }
-    ///
-    ///     pub use mod1::*;
-    ///     pub use mod2::*;
-    /// }
+    /// // another crate using `my_library`
+    /// let c = my_library::C; // `C` is ambiguous
     /// ```
     ///
-    /// {{produces}}
-    ///
     /// ### Explanation
     ///
-    /// Previous versions of Rust compile it successfully because it
-    /// had lost the ambiguity error when resolve `use sub::mod2::*`.
+    /// Previous versions of Rust compile it successfully because
+    /// ambiguous glob imports weren't preserved correctly over crate boundaries.
     ///
     /// This is a [future-incompatible] lint to transition this to a
     /// hard error in the future.
@@ -5453,8 +5446,7 @@
     ///
     /// ### Example
     ///
-    #[cfg_attr(bootstrap, doc = "```rust")]
-    #[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")]
+    /// ```rust,compile_fail
     /// // Using `...` in non-foreign function definitions is unstable, however stability is
     /// // currently only checked after attributes are expanded, so using `#[cfg(false)]` here will
     /// // allow this to compile on stable Rust.
@@ -5462,7 +5454,7 @@
     /// fn foo(...) {
     ///
     /// }
-    #[doc = "```"]
+    /// ```
     ///
     /// {{produces}}
     ///
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index ed1b75b..5be8bd4 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -411,6 +411,16 @@ fn main() {
             continue;
         }
 
+        // On apple-darwin, llvm-config reports the versioned shared library name such as LLVM-22-..., but
+        // the distributed toolchain ships libLLVM.dylib. Normalize the link name here.
+        let name =
+            if target.contains("apple-darwin") && llvm_kind == "dylib" && name.starts_with("LLVM-")
+            {
+                "LLVM"
+            } else {
+                name
+            };
+
         let kind = if name.starts_with("LLVM") {
             llvm_kind
         } else if is_static {
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index b03a075..8a6caa9 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -49,6 +49,9 @@
 #include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
 #include "llvm/Transforms/Scalar/AnnotationRemarks.h"
+#if LLVM_VERSION_GE(23, 0)
+#include "llvm/Transforms/Utils/AssignGUID.h"
+#endif
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
@@ -915,6 +918,9 @@
   if (NeedThinLTOBufferPasses) {
     MPM.addPass(CanonicalizeAliasesPass());
     MPM.addPass(NameAnonGlobalPass());
+#if LLVM_VERSION_GE(23, 0)
+    MPM.addPass(AssignGUIDPass());
+#endif
   }
   // For `-Copt-level=0`, and the pre-link fat/thin LTO stages.
   if (ThinLTOBufferRef && *ThinLTOBufferRef == nullptr) {
@@ -1454,6 +1460,9 @@
         PB.registerLoopAnalyses(LAM);
         PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
         ModulePassManager MPM;
+#if LLVM_VERSION_GE(23, 0)
+        MPM.addPass(AssignGUIDPass());
+#endif
         MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
         MPM.run(*unwrap(M), MAM);
       } else {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index b64cb88..bfe7e01 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -62,12 +62,15 @@ pub fn walk_native_lib_search_dirs<R>(
         f(&sess.target_tlib_path.dir.join("self-contained"), false)?;
     }
 
+    let has_shared_llvm_apple_darwin =
+        sess.target.is_like_darwin && sess.target_tlib_path.dir.join("libLLVM.dylib").exists();
+
     // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
     // library directory instead of the self-contained directories.
     // Sanitizer libraries have the same issue and are also linked by name on Apple targets.
     // The targets here should be in sync with `copy_third_party_objects` in bootstrap.
-    // Finally there is shared LLVM library, which unlike compiler libraries, is linked by the name,
-    // therefore requiring the search path for the linker.
+    // On Apple targets, shared LLVM is linked by name, so when `libLLVM.dylib` is
+    // present in the target libdir, add that directory to the linker search path.
     // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
     // and sanitizers to self-contained directory, and stop adding this search path.
     // FIXME: On AIX this also has the side-effect of making the list of library search paths
@@ -77,7 +80,8 @@ pub fn walk_native_lib_search_dirs<R>(
         || sess.target.os == Os::Linux
         || sess.target.os == Os::Fuchsia
         || sess.target.is_like_aix
-        || sess.target.is_like_darwin && !sess.sanitizers().is_empty()
+        || sess.target.is_like_darwin
+            && (!sess.sanitizers().is_empty() || has_shared_llvm_apple_darwin)
         || sess.target.os == Os::Windows
             && sess.target.env == Env::Gnu
             && sess.target.cfg_abi == CfgAbi::Llvm
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a0db004..1483de5 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -12,7 +12,7 @@
 use rustc_data_structures::thousands::usize_with_underscores;
 use rustc_hir as hir;
 use rustc_hir::attrs::{AttributeKind, EncodeCrossCrate};
-use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
+use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::find_attr;
 use rustc_hir_pretty::id_to_string;
@@ -510,18 +510,20 @@ fn encode_symbol_or_byte_symbol(
     }
 
     fn encode_def_path_table(&mut self) {
-        let table = self.tcx.def_path_table();
+        let defs = self.tcx.definitions();
         if self.is_proc_macro {
-            for def_index in std::iter::once(CRATE_DEF_INDEX)
-                .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
+            for def_id in std::iter::once(CRATE_DEF_ID)
+                .chain(self.tcx.resolutions(()).proc_macros.iter().copied())
             {
-                let def_key = self.lazy(table.def_key(def_index));
-                let def_path_hash = table.def_path_hash(def_index);
-                self.tables.def_keys.set_some(def_index, def_key);
-                self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64());
+                let def_key = self.lazy(defs.def_key(def_id));
+                let def_path_hash = defs.def_path_hash(def_id);
+                self.tables.def_keys.set_some(def_id.local_def_index, def_key);
+                self.tables
+                    .def_path_hashes
+                    .set(def_id.local_def_index, def_path_hash.local_hash().as_u64());
             }
         } else {
-            for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
+            for (def_index, def_key, def_path_hash) in defs.enumerated_keys_and_path_hashes() {
                 let def_key = self.lazy(def_key);
                 self.tables.def_keys.set_some(def_index, def_key);
                 self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64());
@@ -2034,7 +2036,6 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
 
                 let def_id = id.to_def_id();
                 self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into()));
-                self.tables.proc_macro.set_some(def_id.index, macro_kind);
                 self.encode_attrs(id);
                 record!(self.tables.def_keys[def_id] <- def_key);
                 record!(self.tables.def_ident_span[def_id] <- span);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a3645a5..6a396fa 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -464,7 +464,6 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
     variant_data: Table<DefIndex, LazyValue<VariantData>>,
     assoc_container: Table<DefIndex, LazyValue<ty::AssocContainer>>,
     macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
-    proc_macro: Table<DefIndex, MacroKind>,
     deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
     collect_return_position_impl_trait_in_trait_tys: Table<DefIndex, LazyValue<DefIdMap<ty::EarlyBinder<'static, Ty<'static>>>>>,
     doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 8deb75d..29799fe 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -495,7 +495,8 @@ pub fn new(value: MaybeOwner<'tcx>, def_id: LocalDefId) -> Self {
                 delayed_lints: &o.delayed_lints,
             }),
             MaybeOwner::NonOwner(hir_id) => ProjectedMaybeOwner::NonOwner(hir_id),
-            MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
+            // Can't debug fmt `def_id` since it doesn't exist.
+            MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id.local_def_index),
         }
     }
 
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index a9e547b..a018951 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -37,6 +37,7 @@
 #![feature(core_intrinsics)]
 #![feature(debug_closure_helpers)]
 #![feature(decl_macro)]
+#![feature(default_field_values)]
 #![feature(deref_patterns)]
 #![feature(discriminant_kind)]
 #![feature(extern_types)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 94a7f4d..18f93e0 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -272,7 +272,7 @@ pub struct SanitizerFnAttrs {
     pub rtsan_setting: RtsanSetting,
 }
 
-impl const Default for SanitizerFnAttrs {
+const impl Default for SanitizerFnAttrs {
     fn default() -> Self {
         Self { disabled: SanitizerSet::empty(), rtsan_setting: RtsanSetting::default() }
     }
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index a0e4c28..8a2595e 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -55,6 +55,25 @@ pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKin
         }
     }
 
+    /// Given a [`DefId`], returns whether it is one of the built-in callable
+    /// traits: `Fn`/`FnMut`/`FnOnce` or `AsyncFn`/`AsyncFnMut`/`AsyncFnOnce`.
+    ///
+    /// These built-in callable traits all model their inputs using the
+    /// `rust-call` ABI, which is tupled at the type level.
+    pub fn is_callable_trait(self, id: DefId) -> bool {
+        matches!(
+            self.as_lang_item(id),
+            Some(
+                LangItem::Fn
+                    | LangItem::FnMut
+                    | LangItem::FnOnce
+                    | LangItem::AsyncFn
+                    | LangItem::AsyncFnMut
+                    | LangItem::AsyncFnOnce
+            )
+        )
+    }
+
     /// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family
     /// trait, if it is defined.
     pub fn fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option<DefId> {
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 2e9cd31..39c7335 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -467,9 +467,13 @@ pub struct UnevaluatedConst<'tcx> {
 
 impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
-    pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
+    pub fn shrink(self, tcx: TyCtxt<'tcx>) -> ty::UnevaluatedConst<'tcx> {
         assert_eq!(self.promoted, None);
-        ty::UnevaluatedConst { def: self.def, args: self.args }
+        ty::UnevaluatedConst::new(
+            tcx,
+            ty::UnevaluatedConstKind::new_from_def_id(tcx, self.def),
+            self.args,
+        )
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 00ac8e6..6bd1bbe 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -103,7 +103,7 @@ pub fn const_eval_resolve_for_typeck(
             bug!("did not expect inference variables here");
         }
 
-        let cid = match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
+        let cid = match ty::Instance::try_resolve(self, typing_env, ct.kind.def_id(), ct.args) {
             Ok(Some(instance)) => GlobalId { instance, promoted: None },
             // For errors during resolution, we deliberately do not point at the usage site of the constant,
             // since for these errors the place the constant is used shouldn't matter.
@@ -138,11 +138,11 @@ pub fn const_eval_resolve_for_typeck(
             {
                 let mir_body = self.mir_for_ctfe(cid.instance.def_id());
                 if mir_body.is_polymorphic {
-                    let Some(local_def_id) = ct.def.as_local() else { return };
+                    let Some(local_def_id) = ct.kind.def_id().as_local() else { return };
                     self.emit_node_span_lint(
                         lint::builtin::CONST_EVALUATABLE_UNCHECKED,
                         self.local_def_id_to_hir_id(local_def_id),
-                        self.def_span(ct.def),
+                        self.def_span(ct.kind.def_id()),
                         rustc_errors::DiagDecorator(|lint| {
                             lint.primary_message(
                                 "cannot use constants which depend on generic parameters in types",
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 60c8293..8c6d2dc 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -15,6 +15,7 @@
 };
 use crate::mir::visit::Visitor;
 use crate::mir::*;
+use crate::ty::CoroutineArgsExt;
 
 const INDENT: &str = "    ";
 /// Alignment for lining up comments following MIR statements
@@ -185,9 +186,6 @@ pub fn dump_mir_to_writer(&self, body: &Body<'tcx>, w: &mut dyn io::Write) -> io
             Some(promoted) => write!(w, "::{promoted:?}`")?,
         }
         writeln!(w, " {} {}", self.disambiguator, self.pass_name)?;
-        if let Some(ref layout) = body.coroutine_layout_raw() {
-            writeln!(w, "/* coroutine_layout = {layout:#?} */")?;
-        }
         writeln!(w)?;
         (self.writer.extra_data)(PassWhere::BeforeCFG, w)?;
         write_user_type_annotations(self.tcx(), body, w)?;
@@ -429,6 +427,31 @@ fn write_scope_tree(
         }
     }
 
+    // Coroutine debuginfo.
+    if let Some(layout) = body.coroutine_layout_raw() {
+        for (field, name) in layout.field_names.iter_enumerated() {
+            let source_info = layout.field_tys[field].source_info;
+            if let Some(name) = name
+                && source_info.scope == parent
+            {
+                let indented_debug_info =
+                    format!("{0:1$}coroutine debug {2} => {3:?};", INDENT, indent, name, field);
+
+                if options.include_extra_comments {
+                    writeln!(
+                        w,
+                        "{0:1$} // in {2}",
+                        indented_debug_info,
+                        ALIGN,
+                        comment(tcx, source_info),
+                    )?;
+                } else {
+                    writeln!(w, "{indented_debug_info}")?;
+                }
+            }
+        }
+    }
+
     // Local variable types.
     for (local, local_decl) in body.local_decls.iter_enumerated() {
         if (1..body.arg_count + 1).contains(&local.index()) {
@@ -530,6 +553,50 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
     }
 }
 
+fn write_coroutine_layout<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    layout: &CoroutineLayout<'_>,
+    w: &mut dyn io::Write,
+    options: PrettyPrintMirOptions,
+) -> io::Result<()> {
+    let CoroutineLayout {
+        field_tys,
+        field_names: _, // Dumped in scope tree with debug info.
+        variant_fields,
+        variant_source_info,
+        storage_conflicts,
+    } = layout;
+
+    writeln!(w, "{INDENT}coroutine layout {{")?;
+
+    for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits }) in
+        field_tys.iter_enumerated()
+    {
+        let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" };
+        let indented_body = format!("{INDENT}{INDENT}field {field:?}: {ty}{ignore_for_traits};",);
+        if options.include_extra_comments {
+            writeln!(w, "{0:ALIGN$} // in {1}", indented_body, comment(tcx, *source_info))?;
+        } else {
+            writeln!(w, "{}", indented_body)?;
+        }
+    }
+
+    writeln!(w, "{INDENT}{INDENT}variant_fields = {{")?;
+    for (variant, fields) in variant_fields.iter_enumerated() {
+        let variant_name = ty::CoroutineArgs::variant_name(variant);
+        let header = format!("{INDENT}{INDENT}{INDENT}{variant_name:9}({variant:?}): {fields:?},");
+        if options.include_extra_comments {
+            let source_info = variant_source_info[variant];
+            writeln!(w, "{0:ALIGN$} // in {1}", header, comment(tcx, source_info))?;
+        } else {
+            writeln!(w, "{}", header)?;
+        }
+    }
+    writeln!(w, "{INDENT}{INDENT}}}")?;
+    writeln!(w, "{INDENT}{INDENT}storage_conflicts = {storage_conflicts:?}")?;
+    writeln!(w, "{INDENT}}}")
+}
+
 /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
 /// local variables (both user-defined bindings and compiler temporaries).
 fn write_mir_intro<'tcx>(
@@ -541,6 +608,10 @@ fn write_mir_intro<'tcx>(
     write_mir_sig(tcx, body, w)?;
     writeln!(w, "{{")?;
 
+    if let Some(ref layout) = body.coroutine_layout_raw() {
+        write_coroutine_layout(tcx, layout, w, options)?;
+    }
+
     // construct a scope tree and write it out
     let mut scope_tree: FxHashMap<SourceScope, Vec<SourceScope>> = Default::default();
     for (index, scope_data) in body.source_scopes.iter_enumerated() {
@@ -920,10 +991,7 @@ pub fn fmt_head<W: fmt::Write>(&self, fmt: &mut W) -> fmt::Result {
             }
             Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
             Unreachable => write!(fmt, "unreachable"),
-            Drop { place, async_fut: None, .. } => write!(fmt, "drop({place:?})"),
-            Drop { place, async_fut: Some(async_fut), .. } => {
-                write!(fmt, "async drop({place:?}; poll={async_fut:?})")
-            }
+            Drop { place, .. } => write!(fmt, "drop({place:?})"),
             Call { func, args, destination, .. } => {
                 write!(fmt, "{destination:?} = ")?;
                 write!(fmt, "{func:?}(")?;
@@ -1429,7 +1497,11 @@ fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _location: Loca
                 Const::Ty(_, ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("ty::Param({p})"),
                     ty::ConstKind::Unevaluated(uv) => {
-                        format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
+                        format!(
+                            "ty::Unevaluated({}, {:?})",
+                            self.tcx.def_path_str(uv.kind.def_id()),
+                            uv.args,
+                        )
                     }
                     ty::ConstKind::Value(cv) => {
                         format!("ty::Valtree({})", fmt_valtree(&cv))
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 4c619f82..f25eaf3 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -624,11 +624,7 @@ pub fn function_handle(
         span: Span,
     ) -> Self {
         let ty = Ty::new_fn_def(tcx, def_id, args);
-        Operand::Constant(Box::new(ConstOperand {
-            span,
-            user_ty: None,
-            const_: Const::Val(ConstValue::ZeroSized, ty),
-        }))
+        Operand::zero_sized_constant(ty, span)
     }
 
     /// Convenience helper to make a constant that refers to the given `DefId` and args. Since this
@@ -643,6 +639,12 @@ pub fn unevaluated_constant(
         Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
     }
 
+    /// Convenience helper to make a constant that refers to a zero-sized type.
+    pub fn zero_sized_constant(ty: Ty<'tcx>, span: Span) -> Self {
+        let const_ = Const::Val(ConstValue::ZeroSized, ty);
+        Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
+    }
+
     pub fn is_move(&self) -> bool {
         matches!(self, Operand::Move(..))
     }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 8b015e6..91ff3f5 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -760,21 +760,16 @@ pub enum TerminatorKind<'tcx> {
     /// meaning.
     ///
     /// Async drop processing:
-    /// In compiler/rustc_mir_build/src/build/scope.rs we detect possible async drop:
-    ///   drop of object with `needs_async_drop`.
-    /// Async drop later, in StateTransform pass, may be expanded into additional yield-point
-    ///   for poll-loop of async drop future.
-    /// So we need prepared 'drop' target block in the similar way as for `Yield` terminator
-    ///   (see `drops.build_mir::<CoroutineDrop>` in scopes.rs).
-    /// In compiler/rustc_mir_transform/src/elaborate_drops.rs for object implementing `AsyncDrop` trait
-    ///   we need to prepare async drop feature - resolve `AsyncDrop::drop` and codegen call.
-    /// `async_fut` is set to the corresponding local.
-    /// For coroutine drop we don't need this logic because coroutine drop works with the same
-    ///   layout object as coroutine itself. So `async_fut` will be `None` for coroutine drop.
-    /// Both `drop` and `async_fut` fields are only used in compiler/rustc_mir_transform/src/coroutine.rs,
-    ///   StateTransform pass. In `expand_async_drops` async drops are expanded
-    ///   into one or two yield points with poll ready/pending switch.
-    /// When a coroutine has any internal async drop, the coroutine drop function will be async
+    ///   MIR building detects possible async drops, and constructs a complete CFG. To correctly
+    ///   handle the coroutine being dropped while itself drops, we need a 'drop' target
+    ///   similar to `Yield` terminator (see `drops.build_mir::<CoroutineDrop>`).
+    ///
+    ///   Drop elaboration later refines the set of useful async drops. If there is no need for an
+    ///   async drop, it is downgraded to a sync drop by setting `drop` to `None` If this is an
+    ///   actual async drop, it is expanded to an `await` loop over the `async_drop_in_place` or
+    ///   `AsyncDrop::drop` coroutine.
+    ///
+    ///   When a coroutine has any internal async drop, the coroutine drop function will be async
     ///   (generated by `create_coroutine_drop_shim_async`, not `create_coroutine_drop_shim`).
     Drop {
         place: Place<'tcx>,
@@ -783,8 +778,6 @@ pub enum TerminatorKind<'tcx> {
         replace: bool,
         /// Cleanup to be done if the coroutine is dropped at this suspend point (for async drop).
         drop: Option<BasicBlock>,
-        /// Prepared async future local (for async drop)
-        async_fut: Option<Local>,
     },
 
     /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
@@ -872,11 +865,18 @@ pub enum TerminatorKind<'tcx> {
     /// Marks a suspend point.
     ///
     /// Like `Return` terminators in coroutine bodies, this computes `value` and then a
-    /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
-    /// the return place of the function calling this one, and execution continues in the calling
-    /// function. When next invoked with the same first argument, execution of this function
-    /// continues at the `resume` basic block, with the second argument written to the `resume_arg`
-    /// place. If the coroutine is dropped before then, the `drop` basic block is invoked.
+    /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned
+    /// to the return place provided by the caller function, and execution continues in this caller
+    /// function.
+    ///
+    /// When the coroutine is resumed/polled, execution of this function continues at the `resume`
+    /// basic block, the `resume_arg` place is evaluated and the second argument to `resume/poll`
+    /// is written to it.
+    ///
+    /// If the coroutine is dropped before then, execution of this function continues at the `drop`
+    /// basic block and the `resume_arg` place expression is evaluated. For async drop, the second
+    /// argument to the destructor `resume/poll` method is written to `resume_arg`. For synchronous
+    /// drops, uninitialized bytes are written to `resume_arg`.
     ///
     /// Note that coroutines can be (unstably) cloned under certain conditions, which means that
     /// this terminator can **return multiple times**! MIR optimizations that reorder code into
@@ -884,8 +884,6 @@ pub enum TerminatorKind<'tcx> {
     /// See <https://github.com/rust-lang/rust/issues/95360>.
     ///
     /// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.
-    ///
-    /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?
     Yield {
         /// The value to return.
         value: Operand<'tcx>,
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 1cd11bb..741ba8a 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -674,7 +674,7 @@ pub fn as_goto(&self) -> Option<BasicBlock> {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Debug)]
 pub enum TerminatorEdges<'mir, 'tcx> {
     /// For terminators that have no successor, like `return`.
     None,
@@ -686,7 +686,7 @@ pub enum TerminatorEdges<'mir, 'tcx> {
     Double(BasicBlock, BasicBlock),
     /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
     AssignOnReturn {
-        return_: &'mir [BasicBlock],
+        return_: Box<[BasicBlock]>,
         /// The cleanup block, if it exists.
         cleanup: Option<BasicBlock>,
         place: CallReturnPlaces<'mir, 'tcx>,
@@ -743,7 +743,7 @@ pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
             // FIXME: Maybe we need also TerminatorEdges::Trio for async drop
             // (target + unwind + dropline)
             Assert { target, unwind, expected: _, msg: _, cond: _ }
-            | Drop { target, unwind, place: _, replace: _, drop: _, async_fut: _ }
+            | Drop { target, unwind, place: _, replace: _, drop: _ }
             | FalseUnwind { real_target: target, unwind } => match unwind {
                 UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
                 UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => {
@@ -755,27 +755,21 @@ pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
                 TerminatorEdges::Double(real_target, imaginary_target)
             }
 
-            Yield { resume: ref target, drop, resume_arg, value: _ } => {
+            Yield { resume: target, drop, resume_arg, value: _ } => {
                 TerminatorEdges::AssignOnReturn {
-                    return_: slice::from_ref(target),
-                    cleanup: drop,
+                    return_: [target].into_iter().chain(drop.into_iter()).collect(),
+                    cleanup: None,
                     place: CallReturnPlaces::Yield(resume_arg),
                 }
             }
 
-            Call {
-                unwind,
-                destination,
-                ref target,
-                func: _,
-                args: _,
-                fn_span: _,
-                call_source: _,
-            } => TerminatorEdges::AssignOnReturn {
-                return_: target.as_ref().map(slice::from_ref).unwrap_or_default(),
-                cleanup: unwind.cleanup_block(),
-                place: CallReturnPlaces::Call(destination),
-            },
+            Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
+                TerminatorEdges::AssignOnReturn {
+                    return_: target.into_iter().collect(),
+                    cleanup: unwind.cleanup_block(),
+                    place: CallReturnPlaces::Call(destination),
+                }
+            }
 
             InlineAsm {
                 asm_macro: _,
@@ -786,7 +780,7 @@ pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
                 ref targets,
                 unwind,
             } => TerminatorEdges::AssignOnReturn {
-                return_: targets,
+                return_: targets.to_owned(),
                 cleanup: unwind.cleanup_block(),
                 place: CallReturnPlaces::InlineAsm(operands),
             },
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index e6e911d..fbe22ec 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -555,20 +555,12 @@ fn super_terminator(
                         unwind: _,
                         replace: _,
                         drop: _,
-                        async_fut,
                     } => {
                         self.visit_place(
                             place,
                             PlaceContext::MutatingUse(MutatingUseContext::Drop),
                             location
                         );
-                        if let Some(async_fut) = async_fut {
-                            self.visit_local(
-                                $(&$mutability)? *async_fut,
-                                PlaceContext::MutatingUse(MutatingUseContext::Borrow),
-                                location
-                            );
-                        }
                     }
 
                     TerminatorKind::Call {
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 569c30a..346a26a 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -36,6 +36,8 @@ pub trait QueryKey: Sized + QueryKeyBounds {
     /// [`QueryCache`]: rustc_middle::query::QueryCache
     type Cache<V> = DefaultCache<Self, V>;
 
+    type LocalQueryKey = !;
+
     /// In the event that a cycle occurs, if no explicit span has been
     /// given for a query with key `self`, what span should we use?
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span;
@@ -45,14 +47,12 @@ pub trait QueryKey: Sized + QueryKeyBounds {
     fn key_as_def_id(&self) -> Option<DefId> {
         None
     }
-}
-
-pub trait AsLocalQueryKey: QueryKey {
-    type LocalQueryKey;
 
     /// Given an instance of this key, what crate is it referring to?
     /// This is used to find the provider.
-    fn as_local_key(&self) -> Option<Self::LocalQueryKey>;
+    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
+        None
+    }
 }
 
 impl QueryKey for () {
@@ -96,13 +96,11 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 impl QueryKey for CrateNum {
     type Cache<V> = VecCache<Self, V, DepNodeIndex>;
 
+    type LocalQueryKey = LocalCrate;
+
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
     }
-}
-
-impl AsLocalQueryKey for CrateNum {
-    type LocalQueryKey = LocalCrate;
 
     #[inline(always)]
     fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
@@ -136,6 +134,7 @@ fn key_as_def_id(&self) -> Option<DefId> {
 
 impl QueryKey for DefId {
     type Cache<V> = DefIdCache<V>;
+    type LocalQueryKey = LocalDefId;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
@@ -145,10 +144,6 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
     fn key_as_def_id(&self) -> Option<DefId> {
         Some(*self)
     }
-}
-
-impl AsLocalQueryKey for DefId {
-    type LocalQueryKey = LocalDefId;
 
     #[inline(always)]
     fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
@@ -197,13 +192,11 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl QueryKey for (CrateNum, DefId) {
+    type LocalQueryKey = DefId;
+
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
     }
-}
-
-impl AsLocalQueryKey for (CrateNum, DefId) {
-    type LocalQueryKey = DefId;
 
     #[inline(always)]
     fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
@@ -212,13 +205,11 @@ fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
 }
 
 impl QueryKey for (CrateNum, SimplifiedType) {
+    type LocalQueryKey = SimplifiedType;
+
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
     }
-}
-
-impl AsLocalQueryKey for (CrateNum, SimplifiedType) {
-    type LocalQueryKey = SimplifiedType;
 
     #[inline(always)]
     fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index b7e5e9b..1eafd0a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -3,7 +3,7 @@
 pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
 pub use self::into_query_key::IntoQueryKey;
 pub use self::job::{QueryJob, QueryJobId, QueryLatch, QueryWaiter};
-pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
+pub use self::keys::{LocalCrate, QueryKey};
 pub use self::plumbing::{
     ActiveKeyStatus, Cycle, EnsureMode, QueryMode, QueryState, QuerySystem, QueryVTable, TyCtxtAt,
     TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 8cc5e81..8fa0587 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -14,7 +14,7 @@
 use crate::ich::StableHashState;
 use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
 use crate::query::on_disk_cache::OnDiskCache;
-use crate::query::{IntoQueryKey, QueryCache, QueryJob, QueryStackFrame};
+use crate::query::{IntoQueryKey, QueryCache, QueryJob, QueryKey, QueryStackFrame};
 use crate::ty::{self, TyCtxt};
 
 /// For a particular query, keeps track of "active" keys, i.e. keys whose
@@ -86,6 +86,9 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
     /// True if this query has the `feedable` modifier.
     pub feedable: bool,
 
+    pub cache_on_disk_local: bool,
+    pub separate_provide_extern: bool,
+
     pub dep_kind: DepKind,
     pub state: QueryState<'tcx, C::Key>,
     pub cache: C,
@@ -97,11 +100,9 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
     /// This should be the only code that calls the provider function.
     pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
 
-    pub will_cache_on_disk_for_key_fn: fn(key: C::Key) -> bool,
-
     /// Function pointer that tries to load a query value from disk.
     ///
-    /// This should only be called after a successful check of `will_cache_on_disk_for_key_fn`.
+    /// This should only be called after a successful check of [`Self::will_cache_on_disk_for_key`].
     pub try_load_from_disk_fn:
         fn(tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) -> Option<C::Value>,
 
@@ -133,6 +134,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
     pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
 }
 
+impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> {
+    pub fn will_cache_on_disk_for_key(&self, key: C::Key) -> bool {
+        self.cache_on_disk_local && (!self.separate_provide_extern || key.as_local_key().is_some())
+    }
+}
+
 impl<'tcx, C: QueryCache> fmt::Debug for QueryVTable<'tcx, C> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // When debug-printing a query vtable (e.g. for ICE or tracing),
@@ -328,7 +335,7 @@ pub mod $name {
                 /// This query has the `separate_provide_extern` modifier.
                 #[cfg($separate_provide_extern)]
                 pub type LocalKey<'tcx> =
-                    <Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey;
+                    <Key<'tcx> as $crate::query::QueryKey>::LocalQueryKey;
                 /// Key type used by provider functions in `local_providers`.
                 #[cfg(not($separate_provide_extern))]
                 pub type LocalKey<'tcx> = Key<'tcx>;
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index c6fa6eb..984c9ec 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -52,15 +52,17 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             }
             fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
                 let ct = match c.kind() {
-                    ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
-                        Err(e) => ty::Const::new_error(self.tcx, e),
-                        Ok(Some(bac)) => {
-                            let args = self.tcx.erase_and_anonymize_regions(uv.args);
-                            let bac = bac.instantiate(self.tcx, args).skip_norm_wip();
-                            return bac.fold_with(self);
+                    ty::ConstKind::Unevaluated(uv) => {
+                        match self.tcx.thir_abstract_const(uv.kind.def_id()) {
+                            Err(e) => ty::Const::new_error(self.tcx, e),
+                            Ok(Some(bac)) => {
+                                let args = self.tcx.erase_and_anonymize_regions(uv.args);
+                                let bac = bac.instantiate(self.tcx, args).skip_norm_wip();
+                                return bac.fold_with(self);
+                            }
+                            Ok(None) => c,
                         }
-                        Ok(None) => c,
-                    },
+                    }
                     _ => c,
                 };
                 ct.super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 7421024..30d9a9f 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -22,9 +22,10 @@
 
 pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
 pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
+pub type UnevaluatedConstKind<'tcx> = ir::UnevaluatedConstKind<TyCtxt<'tcx>>;
 
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
+rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, StableHash)]
 #[rustc_pass_by_value]
@@ -107,7 +108,6 @@ pub fn new_placeholder(
 
     #[inline]
     pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
-        tcx.debug_assert_args_compatible(uv.def, uv.args);
         Const::new(tcx, ty::ConstKind::Unevaluated(uv))
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 9610956..8c5421d 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -325,10 +325,32 @@ pub struct CommonTypes<'tcx> {
     pub never: Ty<'tcx>,
     pub self_param: Ty<'tcx>,
 
-    /// Dummy type used for the `Self` of a `TraitRef` created for converting
-    /// a trait object, and which gets removed in `ExistentialTraitRef`.
-    /// This type must not appear anywhere in other converted types.
-    /// `Infer(ty::FreshTy(0))` does the job.
+    /// A dummy type that can be used as the self type of trait object types outside of
+    /// [`ty::ExistentialTraitRef`], [`ty::ExistentialProjection`], etc.
+    ///
+    /// This is most useful or even necessary when you want to manipulate existential predicates
+    /// together with normal predicates or if you want to pass them to an API that only expects
+    /// normal predicates.
+    ///
+    /// Indeed, you can sometimes use the trait object type itself as the self type instead of this
+    /// dummy type. However, that's not always correct: For example, if said trait object type can
+    /// also appear "naturally" in whatever type system entity you're working with (like predicates)
+    /// but you still need to be able to identify the erased self type later on.
+    /// That's when this dummy type comes in handy.
+    ///
+    /// HIR ty lowering guarantees / has to guarantee that this dummy type doesn't appear in the
+    /// lowered types, so you can "freely" use it (see warning below).
+    ///
+    /// <div class="warning">
+    ///
+    /// Under the hood, this type is just `ty::Infer(ty::FreshTy(0))`. Consequently, you must be
+    /// sure that fresh types cannot appear by other means in whatever type system entity you're
+    /// working with.
+    ///
+    /// Keep uses of this dummy type as local as possible and try not to leak it to subsequent
+    /// passes!
+    ///
+    /// </div>
     pub trait_object_dummy_self: Ty<'tcx>,
 
     /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
@@ -1349,13 +1371,13 @@ pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> {
         }
     }
 
-    pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
+    pub fn definitions(self) -> &'tcx rustc_hir::definitions::Definitions {
         // Depend on the `analysis` query to ensure compilation if finished.
         self.ensure_ok().analysis(());
 
         // Freeze definitions once we start iterating on them, to prevent adding new ones
         // while iterating. If some query needs to add definitions, it should be `ensure`d above.
-        self.untracked.definitions.freeze().def_path_table()
+        self.untracked.definitions.freeze()
     }
 
     pub fn def_path_hash_to_def_index_map(
diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs
index 7f1eeda..bc8b83e 100644
--- a/compiler/rustc_middle/src/ty/context/impl_interner.rs
+++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs
@@ -219,6 +219,26 @@ fn alias_ty_kind_from_def_id(self, def_id: DefId) -> ty::AliasTyKind<'tcx> {
         }
     }
 
+    fn unevaluated_const_kind_from_def_id(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::UnevaluatedConstKind<'tcx> {
+        match self.def_kind(def_id) {
+            DefKind::AssocConst { .. } => {
+                if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) {
+                    ty::UnevaluatedConstKind::Inherent { def_id }
+                } else {
+                    ty::UnevaluatedConstKind::Projection { def_id }
+                }
+            }
+            DefKind::Const { .. } => ty::UnevaluatedConstKind::Free { def_id },
+            DefKind::AnonConst | DefKind::InlineConst | DefKind::Ctor(_, CtorKind::Const) => {
+                ty::UnevaluatedConstKind::Anon { def_id }
+            }
+            kind => bug!("unexpected DefKind in UnevaluatedConst: {kind:?}"),
+        }
+    }
+
     fn alias_term_kind_from_def_id(self, def_id: DefId) -> ty::AliasTermKind<'tcx> {
         match self.def_kind(def_id) {
             DefKind::AssocTy => {
@@ -239,7 +259,7 @@ fn alias_term_kind_from_def_id(self, def_id: DefId) -> ty::AliasTermKind<'tcx> {
             DefKind::TyAlias => ty::AliasTermKind::FreeTy { def_id },
             DefKind::Const { .. } => ty::AliasTermKind::FreeConst { def_id },
             DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => {
-                ty::AliasTermKind::UnevaluatedConst { def_id }
+                ty::AliasTermKind::AnonConst { def_id }
             }
             kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
         }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index b81e0b6..386ae42 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -151,6 +151,9 @@ pub enum InstanceKind<'tcx> {
     ///
     /// The `DefId` is for `core::ptr::drop_glue`.
     /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop glue.
+    ///
+    /// The type must be monomorphic; for polymorphic drop glue use
+    /// `rustc_mir_transform::build_drop_shim`.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
     /// Compiler-generated `<T as Clone>::clone` implementation.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 168aa5e..98f2a6a 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1097,7 +1097,7 @@ fn ty_and_layout_pointee_info_at(
                         } else {
                             VariantIdx::from_u32(0)
                         };
-                        assert_eq!(tagged_variant, *niche_variants.start());
+                        assert_eq!(tagged_variant, niche_variants.start);
                         if *niche_start == 0 {
                             // The other variant is encoded as "null", so we can recurse searching for
                             // a pointer here. This relies on the fact that the codegen backend
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 74f9e75..9ea476c 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -31,18 +31,17 @@
 use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree};
 use rustc_ast::node_id::NodeMap;
 pub use rustc_ast_ir::{Movability, Mutability, try_visit};
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer};
-use rustc_hir as hir;
 use rustc_hir::attrs::StrippedCfgItem;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_hir::definitions::PerParentDisambiguatorState;
-use rustc_hir::{LangItem, attrs as attr, find_attr};
+use rustc_hir::{self as hir, LangItem, MissingLifetimeKind, attrs as attr, find_attr};
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitMatrix;
 use rustc_macros::{
@@ -79,8 +78,8 @@
 };
 pub use self::consts::{
     AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind,
-    LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value,
-    const_lit_matches_ty,
+    LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, UnevaluatedConstKind, ValTree,
+    ValTreeKindExt, Value, const_lit_matches_ty,
 };
 pub use self::context::{
     CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,
@@ -206,7 +205,15 @@ pub struct ResolverGlobalCtxt {
 
 #[derive(Debug)]
 pub struct PerOwnerResolverData {
-    pub node_id_to_def_id: NodeMap<LocalDefId>,
+    pub node_id_to_def_id: NodeMap<LocalDefId> = Default::default(),
+    /// Whether lifetime elision was successful.
+    pub lifetime_elision_allowed: bool = false,
+    /// Resolutions for labels.
+    /// Maps from NodeId of the break/continue expression to the NodeId of their corresponding blocks or loops.
+    pub label_res_map: NodeMap<ast::NodeId> = Default::default(),
+    /// Resolutions for lifetimes.
+    pub lifetimes_res_map: NodeMap<LifetimeRes> = Default::default(),
+
     /// The id of the owner
     pub id: ast::NodeId,
     /// The `DefId` of the owner, can't be found in `node_id_to_def_id`.
@@ -215,7 +222,17 @@ pub struct PerOwnerResolverData {
 
 impl PerOwnerResolverData {
     pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData {
-        PerOwnerResolverData { node_id_to_def_id: Default::default(), id, def_id }
+        PerOwnerResolverData { id, def_id, .. }
+    }
+
+    /// Obtains resolution for a label with the given `NodeId`.
+    pub fn get_label_res(&self, id: ast::NodeId) -> Option<ast::NodeId> {
+        self.label_res_map.get(&id).copied()
+    }
+
+    /// Obtains resolution for a lifetime with the given `NodeId`.
+    pub fn get_lifetime_res(&self, id: ast::NodeId) -> Option<LifetimeRes> {
+        self.lifetimes_res_map.get(&id).copied()
     }
 }
 
@@ -227,20 +244,14 @@ pub struct ResolverAstLowering<'tcx> {
     pub partial_res_map: NodeMap<hir::def::PartialRes>,
     /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
     pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>,
-    /// Resolutions for labels (node IDs of their corresponding blocks or loops).
-    pub label_res_map: NodeMap<ast::NodeId>,
-    /// Resolutions for lifetimes.
-    pub lifetimes_res_map: NodeMap<LifetimeRes>,
     /// Lifetime parameters that lowering will have to introduce.
-    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
+    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, MissingLifetimeKind)>>,
 
     pub next_node_id: ast::NodeId,
 
     pub owners: NodeMap<PerOwnerResolverData>,
 
     pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]>,
-    /// List functions and methods for which lifetime elision was successful.
-    pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
 
     /// Lints that were emitted by the resolver and early lints.
     pub lint_buffer: Steal<LintBuffer>,
@@ -253,9 +264,12 @@ pub struct ResolverAstLowering<'tcx> {
 
 #[derive(Debug)]
 pub struct DelegationInfo {
-    // NodeId (either delegation.id or item_id in case of a trait impl) for signature resolution,
+    // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution,
     // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914
-    pub resolution_node: ast::NodeId,
+    /// Refers to the next element in a delegation resolution chain.
+    /// Usually points to the final resolution, as most "chains" are just
+    /// one step to a trait or an impl.
+    pub resolution_id: DefId,
 }
 
 #[derive(Clone, Copy, Debug, StableHash)]
@@ -669,14 +683,14 @@ pub fn into_arg(self) -> GenericArg<'tcx> {
         }
     }
 
-    pub fn to_alias_term(self, tcx: TyCtxt<'tcx>) -> Option<AliasTerm<'tcx>> {
+    pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> {
         match self.kind() {
             TermKind::Ty(ty) => match *ty.kind() {
                 ty::Alias(alias_ty) => Some(alias_ty.into()),
                 _ => None,
             },
             TermKind::Const(ct) => match ct.kind() {
-                ConstKind::Unevaluated(uv) => Some(AliasTerm::from_unevaluated_const(tcx, uv)),
+                ConstKind::Unevaluated(uv) => Some(uv.into()),
                 _ => None,
             },
         }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index daead99..46dfcff 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1561,14 +1561,16 @@ fn pretty_print_const(
         }
 
         match ct.kind() {
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
-                match self.tcx().def_kind(def) {
-                    DefKind::Const { .. } | DefKind::AssocConst { .. } => {
-                        self.pretty_print_value_path(def, args)?;
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => {
+                match kind {
+                    ty::UnevaluatedConstKind::Projection { def_id }
+                    | ty::UnevaluatedConstKind::Inherent { def_id }
+                    | ty::UnevaluatedConstKind::Free { def_id } => {
+                        self.pretty_print_value_path(def_id, args)?;
                     }
-                    DefKind::AnonConst => {
-                        if def.is_local()
-                            && let span = self.tcx().def_span(def)
+                    ty::UnevaluatedConstKind::Anon { def_id } => {
+                        if def_id.is_local()
+                            && let span = self.tcx().def_span(def_id)
                             && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
                         {
                             write!(self, "{snip}")?;
@@ -1583,12 +1585,11 @@ fn pretty_print_const(
                             write!(
                                 self,
                                 "{}::{}",
-                                self.tcx().crate_name(def.krate),
-                                self.tcx().def_path(def).to_string_no_crate_verbose()
+                                self.tcx().crate_name(def_id.krate),
+                                self.tcx().def_path(def_id).to_string_no_crate_verbose()
                             )?;
                         }
                     }
-                    defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
                 }
             }
             ty::ConstKind::Infer(infer_ct) => match infer_ct {
@@ -3169,7 +3170,7 @@ macro_rules! define_print_and_forward_display {
             ty::AliasTermKind::FreeTy { def_id }
             | ty::AliasTermKind::FreeConst { def_id }
             | ty::AliasTermKind::OpaqueTy { def_id }
-            | ty::AliasTermKind::UnevaluatedConst { def_id }
+            | ty::AliasTermKind::AnonConst { def_id }
             | ty::AliasTermKind::ProjectionConst { def_id } => {
                 p.print_def_path(def_id, self.args)?;
             }
@@ -3265,9 +3266,9 @@ macro_rules! define_print_and_forward_display {
     }
 
     ty::ExistentialTraitRef<'tcx> {
-        // Use a type that can't appear in defaults of type parameters.
-        let dummy_self = Ty::new_fresh(p.tcx(), 0);
-        let trait_ref = self.with_self_ty(p.tcx(), dummy_self);
+        // Dummy Self is safe to use as it can't appear in generic param defaults which is important
+        // later on for correctly eliding generic args that coincide with their default.
+        let trait_ref = self.with_self_ty(p.tcx(), p.tcx().types.trait_object_dummy_self);
         trait_ref.print_only_trait_path().print(p)?;
     }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 99da2da..9f6d117 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -931,7 +931,7 @@ pub fn opt_alias_variances(
             | ty::AliasTermKind::InherentConst { .. }
             | ty::AliasTermKind::FreeTy { .. }
             | ty::AliasTermKind::FreeConst { .. }
-            | ty::AliasTermKind::UnevaluatedConst { .. }
+            | ty::AliasTermKind::AnonConst { .. }
             | ty::AliasTermKind::ProjectionConst { .. } => None,
         }
     }
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index 5d9a238..84203c5 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -63,7 +63,6 @@ pub(crate) fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind
                     unwind: self.parse_unwind_action(args[2])?,
                     replace: false,
                     drop: None,
-                    async_fut: None,
                 })
             },
             @call(mir_call, args) => {
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
index c67d99a..76360ee 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
@@ -72,7 +72,11 @@ pub(crate) fn as_constant_inner<'tcx>(
         ExprKind::NamedConst { def_id, args, ref user_ty } => {
             let user_ty = user_ty.as_ref().and_then(push_cuta);
             if tcx.is_type_const(def_id) {
-                let uneval = ty::UnevaluatedConst::new(def_id, args);
+                let uneval = ty::UnevaluatedConst::new(
+                    tcx,
+                    ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id),
+                    args,
+                );
                 let ct = ty::Const::new_unevaluated(tcx, uneval);
 
                 let const_ = Const::Ty(ty, ct);
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
index ce443d6..dd36411 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
@@ -642,7 +642,6 @@ fn build_zero_repeat(
                         unwind: UnwindAction::Continue,
                         replace: false,
                         drop: None,
-                        async_fut: None,
                     },
                 );
                 this.diverge_from(block);
diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs
index 6ab1995..c9aae29 100644
--- a/compiler/rustc_mir_build/src/builder/expr/into.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/into.rs
@@ -15,7 +15,7 @@
 use tracing::{debug, instrument};
 
 use crate::builder::expr::category::{Category, RvalueFunc};
-use crate::builder::matches::{DeclareLetBindings, HasMatchGuard};
+use crate::builder::matches::{DeclareLetBindings, Exhaustive, HasMatchGuard};
 use crate::builder::scope::LintLevel;
 use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary};
 use crate::errors::{LoopMatchArmWithGuard, LoopMatchUnsupportedType};
@@ -322,7 +322,7 @@ fn is_supported_loop_match_type(ty: Ty<'_>) -> bool {
                         &scrutinee_place_builder,
                         match_start_span,
                         patterns,
-                        false,
+                        Exhaustive::Yes,
                     );
 
                     let state_place = scrutinee_place_builder.to_place(this);
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 31c7c22..2fbf772 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -376,7 +376,7 @@ pub(crate) fn match_expr(
             &scrutinee_place,
             match_start_span,
             patterns,
-            false,
+            Exhaustive::Yes,
         );
 
         self.lower_match_arms(
@@ -649,7 +649,7 @@ pub(crate) fn place_into_pattern(
             &initializer,
             irrefutable_pat.span,
             vec![(irrefutable_pat, HasMatchGuard::No)],
-            false,
+            Exhaustive::Yes,
         );
         let [branch] = built_tree.branches.try_into().unwrap();
 
@@ -1565,6 +1565,14 @@ pub(crate) enum HasMatchGuard {
     No,
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) enum Exhaustive {
+    /// `let` and `match` are exhaustive.
+    Yes,
+    /// `if let` and `let else` are not exhaustive.
+    No,
+}
+
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The entrypoint of the matching algorithm. Create the decision tree for the match expression,
     /// starting from `block`.
@@ -1572,9 +1580,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// `patterns` is a list of patterns, one for each arm. The associated boolean indicates whether
     /// the arm has a guard.
     ///
-    /// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
-    /// or not (for `let` and `match`). In the refutable case we return the block to which we branch
-    /// on failure.
+    /// `exhaustive` indicates whether the candidate list is exhaustive (for `if let` and `let else`)
+    /// or not (for `let` and `match`). In the non-exhaustive case we return the block to which we
+    /// branch on failure.
     pub(crate) fn lower_match_tree(
         &mut self,
         block: BasicBlock,
@@ -1582,7 +1590,7 @@ pub(crate) fn lower_match_tree(
         scrutinee_place_builder: &PlaceBuilder<'tcx>,
         match_start_span: Span,
         patterns: Vec<(&Pat<'tcx>, HasMatchGuard)>,
-        refutable: bool,
+        exhaustive: Exhaustive,
     ) -> BuiltMatchTree<'tcx> {
         // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
         // input patterns, but other parts of match lowering also introduce subcandidates (for
@@ -1611,9 +1619,12 @@ pub(crate) fn lower_match_tree(
 
         // Set up false edges so that the borrow-checker cannot make use of the specific CFG we
         // generated. We falsely branch from each candidate to the one below it to make it as if we
-        // were testing match branches one by one in order. In the refutable case we also want a
+        // were testing match branches one by one in order. In the non-exhaustive case we also want a
         // false edge to the final failure block.
-        let mut next_candidate_start_block = if refutable { Some(otherwise_block) } else { None };
+        let mut next_candidate_start_block = match exhaustive {
+            Exhaustive::Yes => None,
+            Exhaustive::No => Some(otherwise_block),
+        };
         for candidate in candidates.iter_mut().rev() {
             let has_guard = candidate.has_guard;
             candidate.visit_leaves_rev(|leaf_candidate| {
@@ -1647,8 +1658,8 @@ pub(crate) fn lower_match_tree(
             });
         }
 
-        if !refutable {
-            // Match checking ensures `otherwise_block` is actually unreachable in irrefutable
+        if exhaustive == Exhaustive::Yes {
+            // Match checking ensures `otherwise_block` is actually unreachable in exhaustive
             // cases.
             let source_info = self.source_info(scrutinee_span);
 
@@ -2362,7 +2373,7 @@ pub(crate) fn lower_let_expr(
             &scrutinee,
             pat.span,
             vec![(pat, HasMatchGuard::No)],
-            true,
+            Exhaustive::No,
         );
         let [branch] = built_tree.branches.try_into().unwrap();
 
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 3343bec..a341bef 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -427,7 +427,6 @@ fn link_blocks<'tcx>(
                         place: drop_node.data.local.into(),
                         replace: false,
                         drop: None,
-                        async_fut: None,
                     };
                     cfg.terminate(block, drop_node.data.source_info, terminator);
                 }
@@ -846,7 +845,7 @@ fn eval_unevaluated_mir_constant_to_valtree(
     ) -> Result<(ty::ValTree<'tcx>, Ty<'tcx>), interpret::ErrorHandled> {
         assert!(!constant.const_.ty().has_param());
         let (uv, ty) = match constant.const_ {
-            mir::Const::Unevaluated(uv, ty) => (uv.shrink(), ty),
+            mir::Const::Unevaluated(uv, ty) => (uv.shrink(self.tcx), ty),
             mir::Const::Ty(_, c) => match c.kind() {
                 // A constant that came from a const generic but was then used as an argument to
                 // old-style simd_shuffle (passing as argument instead of as a generic param).
@@ -1170,7 +1169,6 @@ pub(crate) fn break_for_tail_call(
                                 unwind: UnwindAction::Continue,
                                 replace: false,
                                 drop: None,
-                                async_fut: None,
                             },
                         );
                         block = next;
@@ -1745,7 +1743,6 @@ pub(crate) fn build_drop_and_replace(
                 unwind: UnwindAction::Cleanup(assign_unwind),
                 replace: true,
                 drop: None,
-                async_fut: None,
             },
         );
         self.diverge_from(block);
@@ -1916,7 +1913,6 @@ fn build_scope_drops<'tcx, F>(
                         unwind: UnwindAction::Continue,
                         replace: false,
                         drop: None,
-                        async_fut: None,
                     },
                 );
                 block = next;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 0c6e1b8..2f2126c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -73,16 +73,18 @@ fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
     /// We errored. Signal that in the pattern, so that follow up errors can be silenced.
     fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
         if let ty::ConstKind::Unevaluated(uv) = self.c.kind() {
-            let def_kind = self.tcx.def_kind(uv.def);
-            if let hir::def::DefKind::AssocConst { .. } = def_kind
-                && let Some(def_id) = uv.def.as_local()
+            if let ty::UnevaluatedConstKind::Projection { def_id }
+            | ty::UnevaluatedConstKind::Inherent { def_id } = uv.kind
+                && let Some(def_id) = def_id.as_local()
             {
                 // Include the container item in the output.
                 err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), "");
             }
-            if let hir::def::DefKind::Const { .. } | hir::def::DefKind::AssocConst { .. } = def_kind
+            if let ty::UnevaluatedConstKind::Projection { def_id }
+            | ty::UnevaluatedConstKind::Inherent { def_id }
+            | ty::UnevaluatedConstKind::Free { def_id } = uv.kind
             {
-                err.span_label(self.tcx.def_span(uv.def), msg!("constant defined here"));
+                err.span_label(self.tcx.def_span(def_id), msg!("constant defined here"));
             }
         }
         Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None })
@@ -117,8 +119,9 @@ fn unevaluated_to_pat(
                 // We've emitted an error on the original const, it would be redundant to complain
                 // on its use as well.
                 if let ty::ConstKind::Unevaluated(uv) = self.c.kind()
-                    && let hir::def::DefKind::Const { .. } | hir::def::DefKind::AssocConst { .. } =
-                        self.tcx.def_kind(uv.def)
+                    && let ty::UnevaluatedConstKind::Projection { .. }
+                    | ty::UnevaluatedConstKind::Inherent { .. }
+                    | ty::UnevaluatedConstKind::Free { .. } = uv.kind
                 {
                     err.downgrade_to_delayed_bug();
                 }
@@ -183,7 +186,7 @@ fn unevaluated_to_pat(
 
         // Mark the pattern to indicate that it is the result of lowering a named
         // constant. This is used for diagnostics.
-        thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.def);
+        thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.kind.def_id());
         thir_pat
     }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index d59fce3..d826a7e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -657,7 +657,14 @@ fn lower_path(
         let args = self.typeck_results.node_args(id);
         // FIXME(mgca): we will need to special case IACs here to have type system compatible
         // generic args, instead of how we represent them in body expressions.
-        let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
+        let c = ty::Const::new_unevaluated(
+            self.tcx,
+            ty::UnevaluatedConst::new(
+                self.tcx,
+                ty::UnevaluatedConstKind::new_from_def_id(self.tcx, def_id),
+                args,
+            ),
+        );
         let mut pattern = self.const_to_pat(c, ty, id, span);
 
         // If this is an associated constant with an explicit user-written
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index f8d0885..39df331 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -101,11 +101,13 @@ fn apply_effects_in_block<'mir, 'tcx, A>(
                     propagate(pred, &tmp);
                 }
 
-                mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == block => {
+                mir::TerminatorKind::Yield { resume, drop, resume_arg, .. }
+                    if resume == block || drop == Some(block) =>
+                {
                     let mut tmp = exit_state.clone();
                     analysis.apply_call_return_effect(
                         &mut tmp,
-                        resume,
+                        block,
                         CallReturnPlaces::Yield(resume_arg),
                     );
                     propagate(pred, &tmp);
@@ -275,7 +277,7 @@ fn apply_effects_in_block<'mir, 'tcx, A>(
 
                 if !return_.is_empty() {
                     analysis.apply_call_return_effect(exit_state, block, place);
-                    for &target in return_ {
+                    for target in return_ {
                         propagate(target, exit_state);
                     }
                 }
diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
index 38599cd..5578b43 100644
--- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
@@ -41,9 +41,9 @@ fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt
 }
 
 /// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_with`.
-pub struct DebugWithAdapter<'a, T, C> {
-    pub this: T,
-    pub ctxt: &'a C,
+pub(crate) struct DebugWithAdapter<'a, T, C> {
+    pub(crate) this: T,
+    pub(crate) ctxt: &'a C,
 }
 
 impl<T, C> fmt::Debug for DebugWithAdapter<'_, T, C>
@@ -56,10 +56,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 /// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_diff_with`.
-pub struct DebugDiffWithAdapter<'a, T, C> {
-    pub new: T,
-    pub old: T,
-    pub ctxt: &'a C,
+pub(crate) struct DebugDiffWithAdapter<'a, T, C> {
+    pub(crate) new: T,
+    pub(crate) old: T,
+    pub(crate) ctxt: &'a C,
 }
 
 impl<T, C> fmt::Debug for DebugDiffWithAdapter<'_, T, C>
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index e045b0e..b4cbe7d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -412,14 +412,8 @@ fn apply_primary_terminator_effect<'mir>(
         // the result of `is_unwind_dead`.
         let mut edges = terminator.edges();
         if self.skip_unreachable_unwind
-            && let mir::TerminatorKind::Drop {
-                target,
-                unwind,
-                place,
-                replace: _,
-                drop: _,
-                async_fut: _,
-            } = terminator.kind
+            && let mir::TerminatorKind::Drop { target, unwind, place, replace: _, drop: _ } =
+                terminator.kind
             && matches!(unwind, mir::UnwindAction::Cleanup(_))
             && self.is_unwind_dead(place, state)
         {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 8be7d21..7f8872b 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -388,7 +388,7 @@ pub fn find_in_move_path_or_its_descendants(
 
 /// A projection into a move path producing a child path
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum MoveSubPath {
+enum MoveSubPath {
     Deref,
     Field(FieldIdx),
     ConstantIndex(u64),
@@ -397,7 +397,7 @@ pub enum MoveSubPath {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum MoveSubPathResult {
+enum MoveSubPathResult {
     One(MoveSubPath),
     Subslice { from: u64, to: u64 },
     Skip,
@@ -405,7 +405,7 @@ pub enum MoveSubPathResult {
 }
 
 impl MoveSubPath {
-    pub fn of(elem: ProjectionKind) -> MoveSubPathResult {
+    fn of(elem: ProjectionKind) -> MoveSubPathResult {
         let subpath = match elem {
             // correspond to a MoveSubPath
             ProjectionKind::Deref => MoveSubPath::Deref,
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 2476dcd..1e04453 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -120,17 +120,6 @@ pub fn new_reachable() -> State<V> {
         State::Reachable(StateData::new())
     }
 
-    pub fn all_bottom(&self) -> bool {
-        match self {
-            State::Unreachable => false,
-            State::Reachable(values) =>
-            {
-                #[allow(rustc::potential_query_instability)]
-                values.map.values().all(V::is_bottom)
-            }
-        }
-    }
-
     pub fn is_reachable(&self) -> bool {
         matches!(self, State::Reachable(_))
     }
@@ -168,7 +157,7 @@ pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
     ///
     /// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
     /// as such.
-    pub fn flood_with_tail_elem(
+    fn flood_with_tail_elem(
         &mut self,
         place: PlaceRef<'_>,
         tail_elem: Option<TrackElem>,
@@ -238,25 +227,19 @@ pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, ma
     }
 
     /// Retrieve the value stored for a place, or `None` if it is not tracked.
-    pub fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
+    fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
         let place = map.find(place)?;
         self.try_get_idx(place, map)
     }
 
     /// Retrieve the discriminant stored for a place, or `None` if it is not tracked.
-    pub fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
+    fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
         let place = map.find_discr(place)?;
         self.try_get_idx(place, map)
     }
 
-    /// Retrieve the slice length stored for a place, or `None` if it is not tracked.
-    pub fn try_get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
-        let place = map.find_len(place)?;
-        self.try_get_idx(place, map)
-    }
-
     /// Retrieve the value stored for a place index, or `None` if it is not tracked.
-    pub fn try_get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> Option<V> {
+    fn try_get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> Option<V> {
         match self {
             State::Reachable(values) => {
                 map.places[place].value_index.map(|v| values.get(v).clone())
@@ -293,20 +276,6 @@ pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
         }
     }
 
-    /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
-    ///
-    /// This method returns ⊥ the current state is unreachable.
-    pub fn get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
-    where
-        V: HasBottom + HasTop,
-    {
-        match self {
-            State::Reachable(_) => self.try_get_len(place, map).unwrap_or(V::TOP),
-            // Because this is unreachable, we can return any value we want.
-            State::Unreachable => V::BOTTOM,
-        }
-    }
-
     /// Retrieve the value stored for a place index, or ⊤ if it is not tracked.
     ///
     /// This method returns ⊥ the current state is unreachable.
@@ -800,21 +769,6 @@ pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
         self.places[place].value_index
     }
 
-    /// Locates the value corresponding to the given place.
-    pub fn find_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
-        self.value(self.find(place)?)
-    }
-
-    /// Locates the value corresponding to the given discriminant.
-    pub fn find_discr_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
-        self.value(self.find_discr(place)?)
-    }
-
-    /// Locates the value corresponding to the given length.
-    pub fn find_len_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
-        self.value(self.find_len(place)?)
-    }
-
     /// Iterate over all direct children.
     fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
         Children::new(self, parent)
@@ -882,12 +836,6 @@ fn for_each_variant_sibling(
         }
     }
 
-    /// Return the range of value indices inside this place.
-    pub fn values_inside(&self, root: PlaceIndex) -> &[ValueIndex] {
-        let range = self.inner_values[root].clone();
-        &self.inner_values_buffer[range]
-    }
-
     /// Invoke a function on each value in the given place and all descendants.
     #[tracing::instrument(level = "trace", skip(self, f))]
     fn for_each_value_inside(&self, root: PlaceIndex, f: &mut impl FnMut(ValueIndex)) {
@@ -937,7 +885,7 @@ pub fn for_each_projection_value<O>(
 
     /// Recursively iterates on each value contained in `target`, paired with matching projection
     /// inside `source`.
-    pub fn for_each_value_pair(
+    fn for_each_value_pair(
         &self,
         target: PlaceIndex,
         source: PlaceIndex,
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 46d5773..f47751e 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
@@ -83,9 +83,7 @@ fn add_move_for_packed_drop<'tcx>(
     is_cleanup: bool,
 ) {
     debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc);
-    let TerminatorKind::Drop { ref place, target, unwind, replace, drop, async_fut } =
-        terminator.kind
-    else {
+    let TerminatorKind::Drop { ref place, target, unwind, replace, drop } = terminator.kind else {
         unreachable!();
     };
 
@@ -109,7 +107,6 @@ fn add_move_for_packed_drop<'tcx>(
             unwind,
             replace,
             drop,
-            async_fut,
         },
     );
 }
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 4ae6e9a..9047055 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -56,9 +56,9 @@
 
 pub(super) use by_move_body::coroutine_by_move_body_def_id;
 use drop::{
-    cleanup_async_drops, create_coroutine_drop_shim, create_coroutine_drop_shim_async,
-    create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, expand_async_drops,
-    has_expandable_async_drops, insert_clean_drop,
+    create_coroutine_drop_shim, create_coroutine_drop_shim_async,
+    create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, has_async_drops,
+    insert_clean_drop,
 };
 use itertools::izip;
 use rustc_abi::{FieldIdx, VariantIdx};
@@ -70,7 +70,6 @@
 use rustc_index::{Idx, IndexVec, indexvec};
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::{
     self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
 };
@@ -82,8 +81,8 @@
 use rustc_mir_dataflow::{
     Analysis, Results, ResultsCursor, ResultsVisitor, visit_reachable_results,
 };
+use rustc_span::Span;
 use rustc_span::def_id::{DefId, LocalDefId};
-use rustc_span::{DUMMY_SP, Span, dummy_spanned};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::TyCtxtInferExt as _;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
@@ -169,7 +168,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
 }
 
 const SELF_ARG: Local = Local::arg(0);
-const CTX_ARG: Local = Local::arg(1);
+pub(crate) const CTX_ARG: Local = Local::arg(1);
 
 /// A `yield` point in the coroutine.
 struct SuspensionPoint<'tcx> {
@@ -585,7 +584,7 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
 /// still using the `ResumeTy` indirection for the time being, and that indirection
 /// is removed here. After this transform, the coroutine body only knows about `&mut Context<'_>`.
 #[tracing::instrument(level = "trace", skip(tcx, body), ret)]
-fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ty<'tcx> {
+fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let context_mut_ref = Ty::new_task_context(tcx);
 
     // replace the type of the `resume` argument
@@ -615,7 +614,6 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ty
             _ => {}
         }
     }
-    context_mut_ref
 }
 
 fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local {
@@ -1077,7 +1075,7 @@ fn compute_layout<'tcx>(
 /// Replaces the entry point of `body` with a block that switches on the coroutine discriminant and
 /// dispatches to blocks according to `cases`.
 ///
-/// After this function, the former entry point of the function will be bb1.
+/// After this function, the former entry point of the function will be the last block.
 fn insert_switch<'tcx>(
     body: &mut Body<'tcx>,
     cases: Vec<(usize, BasicBlock)>,
@@ -1085,23 +1083,34 @@ fn insert_switch<'tcx>(
     default_block: BasicBlock,
 ) {
     let (assign, discr) = transform.get_discr(body);
-    let switch_targets =
-        SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
-    let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets };
 
-    let source_info = SourceInfo::outermost(body.span);
-    body.basic_blocks_mut().raw.insert(
-        0,
-        BasicBlockData::new_stmts(
-            vec![assign],
-            Some(Terminator { source_info, kind: switch }),
-            false,
-        ),
-    );
-
-    for b in body.basic_blocks_mut().iter_mut() {
-        b.terminator_mut().successors_mut(|target| *target += 1);
+    // MIR validation ensures that no block targets `ENTRY_BLOCK`.
+    #[cfg(debug_assertions)]
+    for bb in body.basic_blocks.iter() {
+        for target in bb.terminator().successors() {
+            assert_ne!(target, START_BLOCK);
+        }
     }
+
+    // Add the switch as entry block, and put the former entry block at the end.
+    let former_entry = std::mem::replace(
+        &mut body.basic_blocks_mut()[START_BLOCK],
+        BasicBlockData::new_stmts(vec![assign], None, false),
+    );
+    let former_entry = body.basic_blocks_mut().push(former_entry);
+
+    // We may point to `START_BLOCK` in our `cases`, replace it with `former_entry`.
+    let mut switch_targets =
+        SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
+    for bb in switch_targets.all_targets_mut() {
+        if *bb == START_BLOCK {
+            *bb = former_entry;
+        }
+    }
+
+    let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets };
+    body.basic_blocks_mut()[START_BLOCK].terminator =
+        Some(Terminator { source_info: SourceInfo::outermost(body.span), kind: switch });
 }
 
 fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
@@ -1172,41 +1181,8 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
         return false;
     }
 
-    // Unwinds can only start at certain terminators.
-    for block in body.basic_blocks.iter() {
-        match block.terminator().kind {
-            // These never unwind.
-            TerminatorKind::Goto { .. }
-            | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::UnwindTerminate(_)
-            | TerminatorKind::Return
-            | TerminatorKind::Unreachable
-            | TerminatorKind::CoroutineDrop
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::FalseUnwind { .. } => {}
-
-            // Resume will *continue* unwinding, but if there's no other unwinding terminator it
-            // will never be reached.
-            TerminatorKind::UnwindResume => {}
-
-            TerminatorKind::Yield { .. } => {
-                unreachable!("`can_unwind` called before coroutine transform")
-            }
-
-            // These may unwind.
-            TerminatorKind::Drop { .. }
-            | TerminatorKind::Call { .. }
-            | TerminatorKind::InlineAsm { .. }
-            | TerminatorKind::Assert { .. } => return true,
-
-            TerminatorKind::TailCall { .. } => {
-                unreachable!("tail calls can't be present in generators")
-            }
-        }
-    }
-
-    // If we didn't find an unwinding terminator, the function cannot unwind.
-    false
+    // If we don't find an unwinding terminator, the function cannot unwind.
+    body.basic_blocks.iter().any(|block| block.terminator().unwind().is_some())
 }
 
 // Poison the coroutine when it unwinds
@@ -1314,6 +1290,9 @@ fn create_coroutine_resume_function<'tcx>(
 
     pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);
 
+    // Run derefer to fix Derefs that are not in the first place
+    deref_finder(tcx, body, false);
+
     if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) {
         dumper.dump_mir(body);
     }
@@ -1324,13 +1303,21 @@ fn create_coroutine_resume_function<'tcx>(
 enum Operation {
     Resume,
     Drop,
+    AsyncDrop,
 }
 
 impl Operation {
     fn target_block(self, point: &SuspensionPoint<'_>) -> Option<BasicBlock> {
         match self {
             Operation::Resume => Some(point.resume),
-            Operation::Drop => point.drop,
+            Operation::Drop | Operation::AsyncDrop => point.drop,
+        }
+    }
+
+    fn resume_place<'tcx>(self, point: &SuspensionPoint<'tcx>) -> Option<Place<'tcx>> {
+        match self {
+            Operation::Resume | Operation::AsyncDrop => Some(point.resume_arg),
+            Operation::Drop => None,
         }
     }
 }
@@ -1361,12 +1348,14 @@ fn create_cases<'tcx>(
                     }
                 }
 
-                if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() {
-                    // Move the resume argument to the destination place of the `Yield` terminator
+                // Move the resume argument to the destination place of the `Yield` terminator
+                if let Some(resume_arg) = operation.resume_place(point)
+                    && resume_arg != CTX_ARG.into()
+                {
                     statements.push(Statement::new(
                         source_info,
                         StatementKind::Assign(Box::new((
-                            point.resume_arg,
+                            resume_arg,
                             Rvalue::Use(Operand::Move(CTX_ARG.into()), WithRetag::Yes),
                         ))),
                     ));
@@ -1519,24 +1508,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // (finally in open_drop_for_tuple) before async drop expansion.
         // Async drops, produced by this drop elaboration, will be expanded,
         // and corresponding futures kept in layout.
-        let has_async_drops = matches!(
-            coroutine_kind,
-            CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _)
-        ) && has_expandable_async_drops(tcx, body, coroutine_ty);
+        let coroutine_is_async = coroutine_kind.is_async_desugaring();
+        let has_async_drops = has_async_drops(body);
 
         // Replace all occurrences of `ResumeTy` with `&mut Context<'_>` within async bodies.
-        if matches!(
-            coroutine_kind,
-            CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _)
-        ) {
-            let context_mut_ref = transform_async_context(tcx, body);
-            expand_async_drops(tcx, body, context_mut_ref, coroutine_kind, coroutine_ty);
-
-            if let Some(dumper) = MirDumper::new(tcx, "coroutine_async_drop_expand", body) {
-                dumper.dump_mir(body);
-            }
-        } else {
-            cleanup_async_drops(body);
+        if coroutine_is_async {
+            transform_async_context(tcx, body);
         }
 
         let always_live_locals = always_storage_live_locals(body);
@@ -1623,10 +1600,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         body.coroutine.as_mut().unwrap().resume_ty = None;
         body.coroutine.as_mut().unwrap().coroutine_layout = Some(layout);
 
-        // FIXME: Drops, produced by insert_clean_drop + elaborate_coroutine_drops,
-        // are currently sync only. To allow async for them, we need to move those calls
-        // before expand_async_drops, and fix the related problems.
-        //
         // Insert `drop(coroutine_struct)` which is used to drop upvars for coroutines in
         // the unresumed state.
         // This is expanded to a drop ladder in `elaborate_coroutine_drops`.
@@ -1650,30 +1623,22 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // Create a copy of our MIR and use it to create the drop shim for the coroutine
         if has_async_drops {
             // If coroutine has async drops, generating async drop shim
-            let mut drop_shim =
+            let drop_shim =
                 create_coroutine_drop_shim_async(tcx, &transform, body, drop_clean, can_unwind);
-            // Run derefer to fix Derefs that are not in the first place
-            deref_finder(tcx, &mut drop_shim, false);
             body.coroutine.as_mut().unwrap().coroutine_drop_async = Some(drop_shim);
         } else {
             // If coroutine has no async drops, generating sync drop shim
-            let mut drop_shim =
+            let drop_shim =
                 create_coroutine_drop_shim(tcx, &transform, coroutine_ty, body, drop_clean);
-            // Run derefer to fix Derefs that are not in the first place
-            deref_finder(tcx, &mut drop_shim, false);
             body.coroutine.as_mut().unwrap().coroutine_drop = Some(drop_shim);
 
             // For coroutine with sync drop, generating async proxy for `future_drop_poll` call
-            let mut proxy_shim = create_coroutine_drop_shim_proxy_async(tcx, body);
-            deref_finder(tcx, &mut proxy_shim, false);
+            let proxy_shim = create_coroutine_drop_shim_proxy_async(tcx, body);
             body.coroutine.as_mut().unwrap().coroutine_drop_proxy_async = Some(proxy_shim);
         }
 
         // Create the Coroutine::resume / Future::poll function
         create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind);
-
-        // Run derefer to fix Derefs that are not in the first place
-        deref_finder(tcx, body, false);
     }
 
     fn is_required(&self) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs
index 372f711..dc58bc1 100644
--- a/compiler/rustc_mir_transform/src/coroutine/drop.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs
@@ -31,438 +31,37 @@ fn visit_assign(
     }
 }
 
-// rv = call fut.poll()
-fn build_poll_call<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    poll_unit_place: &Place<'tcx>,
-    switch_block: BasicBlock,
-    fut_pin_place: &Place<'tcx>,
-    fut_ty: Ty<'tcx>,
-    context_ref_place: &Place<'tcx>,
-    unwind: UnwindAction,
-) -> BasicBlock {
-    let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, DUMMY_SP);
-    let poll_fn = Ty::new_fn_def(tcx, poll_fn, [fut_ty]);
-    let poll_fn = Operand::Constant(Box::new(ConstOperand {
-        span: DUMMY_SP,
-        user_ty: None,
-        const_: Const::zero_sized(poll_fn),
-    }));
-    let call = TerminatorKind::Call {
-        func: poll_fn.clone(),
-        args: [
-            dummy_spanned(Operand::Move(*fut_pin_place)),
-            dummy_spanned(Operand::Move(*context_ref_place)),
-        ]
-        .into(),
-        destination: *poll_unit_place,
-        target: Some(switch_block),
-        unwind,
-        call_source: CallSource::Misc,
-        fn_span: DUMMY_SP,
-    };
-    insert_term_block(body, call)
-}
-
-// pin_fut = Pin::new_unchecked(&mut fut)
-fn build_pin_fut<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    fut_place: Place<'tcx>,
-    unwind: UnwindAction,
-) -> (BasicBlock, Place<'tcx>) {
-    let span = body.span;
-    let source_info = SourceInfo::outermost(span);
-    let fut_ty = fut_place.ty(&body.local_decls, tcx).ty;
-    let fut_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fut_ty);
-    let fut_ref_place = Place::from(body.local_decls.push(LocalDecl::new(fut_ref_ty, span)));
-    let pin_fut_new_unchecked_fn =
-        Ty::new_fn_def(tcx, tcx.require_lang_item(LangItem::PinNewUnchecked, span), [fut_ref_ty]);
-    let fut_pin_ty = pin_fut_new_unchecked_fn.fn_sig(tcx).output().skip_binder();
-    let fut_pin_place = Place::from(body.local_decls.push(LocalDecl::new(fut_pin_ty, span)));
-    let pin_fut_new_unchecked_fn = Operand::Constant(Box::new(ConstOperand {
-        span,
-        user_ty: None,
-        const_: Const::zero_sized(pin_fut_new_unchecked_fn),
-    }));
-
-    let storage_live = Statement::new(source_info, StatementKind::StorageLive(fut_pin_place.local));
-
-    let fut_ref_assign = Statement::new(
-        source_info,
-        StatementKind::Assign(Box::new((
-            fut_ref_place,
-            Rvalue::Ref(
-                tcx.lifetimes.re_erased,
-                BorrowKind::Mut { kind: MutBorrowKind::Default },
-                fut_place,
-            ),
-        ))),
-    );
-
-    // call Pin<FutTy>::new_unchecked(&mut fut)
-    let pin_fut_bb = body.basic_blocks_mut().push(BasicBlockData::new_stmts(
-        [storage_live, fut_ref_assign].to_vec(),
-        Some(Terminator {
-            source_info,
-            kind: TerminatorKind::Call {
-                func: pin_fut_new_unchecked_fn,
-                args: [dummy_spanned(Operand::Move(fut_ref_place))].into(),
-                destination: fut_pin_place,
-                target: None, // will be fixed later
-                unwind,
-                call_source: CallSource::Misc,
-                fn_span: span,
-            },
-        }),
-        false,
-    ));
-    (pin_fut_bb, fut_pin_place)
-}
-
-// Build Poll switch for async drop
-// match rv {
-//     Ready() => ready_block
-//     Pending => yield_block
-//}
-#[tracing::instrument(level = "trace", skip(tcx, body), ret)]
-fn build_poll_switch<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    poll_enum: Ty<'tcx>,
-    poll_unit_place: &Place<'tcx>,
-    fut_pin_place: &Place<'tcx>,
-    ready_block: BasicBlock,
-    yield_block: BasicBlock,
-) -> BasicBlock {
-    let poll_enum_adt = poll_enum.ty_adt_def().unwrap();
-
-    let Discr { val: poll_ready_discr, ty: poll_discr_ty } = poll_enum
-        .discriminant_for_variant(
-            tcx,
-            poll_enum_adt
-                .variant_index_with_id(tcx.require_lang_item(LangItem::PollReady, DUMMY_SP)),
-        )
-        .unwrap();
-    let poll_pending_discr = poll_enum
-        .discriminant_for_variant(
-            tcx,
-            poll_enum_adt
-                .variant_index_with_id(tcx.require_lang_item(LangItem::PollPending, DUMMY_SP)),
-        )
-        .unwrap()
-        .val;
-    let source_info = SourceInfo::outermost(body.span);
-    let poll_discr_place =
-        Place::from(body.local_decls.push(LocalDecl::new(poll_discr_ty, source_info.span)));
-    let discr_assign = Statement::new(
-        source_info,
-        StatementKind::Assign(Box::new((poll_discr_place, Rvalue::Discriminant(*poll_unit_place)))),
-    );
-    let storage_dead = Statement::new(source_info, StatementKind::StorageDead(fut_pin_place.local));
-    let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable);
-    body.basic_blocks_mut().push(BasicBlockData::new_stmts(
-        [storage_dead, discr_assign].to_vec(),
-        Some(Terminator {
-            source_info,
-            kind: TerminatorKind::SwitchInt {
-                discr: Operand::Move(poll_discr_place),
-                targets: SwitchTargets::new(
-                    [(poll_ready_discr, ready_block), (poll_pending_discr, yield_block)]
-                        .into_iter(),
-                    unreachable_block,
-                ),
-            },
-        }),
-        false,
-    ))
-}
-
-// Gather blocks, reachable through 'drop' targets of Yield and Drop terminators (chained)
+/// Drop elaboration has transformed all async drops into `yield` loops.
+/// The resulting coroutine needs `async drop` if it yields on a path
+/// reachable through 'drop' targets of a Yield terminator.
 #[tracing::instrument(level = "trace", skip(body), ret)]
-fn gather_dropline_blocks<'tcx>(body: &mut Body<'tcx>) -> DenseBitSet<BasicBlock> {
+pub(super) fn has_async_drops<'tcx>(body: &mut Body<'tcx>) -> bool {
+    let mut has_async_drops = false;
+
     let mut dropline: DenseBitSet<BasicBlock> = DenseBitSet::new_empty(body.basic_blocks.len());
     for (bb, data) in traversal::reverse_postorder(body) {
+        // Cleanup edges are not async drops.
+        if data.is_cleanup {
+            continue;
+        }
+
+        if let TerminatorKind::Yield { drop, .. } = data.terminator().kind {
+            if dropline.contains(bb) {
+                has_async_drops = true
+            }
+            if let Some(v) = drop {
+                dropline.insert(v);
+            }
+        }
+
         if dropline.contains(bb) {
             data.terminator().successors().for_each(|v| {
                 dropline.insert(v);
             });
-        } else {
-            match data.terminator().kind {
-                TerminatorKind::Yield { drop: Some(v), .. } => {
-                    dropline.insert(v);
-                }
-                TerminatorKind::Drop { drop: Some(v), .. } => {
-                    dropline.insert(v);
-                }
-                _ => (),
-            }
         }
     }
-    dropline
-}
 
-/// Cleanup all async drops (reset to sync)
-pub(super) fn cleanup_async_drops<'tcx>(body: &mut Body<'tcx>) {
-    for block in body.basic_blocks_mut() {
-        if let TerminatorKind::Drop {
-            place: _,
-            target: _,
-            unwind: _,
-            replace: _,
-            ref mut drop,
-            ref mut async_fut,
-        } = block.terminator_mut().kind
-        {
-            if drop.is_some() || async_fut.is_some() {
-                *drop = None;
-                *async_fut = None;
-            }
-        }
-    }
-}
-
-pub(super) fn has_expandable_async_drops<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    coroutine_ty: Ty<'tcx>,
-) -> bool {
-    for bb in START_BLOCK..body.basic_blocks.next_index() {
-        // Drops in unwind path (cleanup blocks) are not expanded to async drops, only sync drops in unwind path
-        if body[bb].is_cleanup {
-            continue;
-        }
-        let TerminatorKind::Drop { place, target: _, unwind: _, replace: _, drop: _, async_fut } =
-            body[bb].terminator().kind
-        else {
-            continue;
-        };
-        let place_ty = place.ty(&body.local_decls, tcx).ty;
-        if place_ty == coroutine_ty {
-            continue;
-        }
-        if async_fut.is_none() {
-            continue;
-        }
-        return true;
-    }
-    return false;
-}
-
-/// Expand Drop terminator for async drops into mainline poll-switch and dropline poll-switch
-#[tracing::instrument(level = "trace", skip(tcx, body), ret)]
-pub(super) fn expand_async_drops<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    context_mut_ref: Ty<'tcx>,
-    coroutine_kind: hir::CoroutineKind,
-    coroutine_ty: Ty<'tcx>,
-) {
-    let dropline = gather_dropline_blocks(body);
-    // Clean drop and async_fut fields if potentially async drop is not expanded (stays sync)
-    let remove_asyncness = |block: &mut BasicBlockData<'tcx>| {
-        tracing::trace!("remove_asyncness");
-        if let TerminatorKind::Drop {
-            place: _,
-            target: _,
-            unwind: _,
-            replace: _,
-            ref mut drop,
-            ref mut async_fut,
-        } = block.terminator_mut().kind
-        {
-            *drop = None;
-            *async_fut = None;
-        }
-    };
-    for bb in START_BLOCK..body.basic_blocks.next_index() {
-        // Drops in unwind path (cleanup blocks) are not expanded to async drops, only sync drops in unwind path
-        if body[bb].is_cleanup {
-            remove_asyncness(&mut body[bb]);
-            continue;
-        }
-        let TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } =
-            body[bb].terminator().kind
-        else {
-            continue;
-        };
-
-        let place_ty = place.ty(&body.local_decls, tcx).ty;
-        if place_ty == coroutine_ty {
-            remove_asyncness(&mut body[bb]);
-            continue;
-        }
-
-        let Some(fut_local) = async_fut else {
-            remove_asyncness(&mut body[bb]);
-            continue;
-        };
-
-        let is_dropline_bb = dropline.contains(bb);
-
-        if !is_dropline_bb && drop.is_none() {
-            remove_asyncness(&mut body[bb]);
-            continue;
-        }
-
-        let fut_place = Place::from(fut_local);
-        let fut_ty = fut_place.ty(&body.local_decls, tcx).ty;
-
-        // poll-code:
-        // state_call_drop:
-        // #bb_pin: fut_pin = Pin<FutT>::new_unchecked(&mut fut)
-        // #bb_call: rv = call fut.poll() (or future_drop_poll(fut) for internal future drops)
-        // #bb_check: match (rv)
-        //  pending => return rv (yield)
-        //  ready => *continue_bb|drop_bb*
-
-        let source_info = body[bb].terminator.as_ref().unwrap().source_info;
-
-        // Compute Poll<> (aka Poll with void return)
-        let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, source_info.span));
-        let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()]));
-        let poll_decl = LocalDecl::new(poll_enum, source_info.span);
-        let poll_unit_place = Place::from(body.local_decls.push(poll_decl));
-
-        // First state-loop yield for mainline
-        let context_ref_place =
-            Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)));
-        let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG)), WithRetag::Yes);
-        body[bb].statements.push(Statement::new(
-            source_info,
-            StatementKind::Assign(Box::new((context_ref_place, arg))),
-        ));
-        let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
-        let (pin_bb, fut_pin_place) =
-            build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue);
-        let switch_block = build_poll_switch(
-            tcx,
-            body,
-            poll_enum,
-            &poll_unit_place,
-            &fut_pin_place,
-            target,
-            yield_block,
-        );
-        let call_bb = build_poll_call(
-            tcx,
-            body,
-            &poll_unit_place,
-            switch_block,
-            &fut_pin_place,
-            fut_ty,
-            &context_ref_place,
-            unwind,
-        );
-
-        // Second state-loop yield for transition to dropline (when coroutine async drop started)
-        let mut dropline_transition_bb: Option<BasicBlock> = None;
-        let mut dropline_yield_bb: Option<BasicBlock> = None;
-        let mut dropline_context_ref: Option<Place<'_>> = None;
-        let mut dropline_call_bb: Option<BasicBlock> = None;
-        if !is_dropline_bb {
-            let context_ref_place2: Place<'_> = Place::from(
-                body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)),
-            );
-            let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
-            let (pin_bb2, fut_pin_place2) =
-                build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
-            let drop_switch_block = build_poll_switch(
-                tcx,
-                body,
-                poll_enum,
-                &poll_unit_place,
-                &fut_pin_place2,
-                drop.unwrap(),
-                drop_yield_block,
-            );
-            let drop_call_bb = build_poll_call(
-                tcx,
-                body,
-                &poll_unit_place,
-                drop_switch_block,
-                &fut_pin_place2,
-                fut_ty,
-                &context_ref_place2,
-                unwind,
-            );
-            dropline_transition_bb = Some(pin_bb2);
-            dropline_yield_bb = Some(drop_yield_block);
-            dropline_context_ref = Some(context_ref_place2);
-            dropline_call_bb = Some(drop_call_bb);
-        }
-
-        let value =
-            if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _))
-            {
-                // For AsyncGen we need `yield Poll<OptRet>::Pending`
-                let full_yield_ty = body.yield_ty().unwrap();
-                let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() };
-                let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() };
-                let yield_ty = args.type_at(0);
-                Operand::Constant(Box::new(ConstOperand {
-                    span: source_info.span,
-                    const_: Const::Unevaluated(
-                        UnevaluatedConst::new(
-                            tcx.require_lang_item(LangItem::AsyncGenPending, source_info.span),
-                            tcx.mk_args(&[yield_ty.into()]),
-                        ),
-                        full_yield_ty,
-                    ),
-                    user_ty: None,
-                }))
-            } else {
-                // value needed only for return-yields or gen-coroutines, so just const here
-                Operand::Constant(Box::new(ConstOperand {
-                    span: source_info.span,
-                    user_ty: None,
-                    const_: Const::from_bool(tcx, false),
-                }))
-            };
-
-        use rustc_middle::mir::AssertKind::ResumedAfterDrop;
-        let panic_bb = insert_panic_block(tcx, body, ResumedAfterDrop(coroutine_kind));
-
-        if is_dropline_bb {
-            body[yield_block].terminator_mut().kind = TerminatorKind::Yield {
-                value: value.clone(),
-                resume: panic_bb,
-                resume_arg: context_ref_place,
-                drop: Some(pin_bb),
-            };
-        } else {
-            body[yield_block].terminator_mut().kind = TerminatorKind::Yield {
-                value: value.clone(),
-                resume: pin_bb,
-                resume_arg: context_ref_place,
-                drop: dropline_transition_bb,
-            };
-            body[dropline_yield_bb.unwrap()].terminator_mut().kind = TerminatorKind::Yield {
-                value,
-                resume: panic_bb,
-                resume_arg: dropline_context_ref.unwrap(),
-                drop: dropline_transition_bb,
-            };
-        }
-
-        if let TerminatorKind::Call { ref mut target, .. } = body[pin_bb].terminator_mut().kind {
-            *target = Some(call_bb);
-        } else {
-            bug!()
-        }
-        if !is_dropline_bb {
-            if let TerminatorKind::Call { ref mut target, .. } =
-                body[dropline_transition_bb.unwrap()].terminator_mut().kind
-            {
-                *target = dropline_call_bb;
-            } else {
-                bug!()
-            }
-        }
-
-        body[bb].terminator_mut().kind = TerminatorKind::Goto { target: pin_bb };
-    }
+    has_async_drops
 }
 
 #[tracing::instrument(level = "trace", skip(tcx, body))]
@@ -481,6 +80,9 @@ pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
         patch: MirPatch::new(body),
         tcx,
         typing_env,
+        // FIXME(async_drop): Drops, produced by insert_clean_drop + elaborate_coroutine_drops, are
+        // currently sync only. To allow async for them, flip this flag and fix the related
+        // problems.
         produce_async_drops: false,
     };
 
@@ -488,7 +90,7 @@ pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
         let (target, unwind, source_info, dropline) = match block_data.terminator() {
             Terminator {
                 source_info,
-                kind: TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut: _ },
+                kind: TerminatorKind::Drop { place, target, unwind, replace: _, drop },
             } => {
                 if let Some(local) = place.as_local()
                     && local == SELF_ARG
@@ -530,7 +132,6 @@ pub(super) fn insert_clean_drop<'tcx>(
     body: &mut Body<'tcx>,
     has_async_drops: bool,
 ) -> BasicBlock {
-    let source_info = SourceInfo::outermost(body.span);
     let return_block = if has_async_drops {
         insert_poll_ready_block(tcx, body)
     } else {
@@ -548,12 +149,10 @@ pub(super) fn insert_clean_drop<'tcx>(
         unwind: UnwindAction::Continue,
         replace: false,
         drop: dropline,
-        async_fut: None,
     };
 
     // Create a block to destroy an unresumed coroutines. This can only destroy upvars.
-    body.basic_blocks_mut()
-        .push(BasicBlockData::new(Some(Terminator { source_info, kind: term }), false))
+    insert_term_block(body, term)
 }
 
 #[tracing::instrument(level = "trace", skip(tcx, transform, body))]
@@ -600,6 +199,9 @@ pub(super) fn create_coroutine_drop_shim<'tcx>(
     // unrelated code from the resume part of the function
     simplify::remove_dead_blocks(&mut body);
 
+    // Run derefer to fix Derefs that are not in the first place
+    deref_finder(tcx, &mut body, false);
+
     // Update the body's def to become the drop glue.
     let coroutine_instance = body.source.instance;
     let drop_glue = tcx.require_lang_item(LangItem::DropGlue, body.span);
@@ -646,7 +248,7 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>(
 
     let source_info = SourceInfo::outermost(body.span);
 
-    let mut cases = create_cases(&mut body, transform, Operation::Drop);
+    let mut cases = create_cases(&mut body, transform, Operation::AsyncDrop);
 
     cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean));
 
@@ -703,6 +305,9 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>(
         None,
     );
 
+    // Run derefer to fix Derefs that are not in the first place
+    deref_finder(tcx, &mut body, false);
+
     if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_async", &body) {
         dumper.dump_mir(&body);
     }
@@ -746,10 +351,12 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>(
         unwind: UnwindAction::Continue,
         replace: false,
         drop: None,
-        async_fut: None,
     };
     body.basic_blocks_mut()[call_bb].terminator = Some(Terminator { source_info, kind });
 
+    // Run derefer to fix Derefs that are not in the first place
+    deref_finder(tcx, &mut body, false);
+
     if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_proxy_async", &body) {
         dumper.dump_mir(&body);
     }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index c835ff7..bb9a0e2 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -1,17 +1,18 @@
 use std::{fmt, iter, mem};
 
 use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
-use rustc_hir::def::DefKind;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::{CoroutineDesugaring, CoroutineKind};
 use rustc_index::Idx;
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug, traits};
-use rustc_span::{DUMMY_SP, Spanned, dummy_spanned};
+use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
+use rustc_span::{DUMMY_SP, dummy_spanned};
 use tracing::{debug, instrument};
 
+use crate::coroutine::CTX_ARG;
 use crate::patch::MirPatch;
 
 /// Describes how/if a value should be dropped.
@@ -96,8 +97,6 @@ pub(crate) trait DropElaborator<'a, 'tcx>: fmt::Debug {
     fn typing_env(&self) -> ty::TypingEnv<'tcx>;
     fn allow_async_drops(&self) -> bool;
 
-    fn terminator_loc(&self, bb: BasicBlock) -> Location;
-
     // Drop logic
 
     /// Returns how `path` should be dropped, given `mode`.
@@ -200,19 +199,35 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.elaborator.tcx()
     }
 
-    // Generates three blocks:
-    // * #1:pin_obj_bb:   call Pin<ObjTy>::new_unchecked(&mut obj)
-    // * #2:call_drop_bb: fut = call obj.<AsyncDrop::drop>() OR call async_drop_in_place<T>(obj)
-    // * #3:drop_term_bb: drop (obj, fut, ...)
-    // We keep async drop unexpanded to poll-loop here, to expand it later, at StateTransform -
-    //   into states expand.
-    // call_destructor_only - to call only AsyncDrop::drop, not full async_drop_in_place glue
+    /// Async-drop `place: drop_ty`.
+    ///
+    /// Conceptually, we want to run `async_drop_in_place(&mut obj).await`.
+    ///
+    /// Await syntax does not exist in MIR, so we need to manually expand it into a poll-yield
+    /// loop, essentially:
+    /// ```mir
+    ///   let fut = async_drop_in_place(&mut obj);
+    ///   loop {
+    ///     let pin_fut = Pin::new_unchecked(&mut fut);
+    ///     match Future::poll(pin_fut, CTX_ARG) {
+    ///       Poll::Ready => break,
+    ///       Poll::Pending(..) => CTX_ARG = yield (),
+    ///     }
+    ///   }
+    ///   // continue to `succ`
+    /// ```
+    ///
+    /// We also need to ensure that async drop also happens on the coroutine drop path, ie. when
+    /// `yield` branches along its `drop` target. This requires a second loop, this time jumping to
+    /// `dropline`.
+    ///
+    /// Arguments:
+    ///   `call_destructor_only`: call only `AsyncDrop::drop`, not full `async_drop_in_place` glue
     #[instrument(level = "debug", skip(self), ret)]
     fn build_async_drop(
         &mut self,
         place: Place<'tcx>,
         drop_ty: Ty<'tcx>,
-        bb: Option<BasicBlock>,
         succ: BasicBlock,
         unwind: Unwind,
         dropline: Option<BasicBlock>,
@@ -220,81 +235,155 @@ fn build_async_drop(
     ) -> BasicBlock {
         let tcx = self.tcx();
         let span = self.source_info.span;
+        let obj_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty);
 
-        let pin_obj_bb = bb.unwrap_or_else(|| {
-            // Temporary terminator, will be replaced by patch
-            self.new_block(unwind, TerminatorKind::Return)
-        });
-
-        let (fut_ty, drop_fn_def_id, trait_args) = if call_destructor_only {
+        let async_drop_fn_def_id = if call_destructor_only {
             // Resolving obj.<AsyncDrop::drop>()
-            let trait_ref =
-                ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::AsyncDrop, span), [drop_ty]);
-            let (drop_trait, trait_args) = match tcx.codegen_select_candidate(
-                ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref),
-            ) {
-                Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
-                    impl_def_id,
-                    args,
-                    ..
-                })) => (*impl_def_id, *args),
-                impl_source => {
-                    span_bug!(span, "invalid `AsyncDrop` impl_source: {:?}", impl_source);
-                }
-            };
-            // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...'
-            // (#140974).
-            // Such code will report error, so just generate sync drop here and return
-            let Some(drop_fn_def_id) =
-                tcx.associated_item_def_ids(drop_trait).first().and_then(|&def_id| {
-                    if tcx.def_kind(def_id) == DefKind::AssocFn
-                        && tcx.check_args_compatible(def_id, trait_args)
-                    {
-                        Some(def_id)
-                    } else {
-                        None
-                    }
-                })
-            else {
-                tcx.dcx().span_delayed_bug(
-                    self.elaborator.body().span,
-                    "AsyncDrop type without correct `async fn drop(...)`.",
-                );
-                self.elaborator.patch().patch_terminator(
-                    pin_obj_bb,
-                    TerminatorKind::Drop {
-                        place,
-                        target: succ,
-                        unwind: unwind.into_action(),
-                        replace: false,
-                        drop: None,
-                        async_fut: None,
-                    },
-                );
-                return pin_obj_bb;
-            };
-            let drop_fn = Ty::new_fn_def(tcx, drop_fn_def_id, trait_args);
-            let sig = drop_fn.fn_sig(tcx);
-            let sig = tcx.instantiate_bound_regions_with_erased(sig);
-            (sig.output(), drop_fn_def_id, trait_args)
+            let async_drop_trait = tcx.require_lang_item(LangItem::AsyncDrop, span);
+            tcx.associated_item_def_ids(async_drop_trait)[0]
         } else {
             // Resolving async_drop_in_place<T> function for drop_ty
-            let drop_fn_def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, span);
-            let trait_args = tcx.mk_args(&[drop_ty.into()]);
-            let sig = tcx.fn_sig(drop_fn_def_id).instantiate(tcx, trait_args).skip_norm_wip();
-            let sig = tcx.instantiate_bound_regions_with_erased(sig);
-            (sig.output(), drop_fn_def_id, trait_args)
+            tcx.require_lang_item(LangItem::AsyncDropInPlace, span)
         };
 
-        let fut = Place::from(self.new_temp(fut_ty));
+        let fut_ty = tcx
+            .instantiate_bound_regions_with_erased(
+                Ty::new_fn_def(tcx, async_drop_fn_def_id, [drop_ty]).fn_sig(tcx),
+            )
+            .output();
+        let fut = self.new_temp(fut_ty);
 
-        // #1:pin_obj_bb >>> obj_ref = &mut obj
-        let obj_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty);
+        // Create an intermediate block that does StorageDead(fut) then jumps to succ.
+        // This is necessary because we do not want to modify statements
+        // in existing blocks, in case those are used somewhere else in MIR.
+        let succ_with_dead = self.new_block_with_statements(
+            unwind,
+            vec![self.storage_dead(fut)],
+            TerminatorKind::Goto { target: succ },
+        );
+        let dropline_with_dead = dropline.map(|target| {
+            self.new_block_with_statements(
+                unwind,
+                vec![self.storage_dead(fut)],
+                TerminatorKind::Goto { target },
+            )
+        });
+        let unwind_with_dead = unwind.map(|target| {
+            self.new_block_with_statements(
+                Unwind::InCleanup,
+                vec![self.storage_dead(fut)],
+                TerminatorKind::Goto { target },
+            )
+        });
+
+        // The yielded value depends on the kind of coroutine, to match what AST lowering does.
+        let coroutine_kind = self.elaborator.body().coroutine_kind().unwrap();
+        let yield_value = match coroutine_kind {
+            // For async gen, we need `yield Poll<OptRet>::Pending`.
+            CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => {
+                let full_yield_ty = self.elaborator.body().yield_ty().unwrap();
+                let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() };
+                let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() };
+                let yield_ty = args.type_at(0);
+                Operand::unevaluated_constant(
+                    tcx,
+                    tcx.require_lang_item(LangItem::AsyncGenPending, span),
+                    tcx.mk_args(&[yield_ty.into()]),
+                    span,
+                )
+            }
+            // For regular async fn, we need `yield ()`.
+            CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
+                Operand::zero_sized_constant(tcx.types.unit, span)
+            }
+            // `is_async_drop` should have checked that.
+            _ => panic!("unexpected coroutine for async drop {coroutine_kind:?}"),
+        };
+
+        // The branching here is tricky and deserves some explanation.
+        //
+        // If we are in the drop code path, ie. we are currently dropping the coroutine.
+        // The state machine follows the `drop` branch in the `yield` terminator.
+        // To repeatedly poll the future, the `drop` branch must loop.
+        // Meanwhile, the `resume` branch corresponds to anomalous execution,
+        // trying to resume the coroutine while it is being dropped. So that branch panics
+        // (`panic_bb`).
+        let panic_bb = self.build_resumed_after_drop_abort_block(unwind_with_dead, coroutine_kind);
+        let (drop_pin_bb, drop_resume_bb, drop_drop_bb) = self.build_pin_poll_yield_loop(
+            CTX_ARG.into(),
+            fut.into(),
+            yield_value.clone(),
+            // If `dropline_with_dead` is set, it points to the continuation of the drop execution.
+            // Otherwise, we are already dropping the coroutine, and `succ_with_dead` does.
+            dropline_with_dead.unwrap_or(succ_with_dead),
+            unwind_with_dead,
+        );
+        self.elaborator
+            .patch()
+            .patch_terminator(drop_resume_bb, TerminatorKind::Goto { target: panic_bb });
+        self.elaborator
+            .patch()
+            .patch_terminator(drop_drop_bb, TerminatorKind::Goto { target: drop_pin_bb });
+
+        // If we are in the regular code path, `dropline_with_dead` is `Some`.
+        //
+        // In that case, the logic is reversed. Normal execution branches on `resume` from the
+        // `yield` terminator. To repeatedly poll the future, that `resume` branch must loop.
+        // When the future is dropped, the `yield` terminator branches to `drop`, which follows to
+        // the previous loop `drop_pin_bb`.
+        let succ_yield_loop = if dropline_with_dead.is_some() {
+            let (pin_bb, resume_bb, drop_bb) = self.build_pin_poll_yield_loop(
+                CTX_ARG.into(),
+                fut.into(),
+                yield_value,
+                // `dropline_with_dead` is `Some`, so the previous loop point to it.
+                succ_with_dead,
+                unwind_with_dead,
+            );
+            self.elaborator
+                .patch()
+                .patch_terminator(resume_bb, TerminatorKind::Goto { target: pin_bb });
+            self.elaborator
+                .patch()
+                .patch_terminator(drop_bb, TerminatorKind::Goto { target: drop_pin_bb });
+            pin_bb
+        } else {
+            // We were already in the drop line, so return the loop we created for it.
+            drop_pin_bb
+        };
+
+        // #2:call_drop_bb >>>
+        //    call AsyncDrop::drop(pin_obj)
+        // OR call async_drop_in_place(pin_obj.pointer)
+        let pin_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
+        let pin_obj_ty = Ty::new_adt(tcx, pin_adt_def, tcx.mk_args(&[obj_ref_ty.into()]));
+        // Where we store the result of Pin<&drop_ty>::new_unchecked(&mut place).
+        let pin_obj_local = self.new_temp(pin_obj_ty);
+        let drop_arg = if call_destructor_only {
+            // `AsyncDrop::drop` takes `self: Pin<&mut Self>`.
+            Operand::Move(pin_obj_local.into())
+        } else {
+            // `async_drop_in_place` takes `obj: &mut T`.
+            Operand::Copy(tcx.mk_place_field(pin_obj_local.into(), FieldIdx::ZERO, obj_ref_ty))
+        };
+        let call_drop_bb = self.new_block_with_statements(
+            unwind_with_dead,
+            vec![self.storage_live(fut)],
+            TerminatorKind::Call {
+                func: Operand::function_handle(tcx, async_drop_fn_def_id, [drop_ty.into()], span),
+                args: [dummy_spanned(drop_arg)].into(),
+                destination: fut.into(),
+                target: Some(succ_yield_loop),
+                unwind: unwind_with_dead.into_action(),
+                call_source: CallSource::Misc,
+                fn_span: self.source_info.span,
+            },
+        );
+
+        // #1:pin_obj_bb >>> call Pin<ObjTy>::new_unchecked(&mut obj)
         let obj_ref_place = Place::from(self.new_temp(obj_ref_ty));
-
-        let term_loc = self.elaborator.terminator_loc(pin_obj_bb);
-        self.elaborator.patch().add_assign(
-            term_loc,
+        let pin_obj_new_unchecked_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, span);
+        let assign_obj_ref_place = self.assign(
             obj_ref_place,
             Rvalue::Ref(
                 tcx.lifetimes.re_erased,
@@ -302,111 +391,250 @@ fn build_async_drop(
                 place,
             ),
         );
-
-        // pin_obj_place preparation
-        let pin_obj_new_unchecked_fn = Ty::new_fn_def(
-            tcx,
-            tcx.require_lang_item(LangItem::PinNewUnchecked, span),
-            [GenericArg::from(obj_ref_ty)],
-        );
-        let pin_obj_ty = pin_obj_new_unchecked_fn.fn_sig(tcx).output().no_bound_vars().unwrap();
-        let pin_obj_place = Place::from(self.new_temp(pin_obj_ty));
-        let pin_obj_new_unchecked_fn = Operand::Constant(Box::new(ConstOperand {
-            span,
-            user_ty: None,
-            const_: Const::zero_sized(pin_obj_new_unchecked_fn),
-        }));
-
-        // Create an intermediate block that does StorageDead(fut) then jumps to succ.
-        // This is necessary because `succ` may differ from `self.succ` (e.g. when
-        // build_async_drop is called from drop_loop, `succ` is the loop header).
-        // Placing StorageDead directly at `self.succ` would miss the loop-back edge,
-        // causing StorageLive(fut) to fire again without a preceding StorageDead.
-        let succ_with_dead = self.new_block_with_statements(
+        self.new_block_with_statements(
             unwind,
-            vec![Statement::new(self.source_info, StatementKind::StorageDead(fut.local))],
-            TerminatorKind::Goto { target: succ },
-        );
-
-        // #3:drop_term_bb
-        let drop_term_bb = self.new_block(
-            unwind,
-            TerminatorKind::Drop {
-                place,
-                target: succ_with_dead,
-                unwind: unwind.into_action(),
-                replace: false,
-                drop: dropline,
-                async_fut: Some(fut.local),
-            },
-        );
-
-        // #2:call_drop_bb
-        let mut call_statements = Vec::new();
-        let drop_arg = if call_destructor_only {
-            pin_obj_place
-        } else {
-            let ty::Adt(adt_def, adt_args) = pin_obj_ty.kind() else {
-                bug!();
-            };
-            let unwrap_ty =
-                adt_def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, adt_args).skip_norm_wip();
-            let obj_ref_place = Place::from(self.new_temp(unwrap_ty));
-            call_statements.push(self.assign(
-                obj_ref_place,
-                Rvalue::Use(
-                    Operand::Copy(tcx.mk_place_field(pin_obj_place, FieldIdx::ZERO, unwrap_ty)),
-                    WithRetag::Yes,
+            vec![assign_obj_ref_place],
+            TerminatorKind::Call {
+                func: Operand::function_handle(
+                    tcx,
+                    pin_obj_new_unchecked_fn,
+                    [obj_ref_ty.into()],
+                    span,
                 ),
-            ));
-
-            obj_ref_place
-        };
-        call_statements
-            .push(Statement::new(self.source_info, StatementKind::StorageLive(fut.local)));
-
-        let call_drop_bb = self.new_block_with_statements(
-            unwind,
-            call_statements,
-            TerminatorKind::Call {
-                func: Operand::function_handle(tcx, drop_fn_def_id, trait_args, span),
-                args: [Spanned { node: Operand::Move(drop_arg), span: DUMMY_SP }].into(),
-                destination: fut,
-                target: Some(drop_term_bb),
-                unwind: unwind.into_action(),
-                call_source: CallSource::Misc,
-                fn_span: self.source_info.span,
-            },
-        );
-        // StorageDead(fut) in unwind block (at the begin)
-        if let Unwind::To(block) = unwind {
-            self.elaborator.patch().add_statement(
-                Location { block, statement_index: 0 },
-                StatementKind::StorageDead(fut.local),
-            );
-        }
-        // StorageDead(fut) in dropline block (at the begin)
-        if let Some(block) = dropline {
-            self.elaborator.patch().add_statement(
-                Location { block, statement_index: 0 },
-                StatementKind::StorageDead(fut.local),
-            );
-        }
-
-        // #1:pin_obj_bb >>> call Pin<ObjTy>::new_unchecked(&mut obj)
-        self.elaborator.patch().patch_terminator(
-            pin_obj_bb,
-            TerminatorKind::Call {
-                func: pin_obj_new_unchecked_fn,
                 args: [dummy_spanned(Operand::Move(obj_ref_place))].into(),
-                destination: pin_obj_place,
+                destination: pin_obj_local.into(),
                 target: Some(call_drop_bb),
                 unwind: unwind.into_action(),
                 call_source: CallSource::Misc,
                 fn_span: span,
             },
+        )
+    }
+
+    fn build_resumed_after_drop_abort_block(
+        &mut self,
+        unwind: Unwind,
+        coroutine_kind: CoroutineKind,
+    ) -> BasicBlock {
+        let tcx = self.tcx();
+        let panic_bb = self.new_block(unwind, TerminatorKind::Unreachable);
+        let msg = AssertMessage::ResumedAfterDrop(coroutine_kind);
+        let false_op = Operand::Constant(Box::new(ConstOperand {
+            span: self.source_info.span,
+            user_ty: None,
+            const_: Const::from_bool(tcx, false),
+        }));
+        self.elaborator.patch().patch_terminator(
+            panic_bb,
+            TerminatorKind::Assert {
+                cond: false_op,
+                expected: true,
+                msg: Box::new(msg),
+                target: panic_bb,
+                unwind: unwind.into_action(),
+            },
         );
-        pin_obj_bb
+        panic_bb
+    }
+
+    /// Build a small MIR loop that pins and polls a future, yielding when
+    /// the future returns `Poll::Pending` and continuing to `ready_target`
+    /// when it returns `Poll::Ready`.
+    ///
+    /// Pseudo-code:
+    /// ```mir
+    /// pin_bb:
+    ///   let pin_fut = Pin::new_unchecked(&mut fut_place);
+    ///   match Future::poll(pin_fut, CTX_ARG) {
+    ///     Poll::Ready => goto succ,
+    ///     Poll::Pending(..) => CTX_ARG = yield () [resume: resume_bb, drop: drop_bb],
+    ///   }
+    /// ```
+    ///
+    ///  Returns: the tuple `(pin_bb, resume_bb, drop_bb)`.
+    #[instrument(level = "trace", skip(self), ret)]
+    fn build_pin_poll_yield_loop(
+        &mut self,
+        resume_place: Place<'tcx>,
+        fut_place: Place<'tcx>,
+        yield_value: Operand<'tcx>,
+        succ: BasicBlock,
+        unwind: Unwind,
+    ) -> (BasicBlock, BasicBlock, BasicBlock) {
+        let tcx = self.tcx();
+        let source_info = self.source_info;
+
+        let resume_arg_ty = resume_place.ty(self.elaborator.body(), tcx).ty;
+        let context_ref_ty = Ty::new_task_context(tcx);
+
+        let poll_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, source_info.span));
+        let poll_enum = Ty::new_adt(tcx, poll_adt_def, tcx.mk_args(&[tcx.types.unit.into()]));
+
+        let fut_ty = self.elaborator.patch_ref().local_ty(fut_place.local);
+        let fut_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fut_ty);
+
+        let pin_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, source_info.span));
+        let fut_pin_ty = Ty::new_adt(tcx, pin_adt_def, tcx.mk_args(&[fut_ref_ty.into()]));
+
+        // Coroutine `transform_async_context` assumes that the local `resume_arg` to a yield
+        // is not used once, so create a special temp for it.
+        let yield_resume_local = self.new_temp(resume_arg_ty);
+        let resume_bb = self.new_block_with_statements(
+            unwind,
+            vec![
+                self.assign(
+                    resume_place,
+                    Rvalue::Use(Operand::Move(yield_resume_local.into()), WithRetag::Yes),
+                ),
+                self.storage_dead(yield_resume_local),
+            ],
+            // This will be transformed by the caller.
+            TerminatorKind::Unreachable,
+        );
+        let dropline_bb = self.new_block_with_statements(
+            unwind,
+            vec![
+                self.assign(
+                    resume_place,
+                    Rvalue::Use(Operand::Move(yield_resume_local.into()), WithRetag::Yes),
+                ),
+                self.storage_dead(yield_resume_local),
+            ],
+            // This will be transformed by the caller.
+            TerminatorKind::Unreachable,
+        );
+        let yield_bb = self.new_block_with_statements(
+            unwind,
+            vec![self.storage_live(yield_resume_local)],
+            TerminatorKind::Yield {
+                value: yield_value,
+                resume: resume_bb,
+                resume_arg: yield_resume_local.into(),
+                drop: Some(dropline_bb),
+            },
+        );
+
+        let poll_unit_local = self.new_temp(poll_enum);
+        let switch_bb = {
+            let poll_ready_variant =
+                tcx.require_lang_item(LangItem::PollReady, self.source_info.span);
+            let poll_ready_variant_idx = poll_adt_def.variant_index_with_id(poll_ready_variant);
+            let poll_pending_variant =
+                tcx.require_lang_item(LangItem::PollPending, self.source_info.span);
+            let poll_pending_variant_idx = poll_adt_def.variant_index_with_id(poll_pending_variant);
+
+            let Discr { val: poll_ready_discr, ty: poll_discr_ty } =
+                poll_enum.discriminant_for_variant(tcx, poll_ready_variant_idx).unwrap();
+            let Discr { val: poll_pending_discr, ty: _ } =
+                poll_enum.discriminant_for_variant(tcx, poll_pending_variant_idx).unwrap();
+
+            let poll_discr_local = self.new_temp(poll_discr_ty);
+            let otherwise_bb = self.elaborator.patch().unreachable_no_cleanup_block();
+            self.new_block_with_statements(
+                unwind,
+                vec![
+                    self.assign(
+                        poll_discr_local.into(),
+                        Rvalue::Discriminant(poll_unit_local.into()),
+                    ),
+                ],
+                TerminatorKind::SwitchInt {
+                    discr: Operand::Move(poll_discr_local.into()),
+                    targets: SwitchTargets::new(
+                        [
+                            // on `Ready`, exit the loop, jump to `succ`
+                            (poll_ready_discr, succ),
+                            // on `Pending`, yield and resume back into the loop
+                            (poll_pending_discr, yield_bb),
+                        ]
+                        .into_iter(),
+                        // otherwise: unreachable
+                        otherwise_bb,
+                    ),
+                },
+            )
+        };
+
+        let fut_pin_local = self.new_temp(fut_pin_ty);
+        let context_ref_local = self.new_temp(context_ref_ty);
+
+        let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, source_info.span);
+        let poll_bb = self.new_block_with_statements(
+            unwind,
+            Vec::new(),
+            TerminatorKind::Call {
+                func: Operand::function_handle(tcx, poll_fn, [fut_ty.into()], source_info.span),
+                args: [
+                    dummy_spanned(Operand::Move(fut_pin_local.into())),
+                    dummy_spanned(Operand::Move(context_ref_local.into())),
+                ]
+                .into(),
+                destination: poll_unit_local.into(),
+                target: Some(switch_bb),
+                unwind: unwind.into_action(),
+                call_source: CallSource::Misc,
+                fn_span: source_info.span,
+            },
+        );
+
+        let get_context_fn = tcx.require_lang_item(LangItem::GetContext, source_info.span);
+        let get_context_bb = {
+            // Coroutine `transform_async_context` assumes that the local argument to `GetContext`
+            // is not used once, so create a special temp for it.
+            let entry_resume_local = self.new_temp(resume_arg_ty);
+            self.new_block_with_statements(
+                unwind,
+                vec![self.assign(
+                    entry_resume_local.into(),
+                    Rvalue::Use(Operand::Move(resume_place), WithRetag::Yes),
+                )],
+                TerminatorKind::Call {
+                    func: Operand::function_handle(
+                        tcx,
+                        get_context_fn,
+                        [tcx.lifetimes.re_erased.into(), tcx.lifetimes.re_erased.into()],
+                        source_info.span,
+                    ),
+                    args: [dummy_spanned(Operand::Move(entry_resume_local.into()))].into(),
+                    destination: context_ref_local.into(),
+                    target: Some(poll_bb),
+                    unwind: unwind.into_action(),
+                    call_source: CallSource::Misc,
+                    fn_span: source_info.span,
+                },
+            )
+        };
+
+        let fut_ref_local = self.new_temp(fut_ref_ty);
+        let fut_pin_new_unchecked_fn =
+            tcx.require_lang_item(LangItem::PinNewUnchecked, source_info.span);
+        let pin_bb = self.new_block_with_statements(
+            unwind,
+            vec![self.assign(
+                fut_ref_local.into(),
+                Rvalue::Ref(
+                    tcx.lifetimes.re_erased,
+                    BorrowKind::Mut { kind: MutBorrowKind::Default },
+                    fut_place,
+                ),
+            )],
+            TerminatorKind::Call {
+                func: Operand::function_handle(
+                    tcx,
+                    fut_pin_new_unchecked_fn,
+                    [fut_ref_ty.into()],
+                    source_info.span,
+                ),
+                args: [dummy_spanned(Operand::Move(fut_ref_local.into()))].into(),
+                destination: fut_pin_local.into(),
+                target: Some(get_context_bb),
+                unwind: unwind.into_action(),
+                call_source: CallSource::Misc,
+                fn_span: source_info.span,
+            },
+        );
+
+        (pin_bb, resume_bb, dropline_bb)
     }
 
     fn build_drop(&mut self, bb: BasicBlock) {
@@ -414,15 +642,17 @@ fn build_drop(&mut self, bb: BasicBlock) {
         if !self.elaborator.patch_ref().block(self.elaborator.body(), bb).is_cleanup
             && self.check_if_can_async_drop(drop_ty, false)
         {
-            self.build_async_drop(
+            let async_drop_bb = self.build_async_drop(
                 self.place,
                 drop_ty,
-                Some(bb),
                 self.succ,
                 self.unwind,
                 self.dropline,
                 false,
             );
+            self.elaborator
+                .patch()
+                .patch_terminator(bb, TerminatorKind::Goto { target: async_drop_bb });
         } else {
             self.elaborator.patch().patch_terminator(
                 bb,
@@ -432,7 +662,6 @@ fn build_drop(&mut self, bb: BasicBlock) {
                     unwind: self.unwind.into_action(),
                     replace: false,
                     drop: None,
-                    async_fut: None,
                 },
             );
         }
@@ -440,6 +669,21 @@ fn build_drop(&mut self, bb: BasicBlock) {
 
     /// Function to check if we can generate an async drop here
     fn check_if_can_async_drop(&mut self, drop_ty: Ty<'tcx>, call_destructor_only: bool) -> bool {
+        if !self.elaborator.allow_async_drops()
+            || !self
+                .elaborator
+                .body()
+                .coroutine
+                .as_ref()
+                .is_some_and(|ck| ck.coroutine_kind.is_async_desugaring())
+        {
+            return false;
+        }
+
+        if drop_ty == self.place_ty(Local::arg(0).into()) {
+            return false;
+        }
+
         let is_async_drop_feature_enabled = if self.tcx().features().async_drop() {
             true
         } else {
@@ -454,10 +698,7 @@ fn check_if_can_async_drop(&mut self, drop_ty: Ty<'tcx>, call_destructor_only: b
         // Short-circuit before calling needs_async_drop/is_async_drop, as those
         // require the `async_drop` lang item to exist (which may not be present
         // in minimal/custom core environments like cranelift's mini_core).
-        if !is_async_drop_feature_enabled
-            || !self.elaborator.body().coroutine.is_some()
-            || !self.elaborator.allow_async_drops()
-        {
+        if !is_async_drop_feature_enabled {
             return false;
         }
 
@@ -842,9 +1083,9 @@ fn open_drop_for_multivariant(
         let mut values = Vec::with_capacity(adt.variants().len());
         let mut normal_blocks = Vec::with_capacity(adt.variants().len());
         let mut unwind_blocks =
-            if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants().len())) };
+            Vec::with_capacity(if unwind.is_cleanup() { 0 } else { adt.variants().len() });
         let mut dropline_blocks =
-            if dropline.is_none() { None } else { Some(Vec::with_capacity(adt.variants().len())) };
+            Vec::with_capacity(if dropline.is_none() { 0 } else { adt.variants().len() });
 
         let mut have_otherwise_with_drop_glue = false;
         let mut have_otherwise = false;
@@ -880,7 +1121,6 @@ fn open_drop_for_multivariant(
                     // I want to minimize the divergence between MSVC
                     // and non-MSVC.
 
-                    let unwind_blocks = unwind_blocks.as_mut().unwrap();
                     let unwind_ladder = vec![Unwind::InCleanup; fields.len() + 1];
                     let dropline_ladder: Vec<Option<BasicBlock>> = vec![None; fields.len() + 1];
                     let halfladder =
@@ -890,7 +1130,7 @@ fn open_drop_for_multivariant(
                 let (normal, _, drop_bb) = self.drop_ladder(fields, succ, unwind, dropline);
                 normal_blocks.push(normal);
                 if dropline.is_some() {
-                    dropline_blocks.as_mut().unwrap().push(drop_bb.unwrap());
+                    dropline_blocks.push(drop_bb.unwrap());
                 }
             } else {
                 have_otherwise = true;
@@ -911,28 +1151,22 @@ fn open_drop_for_multivariant(
         } else if !have_otherwise_with_drop_glue {
             normal_blocks.push(self.goto_block(succ, unwind));
             if let Unwind::To(unwind) = unwind {
-                unwind_blocks.as_mut().unwrap().push(self.goto_block(unwind, Unwind::InCleanup));
+                unwind_blocks.push(self.goto_block(unwind, Unwind::InCleanup));
             }
         } else {
             normal_blocks.push(self.drop_block(succ, unwind));
             if let Unwind::To(unwind) = unwind {
-                unwind_blocks.as_mut().unwrap().push(self.drop_block(unwind, Unwind::InCleanup));
+                unwind_blocks.push(self.drop_block(unwind, Unwind::InCleanup));
             }
         }
 
         (
             self.adt_switch_block(adt, normal_blocks, &values, succ, unwind),
             unwind.map(|unwind| {
-                self.adt_switch_block(
-                    adt,
-                    unwind_blocks.unwrap(),
-                    &values,
-                    unwind,
-                    Unwind::InCleanup,
-                )
+                self.adt_switch_block(adt, unwind_blocks, &values, unwind, Unwind::InCleanup)
             }),
             dropline.map(|dropline| {
-                self.adt_switch_block(adt, dropline_blocks.unwrap(), &values, dropline, unwind)
+                self.adt_switch_block(adt, dropline_blocks, &values, dropline, unwind)
             }),
         )
     }
@@ -992,8 +1226,7 @@ fn destructor_call_block_sync(&mut self, succ: BasicBlock, unwind: Unwind) -> Ba
             )],
             TerminatorKind::Call {
                 func: Operand::function_handle(tcx, drop_fn, [ty.into()], self.source_info.span),
-                args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }]
-                    .into(),
+                args: [dummy_spanned(Operand::Move(Place::from(ref_place)))].into(),
                 destination: unit_temp,
                 target: Some(succ),
                 unwind: unwind.into_action(),
@@ -1012,7 +1245,7 @@ fn destructor_call_block(
     ) -> BasicBlock {
         let ty = self.place_ty(self.place);
         if !unwind.is_cleanup() && self.check_if_can_async_drop(ty, true) {
-            self.build_async_drop(self.place, ty, None, succ, unwind, dropline, true)
+            self.build_async_drop(self.place, ty, succ, unwind, dropline, true)
         } else {
             self.destructor_call_block_sync(succ, unwind)
         }
@@ -1074,15 +1307,11 @@ fn drop_loop(
 
         let place = tcx.mk_place_deref(ptr);
         if !unwind.is_cleanup() && self.check_if_can_async_drop(ety, false) {
-            self.build_async_drop(
-                place,
-                ety,
-                Some(drop_block),
-                loop_block,
-                unwind,
-                dropline,
-                false,
-            );
+            let async_drop_bb =
+                self.build_async_drop(place, ety, loop_block, unwind, dropline, false);
+            self.elaborator
+                .patch()
+                .patch_terminator(drop_block, TerminatorKind::Goto { target: async_drop_bb });
         } else {
             self.elaborator.patch().patch_terminator(
                 drop_block,
@@ -1092,7 +1321,6 @@ fn drop_loop(
                     unwind: unwind.into_action(),
                     replace: false,
                     drop: None,
-                    async_fut: None,
                 },
             );
         }
@@ -1328,7 +1556,6 @@ fn elaborated_drop_block(&mut self) -> BasicBlock {
                 unwind: self.unwind.into_action(),
                 replace: false,
                 drop: self.dropline,
-                async_fut: None,
             },
         );
         self.elaborate_drop(blk);
@@ -1338,15 +1565,7 @@ fn elaborated_drop_block(&mut self) -> BasicBlock {
     fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
         let drop_ty = self.place_ty(self.place);
         if !unwind.is_cleanup() && self.check_if_can_async_drop(drop_ty, false) {
-            self.build_async_drop(
-                self.place,
-                drop_ty,
-                None,
-                self.succ,
-                unwind,
-                self.dropline,
-                false,
-            )
+            self.build_async_drop(self.place, drop_ty, self.succ, unwind, self.dropline, false)
         } else {
             self.new_block(
                 unwind,
@@ -1356,7 +1575,6 @@ fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
                     unwind: unwind.into_action(),
                     replace: false,
                     drop: None,
-                    async_fut: None,
                 },
             )
         }
@@ -1428,4 +1646,12 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
     fn assign(&self, lhs: Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> {
         Statement::new(self.source_info, StatementKind::Assign(Box::new((lhs, rhs))))
     }
+
+    fn storage_live(&self, local: Local) -> Statement<'tcx> {
+        Statement::new(self.source_info, StatementKind::StorageLive(local))
+    }
+
+    fn storage_dead(&self, local: Local) -> Statement<'tcx> {
+        Statement::new(self.source_info, StatementKind::StorageDead(local))
+    }
 }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 3787276..01235b1 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -162,10 +162,6 @@ fn allow_async_drops(&self) -> bool {
         true
     }
 
-    fn terminator_loc(&self, bb: BasicBlock) -> Location {
-        self.patch.terminator_loc(self.body, bb)
-    }
-
     #[instrument(level = "debug", skip(self), ret)]
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
         let ((maybe_init, maybe_uninit), multipart) = match mode {
@@ -336,8 +332,7 @@ fn elaborate_drops(&mut self) {
         // This function should mirror what `collect_drop_flags` does.
         for (bb, data) in self.body.basic_blocks.iter_enumerated() {
             let terminator = data.terminator();
-            let TerminatorKind::Drop { place, target, unwind, replace, drop, async_fut: _ } =
-                terminator.kind
+            let TerminatorKind::Drop { place, target, unwind, replace, drop } = terminator.kind
             else {
                 continue;
             };
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 434f969..f234166 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -413,14 +413,8 @@ fn check_callee_mir_body(
 
             let term = blk.terminator();
             let caller_attrs = tcx.codegen_fn_attrs(self.caller_def_id());
-            if let TerminatorKind::Drop {
-                ref place,
-                target,
-                unwind,
-                replace: _,
-                drop: _,
-                async_fut: _,
-            } = term.kind
+            if let TerminatorKind::Drop { ref place, target, unwind, replace: _, drop: _ } =
+                term.kind
             {
                 work_list.push(target);
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 3106042..ad7affe 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -51,6 +51,9 @@
 mod ssa;
 mod trivial_const;
 
+/// Exposed for rustc drivers.
+pub use shim::build_drop_shim;
+
 /// We import passes via this macro so that we can have a static list of pass names
 /// (used to verify CLI arguments). It takes a list of modules, followed by the passes
 /// declared within them.
diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
index c354279..0bc5704 100644
--- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
+++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
@@ -137,7 +137,6 @@ fn visit(&mut self, block: BasicBlock) {
                     unwind: _,
                     replace: _,
                     drop: _,
-                    async_fut: _,
                 } = &terminator.kind
                 && place_has_common_prefix(dropped_place, self.place)
             {
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index 015bae5..da10777 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -166,11 +166,6 @@ pub(crate) fn block<'a>(
         }
     }
 
-    pub(crate) fn terminator_loc(&self, body: &Body<'tcx>, bb: BasicBlock) -> Location {
-        let offset = self.block(body, bb).statements.len();
-        Location { block: bb, statement_index: offset }
-    }
-
     /// Queues the addition of a new temporary with additional local info.
     pub(crate) fn new_local_with_info(
         &mut self,
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 7f92199..dede4a3 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -30,40 +30,6 @@ pub(super) fn provide(providers: &mut Providers) {
     providers.mir_shims = make_shim;
 }
 
-// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses
-struct FixProxyFutureDropVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    replace_to: Local,
-}
-
-impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn visit_place(
-        &mut self,
-        place: &mut Place<'tcx>,
-        _context: PlaceContext,
-        _location: Location,
-    ) {
-        if place.local == Local::from_u32(1) {
-            if place.projection.len() == 1 {
-                assert!(matches!(
-                    place.projection.first(),
-                    Some(ProjectionElem::Field(FieldIdx::ZERO, _))
-                ));
-                *place = Place::from(self.replace_to);
-            } else if place.projection.len() == 2 {
-                assert!(matches!(place.projection[0], ProjectionElem::Field(FieldIdx::ZERO, _)));
-                assert!(matches!(place.projection[1], ProjectionElem::Deref));
-                *place =
-                    Place::from(self.replace_to).project_deeper(&[ProjectionElem::Deref], self.tcx);
-            }
-        }
-    }
-}
-
 fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> {
     debug!("make_shim({:?})", instance);
 
@@ -160,7 +126,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
                 return body;
             }
 
-            build_drop_shim(tcx, def_id, ty)
+            build_drop_shim(tcx, def_id, ty, ty::TypingEnv::post_analysis(tcx, def_id))
         }
         ty::InstanceKind::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance),
         ty::InstanceKind::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
@@ -190,7 +156,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
             // Main pass required here is StateTransform to convert sync drop ladder
             // into coroutine.
             // Others are minimal passes as for sync drop glue shim
-            pm::run_passes(
+            pm::run_passes_no_validate(
                 tcx,
                 &mut body,
                 &[
@@ -201,7 +167,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
                     &crate::coroutine::StateTransform,
                 ],
                 Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
-                pm::Optimizations::Allowed,
             );
             run_optimization_passes(tcx, &mut body);
             debug!("make_shim({:?}) = {:?}", instance, body);
@@ -296,7 +261,16 @@ fn local_decls_for_sig<'tcx>(
         .collect()
 }
 
-fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
+/// Builds the drop glue for the provided type. The `def_id` is that of `core::ptr::drop_glue`.
+///
+/// Inside rustc this is only called on a monomorphic type, but we expose the function for
+/// rustc_driver writers to be able to generate drop glue for a polymorphic type.
+pub fn build_drop_shim<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    ty: Option<Ty<'tcx>>,
+    typing_env: ty::TypingEnv<'tcx>,
+) -> Body<'tcx> {
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
     assert!(!matches!(ty, Some(ty) if ty.is_coroutine()));
@@ -368,7 +342,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
         });
     } else {
         let patch = {
-            let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
             let mut elaborator = DropShimElaborator {
                 body: &body,
                 patch: MirPatch::new(&body),
@@ -463,9 +436,6 @@ fn typing_env(&self) -> ty::TypingEnv<'tcx> {
         self.typing_env
     }
 
-    fn terminator_loc(&self, bb: BasicBlock) -> Location {
-        self.patch.terminator_loc(self.body, bb)
-    }
     fn allow_async_drops(&self) -> bool {
         self.produce_async_drops
     }
@@ -727,7 +697,6 @@ fn clone_fields<I>(
                     unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
                     replace: false,
                     drop: None,
-                    async_fut: None,
                 },
                 /* is_cleanup */ true,
             );
@@ -994,7 +963,6 @@ fn build_call_shim<'tcx>(
                 unwind: UnwindAction::Continue,
                 replace: false,
                 drop: None,
-                async_fut: None,
             },
             false,
         );
@@ -1013,7 +981,6 @@ fn build_call_shim<'tcx>(
                 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
                 replace: false,
                 drop: None,
-                async_fut: None,
             },
             /* is_cleanup */ true,
         );
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 3a0d0ce..e9c317e 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -9,8 +9,11 @@
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt};
 
 use super::*;
+use crate::deref_separator::deref_finder;
 use crate::patch::MirPatch;
 
+const SELF_ARG: Local = Local::arg(0);
+
 pub(super) fn build_async_destructor_ctor_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
@@ -39,12 +42,12 @@ pub(super) fn build_async_destructor_ctor_shim<'tcx>(
 }
 
 // build_drop_shim analog for async drop glue (for generated coroutine poll function)
+#[tracing::instrument(level = "trace", skip(tcx), ret)]
 pub(super) fn build_async_drop_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     ty: Ty<'tcx>,
 ) -> Body<'tcx> {
-    debug!("build_async_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
     let ty::Coroutine(_, parent_args) = ty.kind() else {
         bug!();
     };
@@ -75,7 +78,7 @@ pub(super) fn build_async_drop_shim<'tcx>(
     let source_info = SourceInfo::outermost(span);
 
     // The first argument (index 0) which will be local 1 (after the return value).
-    let coroutine_layout = Place::from(Local::arg(0));
+    let coroutine_layout = Place::from(SELF_ARG);
     let coroutine_layout_dropee =
         tcx.mk_place_field(coroutine_layout, FieldIdx::new(0), drop_ptr_ty);
 
@@ -93,7 +96,6 @@ pub(super) fn build_async_drop_shim<'tcx>(
                 unwind: UnwindAction::Continue,
                 replace: false,
                 drop: None,
-                async_fut: None,
             }
         } else {
             TerminatorKind::Goto { target: return_block }
@@ -111,45 +113,47 @@ pub(super) fn build_async_drop_shim<'tcx>(
         parent_args.as_coroutine().resume_ty(),
     )));
     body.phase = MirPhase::Runtime(RuntimePhase::Initial);
-    if !needs_async_drop || drop_ty.references_error() {
-        // Returning noop body for types without `need async drop`
-        // (or sync Drop in case of !`need async drop` && `need drop`).
-        // And also for error types.
-        return body;
+
+    // Returning noop body for types without `need async drop`
+    // (or sync Drop in case of !`need async drop` && `need drop`).
+    // And also for error types.
+    if needs_async_drop && !drop_ty.references_error() {
+        let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span)));
+        let st_kind = StatementKind::Assign(Box::new((
+            dropee_ptr,
+            Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes),
+        )));
+        body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind));
+
+        let dropline = body.basic_blocks.last_index();
+
+        let patch = {
+            let mut elaborator = DropShimElaborator {
+                body: &body,
+                patch: MirPatch::new(&body),
+                tcx,
+                typing_env,
+                produce_async_drops: true,
+            };
+            let dropee = tcx.mk_place_deref(dropee_ptr);
+            let resume_block = elaborator.patch.resume_block();
+            elaborate_drop(
+                &mut elaborator,
+                source_info,
+                dropee,
+                (),
+                return_block,
+                Unwind::To(resume_block),
+                START_BLOCK,
+                dropline,
+            );
+            elaborator.patch
+        };
+        patch.apply(&mut body);
     }
 
-    let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span)));
-    let st_kind = StatementKind::Assign(Box::new((
-        dropee_ptr,
-        Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes),
-    )));
-    body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind));
-
-    let dropline = body.basic_blocks.last_index();
-
-    let patch = {
-        let mut elaborator = DropShimElaborator {
-            body: &body,
-            patch: MirPatch::new(&body),
-            tcx,
-            typing_env,
-            produce_async_drops: true,
-        };
-        let dropee = tcx.mk_place_deref(dropee_ptr);
-        let resume_block = elaborator.patch.resume_block();
-        elaborate_drop(
-            &mut elaborator,
-            source_info,
-            dropee,
-            (),
-            return_block,
-            Unwind::To(resume_block),
-            START_BLOCK,
-            dropline,
-        );
-        elaborator.patch
-    };
-    patch.apply(&mut body);
+    // We did not bother respecting deref separation, do it here.
+    deref_finder(tcx, &mut body, false);
 
     body
 }
@@ -196,87 +200,85 @@ fn build_adrop_for_coroutine_shim<'tcx>(
     let ty::Coroutine(coroutine_def_id, impl_args) = impl_ty.kind() else {
         bug!("build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})", instance);
     };
-    let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty);
-    // taking _1.0 (impl from Pin)
-    let pin_proxy_layout_local = Local::new(1);
     let source_info = SourceInfo::outermost(span);
-    // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>`
-    // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>`
-    // let mut _x: &mut CorLayout = &mut *_1.0.0;
-    // Replace old _1.0 accesses into _x accesses;
     let body = tcx.optimized_mir(*coroutine_def_id).future_drop_poll().unwrap();
     let mut body: Body<'tcx> =
         EarlyBinder::bind(body.clone()).instantiate(tcx, impl_args).skip_norm_wip();
     body.source.instance = instance;
     body.phase = MirPhase::Runtime(RuntimePhase::Initial);
     body.var_debug_info.clear();
+
+    // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>`
+    // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>`
+    // let mut _x: &mut CorLayout = &mut *_1.0.0;
+    // Replace old _1.0 accesses into _x accesses;
+    let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty);
+
     let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
     let args = tcx.mk_args(&[proxy_ref.into()]);
     let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args);
 
     let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty);
-
-    let proxy_ref_local = body.local_decls.push(LocalDecl::new(proxy_ref, span));
     let cor_ref_local = body.local_decls.push(LocalDecl::new(cor_ref, span));
 
     FixProxyFutureDropVisitor { tcx, replace_to: cor_ref_local }.visit_body(&mut body);
+
     // Now changing first arg from Pin<&mut ImplCoroutine> to Pin<&mut ProxyCoroutine>
-    body.local_decls[pin_proxy_layout_local] = LocalDecl::new(pin_proxy_ref, span);
+    body.local_decls[SELF_ARG] = LocalDecl::new(pin_proxy_ref, span);
 
-    {
-        let mut idx: usize = 0;
-        // _proxy = _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout
-        let proxy_ref_place = Place::from(pin_proxy_layout_local)
-            .project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx);
-        body.basic_blocks_mut()[START_BLOCK].statements.insert(
-            idx,
-            Statement::new(
-                source_info,
-                StatementKind::Assign(Box::new((
-                    Place::from(proxy_ref_local),
-                    Rvalue::Use(Operand::Copy(proxy_ref_place), WithRetag::Yes),
-                ))),
-            ),
-        );
-        idx += 1;
+    // Build the projection to assign `cor_ref_local = _1.<projection>`.
+    let mut pin_proxy_to_cor_projection = vec![
+        // _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout
+        PlaceElem::Field(FieldIdx::ZERO, proxy_ref),
+    ];
 
-        // _cor_ref_tmp = (*(*_proxy).0).0...
-        let mut cor_ref_tmp_local = proxy_ref_local;
-        proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| {
-            if ty != proxy_ty {
-                let ty_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
-                let impl_ptr_place = Place::from(cor_ref_tmp_local).project_deeper(
-                    &[PlaceElem::Deref, PlaceElem::Field(FieldIdx::ZERO, ty_ref)],
-                    tcx,
-                );
-                cor_ref_tmp_local = body.local_decls.push(LocalDecl::new(ty_ref, span));
-                body.basic_blocks_mut()[START_BLOCK].statements.insert(
-                    idx,
-                    Statement::new(
-                        source_info,
-                        StatementKind::Assign(Box::new((
-                            Place::from(cor_ref_tmp_local),
-                            Rvalue::Use(Operand::Copy(impl_ptr_place), WithRetag::Yes),
-                        ))),
-                    ),
-                );
-                idx += 1;
-            }
-        });
+    // _cor_ref_tmp = (*(*_proxy).0).0...
+    proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| {
+        if ty != proxy_ty {
+            let ty_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
+            pin_proxy_to_cor_projection.push(PlaceElem::Deref);
+            pin_proxy_to_cor_projection.push(PlaceElem::Field(FieldIdx::ZERO, ty_ref));
+        }
+    });
 
-        // _cor_ref = cor_ref_tmp
-        body.basic_blocks_mut()[START_BLOCK].statements.insert(
-            idx,
-            Statement::new(
-                source_info,
-                StatementKind::Assign(Box::new((
-                    Place::from(cor_ref_local),
-                    Rvalue::Use(Operand::Move(Place::from(cor_ref_tmp_local)), WithRetag::Yes),
-                ))),
-            ),
-        );
+    // _cor_ref = cor_ref_tmp
+    let projected_pin = Place::from(SELF_ARG).project_deeper(&pin_proxy_to_cor_projection, tcx);
+    body.basic_blocks_mut()[START_BLOCK].statements.insert(
+        0,
+        Statement::new(
+            source_info,
+            StatementKind::Assign(Box::new((
+                Place::from(cor_ref_local),
+                Rvalue::Use(Operand::Move(projected_pin), WithRetag::Yes),
+            ))),
+        ),
+    );
+
+    // We did not bother respecting deref separation, do it here.
+    deref_finder(tcx, &mut body, false);
+
+    return body;
+
+    /// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses
+    struct FixProxyFutureDropVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        replace_to: Local,
     }
-    body
+
+    impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, _: Location) {
+            if place.local == SELF_ARG
+                && let Some((first, rest)) = place.projection.split_first()
+            {
+                assert!(matches!(first, ProjectionElem::Field(FieldIdx::ZERO, _)));
+                *place = Place::from(self.replace_to).project_deeper(rest, self.tcx);
+            }
+        }
+    }
 }
 
 // When dropping async drop coroutine, we continue its execution.
@@ -291,9 +293,8 @@ fn build_adrop_for_adrop_shim<'tcx>(
     let source_info = SourceInfo::outermost(span);
     let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty);
     // taking _1.0 (impl from Pin)
-    let pin_proxy_layout_local = Local::new(1);
-    let proxy_ref_place = Place::from(pin_proxy_layout_local)
-        .project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx);
+    let proxy_ref_place =
+        Place::from(SELF_ARG).project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx);
     let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty);
 
     // ret_ty = `Poll<()>`
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 815b94d..3dca3f0 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -367,6 +367,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 self.check_unwind_edge(location, *unwind);
                 if let Some(drop) = drop {
                     self.check_edge(location, *drop, EdgeKind::Normal);
+                    if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                        self.fail(
+                            location,
+                            "`async drop` should have been removed after drop elaboration",
+                        );
+                    }
                 }
             }
             TerminatorKind::Call { func, args, .. }
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 1021852..812979d 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -25,10 +25,7 @@ fn passes_vectors_by_value(mode: &PassMode, repr: &BackendRepr) -> UsesVectorReg
     match mode {
         PassMode::Ignore | PassMode::Indirect { .. } => UsesVectorRegisters::No,
         PassMode::Cast { pad_i32: _, cast }
-            if cast
-                .prefix
-                .iter()
-                .any(|r| r.is_some_and(|x| matches!(x.kind, RegKind::Vector { .. })))
+            if cast.prefix.iter().any(|x| matches!(x.kind, RegKind::Vector { .. }))
                 || matches!(cast.rest.unit.kind, RegKind::Vector { .. }) =>
         {
             UsesVectorRegisters::FixedVector
diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
index 47d33985..b7e2101 100644
--- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
@@ -41,14 +41,14 @@ pub(super) fn compute_alias_relate_goal(
         // `{type error}` if the alias still contains infer vars, so we also
         // accept alias-relate goals where one of the terms is an error.
         debug_assert!(
-            lhs.to_alias_term(self.cx()).is_some()
-                || rhs.to_alias_term(self.cx()).is_some()
+            lhs.to_alias_term().is_some()
+                || rhs.to_alias_term().is_some()
                 || lhs.is_error()
                 || rhs.is_error()
         );
 
         // Structurally normalize the lhs.
-        let lhs = if let Some(alias) = lhs.to_alias_term(self.cx()) {
+        let lhs = if let Some(alias) = lhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(lhs);
             self.add_goal(
                 GoalSource::TypeRelating,
@@ -60,7 +60,7 @@ pub(super) fn compute_alias_relate_goal(
         };
 
         // Structurally normalize the rhs.
-        let rhs = if let Some(alias) = rhs.to_alias_term(self.cx()) {
+        let rhs = if let Some(alias) = rhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(rhs);
             self.add_goal(
                 GoalSource::TypeRelating,
@@ -87,7 +87,7 @@ pub(super) fn compute_alias_relate_goal(
             ty::AliasRelationDirection::Equate => ty::Invariant,
             ty::AliasRelationDirection::Subtype => ty::Covariant,
         };
-        match (lhs.to_alias_term(self.cx()), rhs.to_alias_term(self.cx())) {
+        match (lhs.to_alias_term(), rhs.to_alias_term()) {
             (None, None) => {
                 self.relate(param_env, lhs, variance, rhs)?;
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index fbd6bdf..04da730 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -247,7 +247,7 @@ fn compute_const_arg_has_type_goal(
                     .map_err(Into::into);
             }
             ty::ConstKind::Unevaluated(uv) => {
-                self.cx().type_of(uv.def.into()).instantiate(self.cx(), uv.args).skip_norm_wip()
+                self.cx().type_of(uv.kind.def_id()).instantiate(self.cx(), uv.args).skip_norm_wip()
             }
             ty::ConstKind::Expr(_) => unimplemented!(
                 "`feature(generic_const_exprs)` is not supported in the new trait solver"
@@ -368,7 +368,7 @@ fn structurally_normalize_term(
         param_env: I::ParamEnv,
         term: I::Term,
     ) -> Result<I::Term, NoSolutionOrRerunNonErased> {
-        if let Some(_) = term.to_alias_term(self.cx()) {
+        if let Some(_) = term.to_alias_term() {
             let normalized_term = self.next_term_infer_of_kind(term);
             let alias_relate_goal = Goal::new(
                 self.cx(),
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 e9a4d7e..afec80e 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
@@ -49,7 +49,7 @@ pub(super) fn compute_normalizes_to_goal(
             ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => {
                 self.normalize_free_alias(goal).map_err(Into::into)
             }
-            ty::AliasTermKind::UnevaluatedConst { def_id } => {
+            ty::AliasTermKind::AnonConst { def_id } => {
                 self.normalize_anon_const(goal, def_id).map_err(Into::into)
             }
         }
@@ -416,7 +416,8 @@ fn consider_impl_candidate(
                 }
                 ty::AliasTermKind::ProjectionConst { .. } => {
                     let uv = ty::UnevaluatedConst::new(
-                        target_item_def_id.into().try_into().unwrap(),
+                        cx,
+                        ty::UnevaluatedConstKind::new_from_def_id(cx, target_item_def_id.into()),
                         target_args,
                     );
                     return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv);
diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs
index 2916f53..6aceae2 100644
--- a/compiler/rustc_passes/src/eii.rs
+++ b/compiler/rustc_passes/src/eii.rs
@@ -141,6 +141,7 @@ struct FoundEii {
                         decl_crate_name: tcx.crate_name(decl_crate),
                         // FIXME: shouldn't call `item_name`
                         name: decl.name.name,
+                        kind: tcx.def_kind(decl.foreign_item).descr(decl.foreign_item),
                         span: decl.name.span,
                         help: (),
                     });
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index b87a43e..208aa65 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1209,12 +1209,13 @@ pub(crate) struct EiiWithTrackCaller {
 }
 
 #[derive(Diagnostic)]
-#[diag("`#[{$name}]` required, but not found")]
+#[diag("`#[{$name}]` {$kind} required, but not found")]
 pub(crate) struct EiiWithoutImpl {
     #[primary_span]
     #[label("expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}`")]
     pub span: Span,
     pub name: Symbol,
+    pub kind: &'static str,
 
     pub current_crate_name: Symbol,
     pub decl_crate_name: Symbol,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index de5c003..9cf0576 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -788,8 +788,7 @@ fn enqueue_def_id(&mut self, def_id: LocalDefId) {
             }
 
             DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy => {
-                // FIXME: `EmbargoVisitor` can't check assoc items(see `check_def_id`).
-                // Let's traverse the whole impl/trait.
+                // Traverse the whole impl/trait.
                 self.ev.queue.insert(self.ev.tcx.local_parent(def_id));
             }
 
@@ -843,6 +842,10 @@ fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display
             // All effective visibilities except `reachable_through_impl_trait` are limited to
             // nominal visibility. If any type or trait is leaked farther than that, it will
             // produce type privacy errors on any use, so we don't consider it leaked.
+            //
+            // FIXME: If self.level == Level::Reachable and self.ev == (priv, priv, priv, pub),
+            // then the effective visibility of def_id wouldn't be updated at level
+            // `ReachableThroughImplTrait` due to max_vis. Could this lead to a privacy violation?
             let max_vis = (self.level != Level::ReachableThroughImplTrait)
                 .then(|| self.ev.tcx.local_visibility(def_id));
             if self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level) {
diff --git a/compiler/rustc_public/src/compiler_interface.rs b/compiler/rustc_public/src/compiler_interface.rs
index c2f36be..7953af3 100644
--- a/compiler/rustc_public/src/compiler_interface.rs
+++ b/compiler/rustc_public/src/compiler_interface.rs
@@ -79,183 +79,191 @@ pub(crate) struct CompilerInterface<'tcx> {
 }
 
 impl<'tcx> CompilerInterface<'tcx> {
-    pub(crate) fn entry_fn(&self) -> Option<CrateItem> {
+    fn with_cx<R>(
+        &self,
+        f: impl FnOnce(&mut Tables<'tcx, BridgeTys>, &CompilerCtxt<'tcx, BridgeTys>) -> R,
+    ) -> R {
         let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = cx.entry_fn();
-        Some(tables.crate_item(did?))
+        let cx = self.cx.borrow();
+        f(&mut *tables, &*cx)
+    }
+
+    pub(crate) fn entry_fn(&self) -> Option<CrateItem> {
+        self.with_cx(|tables, cx| {
+            let did = cx.entry_fn();
+            Some(tables.crate_item(did?))
+        })
     }
 
     /// Retrieve all items of the local crate that have a MIR associated with them.
     pub(crate) fn all_local_items(&self) -> CrateItems {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.all_local_items().iter().map(|did| tables.crate_item(*did)).collect()
+        self.with_cx(|tables, cx| {
+            cx.all_local_items().iter().map(|did| tables.crate_item(*did)).collect()
+        })
     }
 
     /// Retrieve the body of a function.
     /// This function will panic if the body is not available.
     pub(crate) fn mir_body(&self, item: DefId) -> mir::Body {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[item];
-        cx.mir_body(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[item];
+            cx.mir_body(did).stable(tables, cx)
+        })
     }
 
     /// Check whether the body of a function is available.
     pub(crate) fn has_body(&self, item: DefId) -> bool {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def = item.internal(&mut *tables, cx.tcx);
-        cx.has_body(def)
+        self.with_cx(|tables, cx| {
+            let def = item.internal(tables, cx.tcx);
+            cx.has_body(def)
+        })
     }
 
     pub(crate) fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.foreign_modules(crate_num.internal(&mut *tables, cx.tcx))
-            .iter()
-            .map(|did| tables.foreign_module_def(*did))
-            .collect()
+        self.with_cx(|tables, cx| {
+            cx.foreign_modules(crate_num.internal(tables, cx.tcx))
+                .iter()
+                .map(|did| tables.foreign_module_def(*did))
+                .collect()
+        })
     }
 
     /// Retrieve all functions defined in this crate.
     pub(crate) fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx.tcx);
-        cx.crate_functions(krate).iter().map(|did| tables.fn_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            let krate = crate_num.internal(tables, cx.tcx);
+            cx.crate_functions(krate).iter().map(|did| tables.fn_def(*did)).collect()
+        })
     }
 
     /// Retrieve all static items defined in this crate.
     pub(crate) fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx.tcx);
-        cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            let krate = crate_num.internal(tables, cx.tcx);
+            cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect()
+        })
     }
 
     pub(crate) fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[mod_def.def_id()];
-        cx.foreign_module(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[mod_def.def_id()];
+            cx.foreign_module(did).stable(tables, cx)
+        })
     }
 
     pub(crate) fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[mod_def.def_id()];
-        cx.foreign_items(did).iter().map(|did| tables.foreign_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            let did = tables[mod_def.def_id()];
+            cx.foreign_items(did).iter().map(|did| tables.foreign_def(*did)).collect()
+        })
     }
 
     pub(crate) fn all_trait_decls(&self) -> TraitDecls {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.all_trait_decls().map(|did| tables.trait_def(did)).collect()
+        self.with_cx(|tables, cx| cx.all_trait_decls().map(|did| tables.trait_def(did)).collect())
     }
 
     pub(crate) fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx.tcx);
-        cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            let krate = crate_num.internal(tables, cx.tcx);
+            cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect()
+        })
     }
 
     pub(crate) fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[trait_def.0];
-        cx.trait_decl(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[trait_def.0];
+            cx.trait_decl(did).stable(tables, cx)
+        })
     }
 
     pub(crate) fn all_trait_impls(&self) -> ImplTraitDecls {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.all_trait_impls().iter().map(|did| tables.impl_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            cx.all_trait_impls().iter().map(|did| tables.impl_def(*did)).collect()
+        })
     }
 
     pub(crate) fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx.tcx);
-        cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect()
+        self.with_cx(|tables, cx| {
+            let krate = crate_num.internal(tables, cx.tcx);
+            cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect()
+        })
     }
 
     pub(crate) fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[trait_impl.0];
-        cx.trait_impl(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[trait_impl.0];
+            cx.trait_impl(did).stable(tables, cx)
+        })
     }
 
     pub(crate) fn generics_of(&self, def_id: DefId) -> Generics {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.generics_of(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.generics_of(did).stable(tables, cx)
+        })
     }
 
     pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        let (parent, kinds) = cx.predicates_of(did);
-        crate::ty::GenericPredicates {
-            parent: parent.map(|did| tables.trait_def(did)),
-            predicates: kinds
-                .iter()
-                .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx)))
-                .collect(),
-        }
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            let (parent, kinds) = cx.predicates_of(did);
+            crate::ty::GenericPredicates {
+                parent: parent.map(|did| tables.trait_def(did)),
+                predicates: kinds
+                    .iter()
+                    .map(|(kind, span)| (kind.stable(tables, cx), span.stable(tables, cx)))
+                    .collect(),
+            }
+        })
     }
 
     pub(crate) fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        let (parent, kinds) = cx.explicit_predicates_of(did);
-        crate::ty::GenericPredicates {
-            parent: parent.map(|did| tables.trait_def(did)),
-            predicates: kinds
-                .iter()
-                .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx)))
-                .collect(),
-        }
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            let (parent, kinds) = cx.explicit_predicates_of(did);
+            crate::ty::GenericPredicates {
+                parent: parent.map(|did| tables.trait_def(did)),
+                predicates: kinds
+                    .iter()
+                    .map(|(kind, span)| (kind.stable(tables, cx), span.stable(tables, cx)))
+                    .collect(),
+            }
+        })
     }
 
     /// Get information about the local crate.
     pub(crate) fn local_crate(&self) -> Crate {
-        let cx = &*self.cx.borrow();
-        smir_crate(cx, cx.local_crate_num())
+        self.with_cx(|_, cx| smir_crate(cx, cx.local_crate_num()))
     }
 
     /// Retrieve a list of all external crates.
     pub(crate) fn external_crates(&self) -> Vec<Crate> {
-        let cx = &*self.cx.borrow();
-        cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
+        self.with_cx(|_, cx| {
+            cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
+        })
     }
 
     /// Find a crate with the given name.
     pub(crate) fn find_crates(&self, name: &str) -> Vec<Crate> {
-        let cx = &*self.cx.borrow();
-        cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
+        self.with_cx(|_, cx| {
+            cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
+        })
     }
 
     /// Returns the name of given `DefId`.
     pub(crate) fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol {
-        let tables = self.tables.borrow();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.def_name(did, trimmed)
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.def_name(did, trimmed)
+        })
     }
 
     /// Returns the parent of the given `DefId`.
     pub(crate) fn def_parent(&self, def_id: DefId) -> Option<DefId> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.def_parent(did).map(|did| tables.create_def_id(did))
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.def_parent(did).map(|did| tables.create_def_id(did))
+        })
     }
 
     /// Return registered tool attributes with the given attribute name.
@@ -266,184 +274,169 @@ pub(crate) fn def_parent(&self, def_id: DefId) -> Option<DefId> {
     /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
     /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
     pub(crate) fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.tool_attrs(did, attr)
-            .into_iter()
-            .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx)))
-            .collect()
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.tool_attrs(did, attr)
+                .into_iter()
+                .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(tables, cx)))
+                .collect()
+        })
     }
 
     /// Get all tool attributes of a definition.
     pub(crate) fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.all_tool_attrs(did)
-            .into_iter()
-            .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx)))
-            .collect()
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.all_tool_attrs(did)
+                .into_iter()
+                .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(tables, cx)))
+                .collect()
+        })
     }
 
     /// Returns printable, human readable form of `Span`.
     pub(crate) fn span_to_string(&self, span: Span) -> String {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let sp = tables.spans[span];
-        cx.span_to_string(sp)
+        self.with_cx(|tables, cx| {
+            let sp = tables.spans[span];
+            cx.span_to_string(sp)
+        })
     }
 
     /// Return filename from given `Span`, for diagnostic purposes.
     pub(crate) fn get_filename(&self, span: &Span) -> Filename {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let sp = tables.spans[*span];
-        cx.get_filename(sp)
+        self.with_cx(|tables, cx| {
+            let sp = tables.spans[*span];
+            cx.get_filename(sp)
+        })
     }
 
     /// Return lines corresponding to this `Span`.
     pub(crate) fn get_lines(&self, span: &Span) -> LineInfo {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let sp = tables.spans[*span];
-        let lines = cx.get_lines(sp);
-        LineInfo::from(lines)
+        self.with_cx(|tables, cx| {
+            let sp = tables.spans[*span];
+            let lines = cx.get_lines(sp);
+            LineInfo::from(lines)
+        })
     }
 
     /// Returns the `kind` of given `DefId`.
     pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind {
-        let tables = self.tables.borrow();
-        let cx = &*self.cx.borrow();
-        let did = tables[item.0];
-        new_item_kind(cx.def_kind(did))
+        self.with_cx(|tables, cx| {
+            let did = tables[item.0];
+            new_item_kind(cx.def_kind(did))
+        })
     }
 
     /// Returns whether this is a foreign item.
     pub(crate) fn is_foreign_item(&self, item: DefId) -> bool {
-        let tables = self.tables.borrow();
-        let cx = &*self.cx.borrow();
-        let did = tables[item];
-        cx.is_foreign_item(did)
+        self.with_cx(|tables, cx| {
+            let did = tables[item];
+            cx.is_foreign_item(did)
+        })
     }
 
     /// Returns the kind of a given foreign item.
     pub(crate) fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = tables[def.def_id()];
-        let def_kind = cx.foreign_item_kind(def_id);
-        match def_kind {
-            DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
-            DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)),
-            DefKind::ForeignTy => {
-                use rustc_public_bridge::context::TyHelpers;
-                ForeignItemKind::Type(tables.intern_ty(cx.new_foreign(def_id)))
+        self.with_cx(|tables, cx| {
+            let def_id = tables[def.def_id()];
+            let def_kind = cx.foreign_item_kind(def_id);
+            match def_kind {
+                DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
+                DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)),
+                DefKind::ForeignTy => {
+                    use rustc_public_bridge::context::TyHelpers;
+                    ForeignItemKind::Type(tables.intern_ty(cx.new_foreign(def_id)))
+                }
+                def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind),
             }
-            def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind),
-        }
+        })
     }
 
     /// Returns the kind of a given algebraic data type.
     pub(crate) fn adt_kind(&self, def: AdtDef) -> AdtKind {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_kind(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| cx.adt_kind(def.internal(tables, cx.tcx)).stable(tables, cx))
     }
 
     /// Returns if the ADT is a box.
     pub(crate) fn adt_is_box(&self, def: AdtDef) -> bool {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_is_box(def.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| cx.adt_is_box(def.internal(tables, cx.tcx)))
     }
 
     /// Returns whether this ADT is simd.
     pub(crate) fn adt_is_simd(&self, def: AdtDef) -> bool {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_is_simd(def.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| cx.adt_is_simd(def.internal(tables, cx.tcx)))
     }
 
     /// Returns whether this definition is a C string.
     pub(crate) fn adt_is_cstr(&self, def: AdtDef) -> bool {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_is_cstr(def.0.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| cx.adt_is_cstr(def.0.internal(tables, cx.tcx)))
     }
 
     /// Returns the representation options for this ADT
     pub(crate) fn adt_repr(&self, def: AdtDef) -> ReprOptions {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_repr(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| cx.adt_repr(def.internal(tables, cx.tcx)).stable(tables, cx))
     }
 
     /// Retrieve the function signature for the given generic arguments.
     pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        cx.fn_sig(def_id, args_ref).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            let args_ref = args.internal(tables, cx.tcx);
+            cx.fn_sig(def_id, args_ref).stable(tables, cx)
+        })
     }
 
     /// Retrieve the constness for the given function definition.
     pub(crate) fn constness(&self, def: FnDef) -> Constness {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        cx.constness(def_id).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            cx.constness(def_id).stable(tables, cx)
+        })
     }
 
     /// Retrieve the asyncness for the given function definition.
     pub(crate) fn asyncness(&self, def: FnDef) -> Asyncness {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        cx.asyncness(def_id).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            cx.asyncness(def_id).stable(tables, cx)
+        })
     }
 
     /// Retrieve the intrinsic definition if the item corresponds one.
     pub(crate) fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = item.internal(&mut *tables, cx.tcx);
-        cx.intrinsic(def_id).map(|_| IntrinsicDef(item))
+        self.with_cx(|tables, cx| {
+            let def_id = item.internal(tables, cx.tcx);
+            cx.intrinsic(def_id).map(|_| IntrinsicDef(item))
+        })
     }
 
     /// Retrieve the plain function name of an intrinsic.
     pub(crate) fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        cx.intrinsic_name(def_id)
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            cx.intrinsic_name(def_id)
+        })
     }
 
     /// Retrieve the closure signature for the given generic arguments.
     pub(crate) fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        cx.closure_sig(args_ref).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let args_ref = args.internal(tables, cx.tcx);
+            cx.closure_sig(args_ref).stable(tables, cx)
+        })
     }
 
     /// The number of variants in this ADT.
     pub(crate) fn adt_variants_len(&self, def: AdtDef) -> usize {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_variants_len(def.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| cx.adt_variants_len(def.internal(tables, cx.tcx)))
     }
 
     /// Discriminant for a given variant index of AdtDef.
     pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.adt_discr_for_variant(
-            adt.internal(&mut *tables, cx.tcx),
-            variant.internal(&mut *tables, cx.tcx),
-        )
-        .stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            cx.adt_discr_for_variant(adt.internal(tables, cx.tcx), variant.internal(tables, cx.tcx))
+                .stable(tables, cx)
+        })
     }
 
     /// Discriminant for a given variand index and args of a coroutine.
@@ -453,67 +446,57 @@ pub(crate) fn coroutine_discr_for_variant(
         args: &GenericArgs,
         variant: VariantIdx,
     ) -> Discr {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let tcx = cx.tcx;
-        let def = coroutine.def_id().internal(&mut *tables, tcx);
-        let args_ref = args.internal(&mut *tables, tcx);
-        cx.coroutine_discr_for_variant(def, args_ref, variant.internal(&mut *tables, tcx))
-            .stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let tcx = cx.tcx;
+            let def = coroutine.def_id().internal(tables, tcx);
+            let args_ref = args.internal(tables, tcx);
+            cx.coroutine_discr_for_variant(def, args_ref, variant.internal(tables, tcx))
+                .stable(tables, cx)
+        })
     }
 
     /// The name of a variant.
     pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.variant_name(def.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| cx.variant_name(def.internal(tables, cx.tcx)))
     }
 
     pub(crate) fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        def.internal(&mut *tables, cx.tcx)
-            .fields
-            .iter()
-            .map(|f| f.stable(&mut *tables, cx))
-            .collect()
+        self.with_cx(|tables, cx| {
+            def.internal(tables, cx.tcx).fields.iter().map(|f| f.stable(tables, cx)).collect()
+        })
     }
 
     /// Evaluate constant as a target usize.
     pub(crate) fn eval_target_usize(&self, mir_const: &MirConst) -> Result<u64, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let cnst = mir_const.internal(&mut *tables, cx.tcx);
-        cx.eval_target_usize(cnst)
+        self.with_cx(|tables, cx| {
+            let cnst = mir_const.internal(tables, cx.tcx);
+            cx.eval_target_usize(cnst)
+        })
     }
 
     pub(crate) fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result<u64, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let cnst = ty_const.internal(&mut *tables, cx.tcx);
-        cx.eval_target_usize_ty(cnst)
+        self.with_cx(|tables, cx| {
+            let cnst = ty_const.internal(tables, cx.tcx);
+            cx.eval_target_usize_ty(cnst)
+        })
     }
 
     /// Create a new zero-sized constant.
     pub(crate) fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let ty_internal = ty.internal(&mut *tables, cx.tcx);
-        cx.try_new_const_zst(ty_internal).map(|cnst| cnst.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let ty_internal = ty.internal(tables, cx.tcx);
+            cx.try_new_const_zst(ty_internal).map(|cnst| cnst.stable(tables, cx))
+        })
     }
 
     /// Create a new constant that represents the given string value.
     pub(crate) fn new_const_str(&self, value: &str) -> MirConst {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.new_const_str(value).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| cx.new_const_str(value).stable(tables, cx))
     }
 
     /// Create a new constant that represents the given boolean value.
     pub(crate) fn new_const_bool(&self, value: bool) -> MirConst {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.new_const_bool(value).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| cx.new_const_bool(value).stable(tables, cx))
     }
 
     /// Create a new constant that represents the given value.
@@ -522,10 +505,10 @@ pub(crate) fn try_new_const_uint(
         value: u128,
         uint_ty: UintTy,
     ) -> Result<MirConst, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx));
-        cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let ty = cx.ty_new_uint(uint_ty.internal(tables, cx.tcx));
+            cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(tables, cx))
+        })
     }
 
     pub(crate) fn try_new_ty_const_uint(
@@ -533,178 +516,170 @@ pub(crate) fn try_new_ty_const_uint(
         value: u128,
         uint_ty: UintTy,
     ) -> Result<TyConst, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx));
-        cx.try_new_ty_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let ty = cx.ty_new_uint(uint_ty.internal(tables, cx.tcx));
+            cx.try_new_ty_const_uint(value, ty).map(|cnst| cnst.stable(tables, cx))
+        })
     }
 
     /// Create a new type from the given kind.
     pub(crate) fn new_rigid_ty(&self, kind: RigidTy) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let internal_kind = kind.internal(&mut *tables, cx.tcx);
-        cx.new_rigid_ty(internal_kind).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let internal_kind = kind.internal(tables, cx.tcx);
+            cx.new_rigid_ty(internal_kind).stable(tables, cx)
+        })
     }
 
     /// Create a new box type, `Box<T>`, for the given inner type `T`.
     pub(crate) fn new_box_ty(&self, ty: Ty) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let inner = ty.internal(&mut *tables, cx.tcx);
-        cx.new_box_ty(inner).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let inner = ty.internal(tables, cx.tcx);
+            cx.new_box_ty(inner).stable(tables, cx)
+        })
     }
 
     /// Returns the type of given crate item.
     pub(crate) fn def_ty(&self, item: DefId) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let inner = item.internal(&mut *tables, cx.tcx);
-        cx.def_ty(inner).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let inner = item.internal(tables, cx.tcx);
+            cx.def_ty(inner).stable(tables, cx)
+        })
     }
 
     /// Returns the type of given definition instantiated with the given arguments.
     pub(crate) fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let inner = item.internal(&mut *tables, cx.tcx);
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        cx.def_ty_with_args(inner, args_ref).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let inner = item.internal(tables, cx.tcx);
+            let args_ref = args.internal(tables, cx.tcx);
+            cx.def_ty_with_args(inner, args_ref).stable(tables, cx)
+        })
     }
 
     /// Returns literal value of a const as a string.
     pub(crate) fn mir_const_pretty(&self, cnst: &MirConst) -> String {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cnst.internal(&mut *tables, cx.tcx).to_string()
+        self.with_cx(|tables, cx| cnst.internal(tables, cx.tcx).to_string())
     }
 
     /// `Span` of a `DefId`.
     pub(crate) fn span_of_a_def(&self, def_id: DefId) -> Span {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.span_of_a_def(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.span_of_a_def(did).stable(tables, cx)
+        })
     }
 
     pub(crate) fn ty_const_pretty(&self, ct: TyConstId) -> String {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.ty_const_pretty(tables.ty_consts[ct])
+        self.with_cx(|tables, cx| cx.ty_const_pretty(tables.ty_consts[ct]))
     }
 
     /// Obtain the representation of a type.
     pub(crate) fn ty_pretty(&self, ty: Ty) -> String {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.ty_pretty(tables.types[ty])
+        self.with_cx(|tables, cx| cx.ty_pretty(tables.types[ty]))
     }
 
     /// Obtain the kind of a type.
     pub(crate) fn ty_kind(&self, ty: Ty) -> TyKind {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.ty_kind(tables.types[ty]).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| cx.ty_kind(tables.types[ty]).stable(tables, cx))
     }
 
     /// Get the discriminant Ty for this Ty if there's one.
     pub(crate) fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let internal_kind = ty.internal(&mut *tables, cx.tcx);
-        cx.rigid_ty_discriminant_ty(internal_kind).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let internal_kind = ty.internal(tables, cx.tcx);
+            cx.rigid_ty_discriminant_ty(internal_kind).stable(tables, cx)
+        })
     }
 
     /// Get the body of an Instance which is already monomorphized.
     pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option<Body> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[instance];
-        cx.instance_body(instance).map(|body| body.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[instance];
+            cx.instance_body(instance).map(|body| body.stable(tables, cx))
+        })
     }
 
     /// Get the instance type with generic instantiations applied and lifetimes erased.
     pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[instance];
-        cx.instance_ty(instance).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[instance];
+            cx.instance_ty(instance).stable(tables, cx)
+        })
     }
 
     /// Get the instantiation types.
     pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[def];
-        cx.instance_args(instance).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[def];
+            cx.instance_args(instance).stable(tables, cx)
+        })
     }
 
     /// Get the instance.
     pub(crate) fn instance_def_id(&self, instance: InstanceDef) -> DefId {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[instance];
-        cx.instance_def_id(instance, &mut *tables)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[instance];
+            cx.instance_def_id(instance, tables)
+        })
     }
 
     /// Get the instance mangled name.
     pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[instance];
-        cx.instance_mangled_name(instance)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[instance];
+            cx.instance_mangled_name(instance)
+        })
     }
 
     /// Check if this is an empty DropGlue shim.
     pub(crate) fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[def];
-        cx.is_empty_drop_shim(instance)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[def];
+            cx.is_empty_drop_shim(instance)
+        })
     }
 
     /// Convert a non-generic crate item into an instance.
     /// This function will panic if the item is generic.
     pub(crate) fn mono_instance(&self, def_id: DefId) -> Instance {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.mono_instance(did).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.mono_instance(did).stable(tables, cx)
+        })
     }
 
     /// Item requires monomorphization.
     pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool {
-        let tables = self.tables.borrow();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.requires_monomorphization(did)
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.requires_monomorphization(did)
+        })
     }
 
     /// Resolve an instance from the given function definition and generic arguments.
     pub(crate) fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        cx.resolve_instance(def_id, args_ref).map(|inst| inst.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            let args_ref = args.internal(tables, cx.tcx);
+            cx.resolve_instance(def_id, args_ref).map(|inst| inst.stable(tables, cx))
+        })
     }
 
     /// Resolve an instance for drop_in_place for the given type.
     pub(crate) fn resolve_drop_in_place(&self, ty: Ty) -> Instance {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let internal_ty = ty.internal(&mut *tables, cx.tcx);
+        self.with_cx(|tables, cx| {
+            let internal_ty = ty.internal(tables, cx.tcx);
 
-        cx.resolve_drop_in_place(internal_ty).stable(&mut *tables, cx)
+            cx.resolve_drop_in_place(internal_ty).stable(tables, cx)
+        })
     }
 
     /// Resolve instance for a function pointer.
     pub(crate) fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        cx.resolve_for_fn_ptr(def_id, args_ref).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            let args_ref = args.internal(tables, cx.tcx);
+            cx.resolve_for_fn_ptr(def_id, args_ref).stable(tables, cx)
+        })
     }
 
     /// Resolve instance for a closure with the requested type.
@@ -714,21 +689,21 @@ pub(crate) fn resolve_closure(
         args: &GenericArgs,
         kind: ClosureKind,
     ) -> Option<Instance> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
-        let args_ref = args.internal(&mut *tables, cx.tcx);
-        let closure_kind = kind.internal(&mut *tables, cx.tcx);
-        cx.resolve_closure(def_id, args_ref, closure_kind).map(|inst| inst.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
+            let args_ref = args.internal(tables, cx.tcx);
+            let closure_kind = kind.internal(tables, cx.tcx);
+            cx.resolve_closure(def_id, args_ref, closure_kind).map(|inst| inst.stable(tables, cx))
+        })
     }
 
     /// Evaluate a static's initializer.
     pub(crate) fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx.tcx);
+        self.with_cx(|tables, cx| {
+            let def_id = def.0.internal(tables, cx.tcx);
 
-        cx.eval_static_initializer(def_id).stable(&mut *tables, cx)
+            cx.eval_static_initializer(def_id).stable(tables, cx)
+        })
     }
 
     /// Try to evaluate an instance into a constant.
@@ -737,142 +712,133 @@ pub(crate) fn eval_instance(
         def: InstanceDef,
         const_ty: Ty,
     ) -> Result<Allocation, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let instance = tables.instances[def];
-        let cx = &*self.cx.borrow();
-        let const_ty = const_ty.internal(&mut *tables, cx.tcx);
-        cx.eval_instance(instance)
-            .map(|const_val| alloc::try_new_allocation(const_ty, const_val, &mut *tables, cx))
-            .map_err(|e| e.stable(&mut *tables, cx))?
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[def];
+            let const_ty = const_ty.internal(tables, cx.tcx);
+            cx.eval_instance(instance)
+                .map(|const_val| alloc::try_new_allocation(const_ty, const_val, tables, cx))
+                .map_err(|e| e.stable(tables, cx))?
+        })
     }
 
     /// Retrieve global allocation for the given allocation ID.
     pub(crate) fn global_alloc(&self, id: AllocId) -> GlobalAlloc {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let alloc_id = id.internal(&mut *tables, cx.tcx);
-        cx.global_alloc(alloc_id).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let alloc_id = id.internal(tables, cx.tcx);
+            cx.global_alloc(alloc_id).stable(tables, cx)
+        })
     }
 
     /// Retrieve the id for the virtual table.
     pub(crate) fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> {
-        let mut tables = self.tables.borrow_mut();
-        let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else {
-            return None;
-        };
-        let cx = &*self.cx.borrow();
-        let ty = ty.internal(&mut *tables, cx.tcx);
-        let trait_ref = trait_ref.internal(&mut *tables, cx.tcx);
-        let alloc_id = cx.vtable_allocation(ty, trait_ref);
-        Some(alloc_id.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else {
+                return None;
+            };
+            let ty = ty.internal(tables, cx.tcx);
+            let trait_ref = trait_ref.internal(tables, cx.tcx);
+            let alloc_id = cx.vtable_allocation(ty, trait_ref);
+            Some(alloc_id.stable(tables, cx))
+        })
     }
 
     pub(crate) fn krate(&self, def_id: DefId) -> Crate {
-        let tables = self.tables.borrow();
-        let cx = &*self.cx.borrow();
-        smir_crate(cx, tables[def_id].krate)
+        self.with_cx(|tables, cx| smir_crate(cx, tables[def_id].krate))
     }
 
     pub(crate) fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
-        let tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[def];
-        cx.instance_name(instance, trimmed)
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[def];
+            cx.instance_name(instance, trimmed)
+        })
     }
 
     /// Return information about the target machine.
     pub(crate) fn target_info(&self) -> MachineInfo {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        MachineInfo {
-            endian: cx.target_endian().stable(&mut *tables, cx),
+        self.with_cx(|tables, cx| MachineInfo {
+            endian: cx.target_endian().stable(tables, cx),
             pointer_width: MachineSize::from_bits(cx.target_pointer_size()),
-        }
+        })
     }
 
     /// Get an instance ABI.
     pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let instance = tables.instances[def];
-        cx.instance_abi(instance).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let instance = tables.instances[def];
+            cx.instance_abi(instance).map(|fn_abi| fn_abi.stable(tables, cx))
+        })
     }
 
     /// Get the ABI of a function pointer.
     pub(crate) fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let sig = fn_ptr.internal(&mut *tables, cx.tcx);
-        cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let sig = fn_ptr.internal(tables, cx.tcx);
+            cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(tables, cx))
+        })
     }
 
     /// Get the layout of a type.
     pub(crate) fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let internal_ty = ty.internal(&mut *tables, cx.tcx);
-        cx.ty_layout(internal_ty).map(|layout| layout.stable(&mut *tables, cx))
+        self.with_cx(|tables, cx| {
+            let internal_ty = ty.internal(tables, cx.tcx);
+            cx.ty_layout(internal_ty).map(|layout| layout.stable(tables, cx))
+        })
     }
 
     /// Get the layout shape.
     pub(crate) fn layout_shape(&self, id: Layout) -> LayoutShape {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        id.internal(&mut *tables, cx.tcx).0.stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| id.internal(tables, cx.tcx).0.stable(tables, cx))
     }
 
     /// Get a debug string representation of a place.
     pub(crate) fn place_pretty(&self, place: &Place) -> String {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-
-        format!("{:?}", place.internal(&mut *tables, cx.tcx))
+        self.with_cx(|tables, cx| format!("{:?}", place.internal(tables, cx.tcx)))
     }
 
     /// Get the resulting type of binary operation.
     pub(crate) fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let rhs_internal = rhs.internal(&mut *tables, cx.tcx);
-        let lhs_internal = lhs.internal(&mut *tables, cx.tcx);
-        let bin_op_internal = bin_op.internal(&mut *tables, cx.tcx);
-        cx.binop_ty(bin_op_internal, rhs_internal, lhs_internal).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let rhs_internal = rhs.internal(tables, cx.tcx);
+            let lhs_internal = lhs.internal(tables, cx.tcx);
+            let bin_op_internal = bin_op.internal(tables, cx.tcx);
+            cx.binop_ty(bin_op_internal, rhs_internal, lhs_internal).stable(tables, cx)
+        })
     }
 
     /// Get the resulting type of unary operation.
     pub(crate) fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let un_op = un_op.internal(&mut *tables, cx.tcx);
-        let arg = arg.internal(&mut *tables, cx.tcx);
-        cx.unop_ty(un_op, arg).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            let un_op = un_op.internal(tables, cx.tcx);
+            let arg = arg.internal(tables, cx.tcx);
+            cx.unop_ty(un_op, arg).stable(tables, cx)
+        })
     }
 
     /// Get all associated items of a definition.
     pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        let did = tables[def_id];
-        cx.associated_items(did).iter().map(|assoc| assoc.stable(&mut *tables, cx)).collect()
+        self.with_cx(|tables, cx| {
+            let did = tables[def_id];
+            cx.associated_items(did).iter().map(|assoc| assoc.stable(tables, cx)).collect()
+        })
     }
 
     /// Get all vtable entries of a trait.
     pub(crate) fn vtable_entries(&self, trait_ref: &TraitRef) -> Vec<VtblEntry> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.vtable_entries(trait_ref.internal(&mut *tables, cx.tcx))
-            .iter()
-            .map(|v| v.stable(&mut *tables, cx))
-            .collect()
+        self.with_cx(|tables, cx| {
+            cx.vtable_entries(trait_ref.internal(tables, cx.tcx))
+                .iter()
+                .map(|v| v.stable(tables, cx))
+                .collect()
+        })
     }
 
     /// Returns the vtable entry at the given index.
     ///
     /// Returns `None` if the index is out of bounds.
     pub(crate) fn vtable_entry(&self, trait_ref: &TraitRef, idx: usize) -> Option<VtblEntry> {
-        let mut tables = self.tables.borrow_mut();
-        let cx = &*self.cx.borrow();
-        cx.vtable_entry(trait_ref.internal(&mut *tables, cx.tcx), idx).stable(&mut *tables, cx)
+        self.with_cx(|tables, cx| {
+            cx.vtable_entry(trait_ref.internal(tables, cx.tcx), idx).stable(tables, cx)
+        })
     }
 }
 
diff --git a/compiler/rustc_public/src/unstable/convert/mod.rs b/compiler/rustc_public/src/unstable/convert/mod.rs
index f204066..1ec0b9a 100644
--- a/compiler/rustc_public/src/unstable/convert/mod.rs
+++ b/compiler/rustc_public/src/unstable/convert/mod.rs
@@ -6,7 +6,7 @@
 //! For contributors, please make sure to avoid calling rustc's internal functions and queries.
 //! These should be done via `rustc_public_bridge` APIs, but it's possible to access ADT fields directly.
 
-use std::ops::RangeInclusive;
+use std::{ops, range};
 
 use rustc_public_bridge::Tables;
 use rustc_public_bridge::context::CompilerCtxt;
@@ -95,16 +95,16 @@ fn stable<'cx>(
     }
 }
 
-impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
+impl<'tcx, T> Stable<'tcx> for range::RangeInclusive<T>
 where
     T: Stable<'tcx>,
 {
-    type T = RangeInclusive<T::T>;
+    type T = ops::RangeInclusive<T::T>;
     fn stable<'cx>(
         &self,
         tables: &mut Tables<'cx, BridgeTys>,
         cx: &CompilerCtxt<'cx, BridgeTys>,
     ) -> Self::T {
-        RangeInclusive::new(self.start().stable(tables, cx), self.end().stable(tables, cx))
+        ops::RangeInclusive::new(self.start.stable(tables, cx), self.last.stable(tables, cx))
     }
 }
diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs
index 7e76d5a..d126304 100644
--- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs
+++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs
@@ -726,18 +726,13 @@ fn stable<'cx>(
             mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
             mir::TerminatorKind::Return => TerminatorKind::Return,
             mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
-            mir::TerminatorKind::Drop {
-                place,
-                target,
-                unwind,
-                replace: _,
-                drop: _,
-                async_fut: _,
-            } => TerminatorKind::Drop {
-                place: place.stable(tables, cx),
-                target: target.as_usize(),
-                unwind: unwind.stable(tables, cx),
-            },
+            mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop: _ } => {
+                TerminatorKind::Drop {
+                    place: place.stable(tables, cx),
+                    target: target.as_usize(),
+                    unwind: unwind.stable(tables, cx),
+                }
+            }
             mir::TerminatorKind::Call {
                 func,
                 args,
diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs
index c4f1da1..925d4a5 100644
--- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs
+++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs
@@ -541,7 +541,7 @@ fn stable<'cx>(
             }
             ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)),
             ty::ConstKind::Unevaluated(uv) => crate::ty::TyConstKind::Unevaluated(
-                tables.const_def(uv.def),
+                tables.const_def(uv.kind.def_id()),
                 uv.args.stable(tables, cx),
             ),
             ty::ConstKind::Error(_) => unreachable!(),
diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs
index b614bc1..2f48583 100644
--- a/compiler/rustc_query_impl/src/execution.rs
+++ b/compiler/rustc_query_impl/src/execution.rs
@@ -498,7 +498,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
     debug_assert!(dep_graph_data.is_index_green(prev_index));
 
     // First try to load the result from the on-disk cache. Some things are never cached on disk.
-    let try_value = if (query.will_cache_on_disk_for_key_fn)(key) {
+    let try_value = if query.will_cache_on_disk_for_key(key) {
         let prof_timer = tcx.prof.incr_cache_loading();
         let value = (query.try_load_from_disk_fn)(tcx, prev_index);
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -603,7 +603,7 @@ fn ensure_can_skip_execution<'tcx, C: QueryCache>(
                 // needed, which guarantees the query provider will never run
                 // for this key.
                 EnsureMode::Done => {
-                    (query.will_cache_on_disk_for_key_fn)(key)
+                    query.will_cache_on_disk_for_key(key)
                         && loadable_from_disk(tcx, serialized_dep_node_index)
                 }
             }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 11f9605..3d93bea 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -93,7 +93,7 @@ fn encode_query_values_inner<'a, 'tcx, C, V>(
 
     assert!(all_inactive(&query.state));
     query.cache.for_each(&mut |key, value, dep_node| {
-        if (query.will_cache_on_disk_for_key_fn)(*key) {
+        if query.will_cache_on_disk_for_key(*key) {
             encoder.encode_query_value::<V>(dep_node, &erase::restore_val::<V>(*value));
         }
     });
@@ -152,7 +152,7 @@ pub(crate) fn promote_from_disk_inner<'tcx, C: QueryCache>(
 
     // If the recovered key isn't eligible for cache-on-disk, then there's no
     // value on disk to promote.
-    if !(query.will_cache_on_disk_for_key_fn)(key) {
+    if !query.will_cache_on_disk_for_key(key) {
         return;
     }
 
diff --git a/compiler/rustc_query_impl/src/query_impl.rs b/compiler/rustc_query_impl/src/query_impl.rs
index 4425acc..3720d9f 100644
--- a/compiler/rustc_query_impl/src/query_impl.rs
+++ b/compiler/rustc_query_impl/src/query_impl.rs
@@ -1,6 +1,6 @@
 use rustc_middle::queries::TaggedQueryKey;
 use rustc_middle::query::erase::{self, Erased};
-use rustc_middle::query::{AsLocalQueryKey, QueryMode, QueryVTable};
+use rustc_middle::query::{QueryKey, QueryMode, QueryVTable};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
@@ -127,20 +127,6 @@ pub(crate) fn __rust_begin_short_backtrace<'tcx>(
                     }
                 }
 
-                fn will_cache_on_disk_for_key<'tcx>(
-                    _key: rustc_middle::queries::$name::Key<'tcx>,
-                ) -> bool {
-                    cfg_select! {
-                        // If a query has both `cache_on_disk` and `separate_provide_extern`, only
-                        // disk-cache values for "local" keys, i.e. things in the current crate.
-                        all($cache_on_disk, $separate_provide_extern) => {
-                            AsLocalQueryKey::as_local_key(&_key).is_some()
-                        }
-                        all($cache_on_disk, not($separate_provide_extern)) => true,
-                        not($cache_on_disk) => false,
-                    }
-                }
-
                 pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
                     -> QueryVTable<'tcx, rustc_middle::queries::$name::Cache<'tcx>>
                 {
@@ -153,12 +139,11 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
                         dep_kind: rustc_middle::dep_graph::DepKind::$name,
                         state: Default::default(),
                         cache: Default::default(),
+                        cache_on_disk_local: $cache_on_disk,
+                        separate_provide_extern: $separate_provide_extern,
 
                         invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace,
 
-                        will_cache_on_disk_for_key_fn:
-                            $crate::query_impl::$name::will_cache_on_disk_for_key,
-
                         #[cfg($cache_on_disk)]
                         try_load_from_disk_fn: |tcx, prev_index| {
                             use rustc_middle::queries::$name::{ProvidedValue, provided_to_erased};
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 43443e0..4fd9894 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -52,7 +52,7 @@ pub(crate) fn plant_decl_into_local_module(
         decl: Decl<'ra>,
     ) {
         if let Err(old_decl) =
-            self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl, false)
+            self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl)
         {
             self.report_conflict(ident, ns, old_decl, decl);
         }
@@ -87,13 +87,11 @@ fn define_extern(
         vis: Visibility<DefId>,
         span: Span,
         expansion: LocalExpnId,
-        ambiguity: Option<Decl<'ra>>,
+        ambiguity: Option<(Decl<'ra>, bool)>,
     ) {
         let decl = self.arenas.alloc_decl(DeclData {
             kind: DeclKind::Def(res),
             ambiguity: CmCell::new(ambiguity),
-            // External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
-            warn_ambiguity: CmCell::new(true),
             initial_vis: vis,
             ambiguity_vis_max: CmCell::new(None),
             ambiguity_vis_min: CmCell::new(None),
@@ -392,7 +390,8 @@ fn build_reduced_graph_for_external_crate_res(
             let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child;
             let span = child_span(self, reexport_chain, res);
             let res = res.expect_non_local();
-            self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module()))
+            // External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
+            (self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module())), true)
         });
 
         // Record primary definitions.
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 84221cb..dc17aaa 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -438,7 +438,10 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
                             && !tcx.is_panic_runtime(cnum)
                             && !tcx.has_global_allocator(cnum)
                             && !tcx.has_panic_handler(cnum)
-                            && tcx.externally_implementable_items(cnum).is_empty()
+                            && tcx
+                                .externally_implementable_items(cnum)
+                                .values()
+                                .all(|(_, defs)| defs.is_empty())
                     }) {
                         maybe_unused_extern_crates.insert(id, import.span);
                     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 85e8d67..d75ae85 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1188,7 +1188,7 @@ pub(crate) fn report_vis_error(
         .emit()
     }
 
-    fn def_path_str(&self, mut def_id: DefId) -> String {
+    pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
         // We can't use `def_path_str` in resolve.
         let mut path = vec![def_id];
         while let Some(parent) = self.tcx.opt_parent(def_id) {
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 44f14fa..e20c86d 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -278,9 +278,8 @@ fn update_reachability_from_macro(
         // all the parents in the loop below are also guaranteed to be modules.
         let mut module_def_id = macro_module_def_id;
         loop {
-            let changed_reachability =
-                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
-            if changed_reachability || module_def_id == CRATE_DEF_ID {
+            self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
+            if module_def_id == CRATE_DEF_ID {
                 break;
             }
             module_def_id = self.r.tcx.local_parent(module_def_id);
@@ -294,7 +293,7 @@ fn update_macro_reachable(
         module_def_id: LocalDefId,
         defining_mod: LocalDefId,
         macro_ev: EffectiveVisibility,
-    ) -> bool {
+    ) {
         if self.macro_reachable.insert((module_def_id, defining_mod)) {
             let module = self.r.expect_module(module_def_id.to_def_id());
             for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
@@ -311,9 +310,6 @@ fn update_macro_reachable(
                     self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
                 }
             }
-            true
-        } else {
-            false
         }
     }
 
@@ -334,11 +330,7 @@ fn update_macro_reachable_def(
                 }
             }
             DefKind::Struct | DefKind::Union => {
-                self.r
-                    .macro_reachable_adts
-                    .entry(def_id)
-                    .or_insert_with(Default::default)
-                    .insert(module);
+                self.r.macro_reachable_adts.entry(def_id).or_default().insert(module);
             }
             _ => {}
         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index c49e0fc..c957997 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -382,11 +382,9 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
         assert_eq!(d1.span, d2.span);
         if d1.ambiguity.get() != d2.ambiguity.get() {
             assert!(d1.ambiguity.get().is_some());
-            assert!(d2.ambiguity.get().is_none());
         }
         // Visibility of the new import declaration may be different,
         // because it already incorporates the visibility of the source binding.
-        // `warn_ambiguity` of a re-fetched glob can also change in both directions.
         remove_same_import(d1_next, d2_next)
     } else {
         (d1, d2)
@@ -450,7 +448,6 @@ pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> De
         self.arenas.alloc_decl(DeclData {
             kind: DeclKind::Import { source_decl: decl, import },
             ambiguity: CmCell::new(None),
-            warn_ambiguity: CmCell::new(false),
             span: import.span,
             initial_vis: vis.to_def_id(),
             ambiguity_vis_max: CmCell::new(None),
@@ -460,14 +457,85 @@ pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> De
         })
     }
 
+    fn is_noise_0_7_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
+        let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
+        let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
+        let [seg1, seg2] = &i1.module_path[..] else { return false };
+        if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin_surflet" {
+            return false;
+        }
+        let [seg1, seg2] = &i2.module_path[..] else { return false };
+        if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin" {
+            return false;
+        }
+        let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
+        let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
+        self.def_path_str(def_id1).ends_with("noise_fns::generators::perlin_surflet::Perlin")
+            && self.def_path_str(def_id2).ends_with("noise_fns::generators::perlin::Perlin")
+    }
+
+    fn is_rustybuzz_0_4_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
+        let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
+        let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
+        let [seg1, seg2] = &i1.module_path[..] else { return false };
+        if seg1.ident.name != kw::Super || seg2.ident.name.as_str() != "gsubgpos" {
+            return false;
+        }
+        let [seg1] = &i2.module_path[..] else { return false };
+        if seg1.ident.name != kw::Super {
+            return false;
+        }
+        let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
+        let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
+        self.def_path_str(def_id1).ends_with("tables::gsubgpos::Class")
+            && self.def_path_str(def_id2).ends_with("ggg::Class")
+    }
+
+    fn is_pdf_0_9_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
+        let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
+        let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
+        let [seg1, seg2] = &i1.module_path[..] else { return false };
+        if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "content" {
+            return false;
+        }
+        let [seg1, seg2] = &i2.module_path[..] else { return false };
+        if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "object" {
+            return false;
+        }
+        let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
+        let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
+        self.def_path_str(def_id1).ends_with("crate::content::Rect")
+            && self.def_path_str(def_id2).ends_with("crate::object::types::Rect")
+    }
+
+    fn is_net2_0_2_39(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
+        let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
+        let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
+        let [seg1, seg2, seg3, seg4] = &i1.module_path[..] else { return false };
+        if seg1.ident.name != kw::PathRoot
+            || seg2.ident.name.as_str() != "winapi"
+            || seg3.ident.name.as_str() != "shared"
+            || seg4.ident.name.as_str() != "ws2def"
+        {
+            return false;
+        }
+        let [seg1, seg2, seg3, seg4] = &i2.module_path[..] else { return false };
+        if seg1.ident.name != kw::PathRoot
+            || seg2.ident.name.as_str() != "winapi"
+            || seg3.ident.name.as_str() != "um"
+            || seg4.ident.name.as_str() != "winsock2"
+        {
+            return false;
+        }
+        let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
+        let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
+        self.def_path_str(def_id1).starts_with("winapi::shared::ws2def::")
+            && self.def_path_str(def_id2).starts_with("winapi::um::winsock2::")
+    }
+
     /// If `glob_decl` attempts to overwrite `old_glob_decl` in a module,
     /// decide which one to keep.
-    fn select_glob_decl(
-        &self,
-        old_glob_decl: Decl<'ra>,
-        glob_decl: Decl<'ra>,
-        warn_ambiguity: bool,
-    ) -> Decl<'ra> {
+    fn select_glob_decl(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> Decl<'ra> {
         assert!(glob_decl.is_glob_import());
         assert!(old_glob_decl.is_glob_import());
         assert_ne!(glob_decl, old_glob_decl);
@@ -476,9 +544,6 @@ fn select_glob_decl(
         // all these overwrites will be re-fetched by glob imports importing
         // from that module without generating new ambiguities.
         // - A glob decl is overwritten by a non-glob decl arriving later.
-        // - A glob decl is overwritten by its clone after setting ambiguity in it.
-        //   FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch
-        //   with the same decl in some way.
         // - A glob decl is overwritten by a glob decl re-fetching an
         //   overwritten decl from other module (the recursive case).
         // Here we are detecting all such re-fetches and overwrite old decls
@@ -489,29 +554,21 @@ fn select_glob_decl(
         if deep_decl != glob_decl {
             // Some import layers have been removed, need to overwrite.
             assert_ne!(old_deep_decl, old_glob_decl);
-            // FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
-            // assert_ne!(old_deep_decl, deep_decl);
-            // assert!(old_deep_decl.is_glob_import());
             assert!(!deep_decl.is_glob_import());
-            if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
+            if let Some((old_ambig, _)) = old_glob_decl.ambiguity.get()
+                && glob_decl.ambiguity.get().is_none()
+            {
                 // Do not lose glob ambiguities when re-fetching the glob.
-                glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
-            }
-            if glob_decl.is_ambiguity_recursive() {
-                glob_decl.warn_ambiguity.set_unchecked(true);
+                glob_decl.ambiguity.set_unchecked(Some((old_ambig, true)));
             }
             glob_decl
         } else if glob_decl.res() != old_glob_decl.res() {
-            old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
-            old_glob_decl.warn_ambiguity.set_unchecked(warn_ambiguity);
-            if warn_ambiguity {
-                old_glob_decl
-            } else {
-                // Need a fresh decl so other glob imports importing it could re-fetch it
-                // and set their own `warn_ambiguity` to true.
-                // FIXME: remove this when `warn_ambiguity` is removed (#149195).
-                self.arenas.alloc_decl((*old_glob_decl).clone())
-            }
+            let warning = self.is_noise_0_7_0(old_glob_decl, glob_decl)
+                || self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl)
+                || self.is_pdf_0_9_0(old_glob_decl, glob_decl)
+                || self.is_net2_0_2_39(old_glob_decl, glob_decl);
+            old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, warning)));
+            old_glob_decl
         } else if let old_vis = old_glob_decl.vis()
             && let vis = glob_decl.vis()
             && old_vis != vis
@@ -529,8 +586,7 @@ fn select_glob_decl(
             old_glob_decl
         } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {
             // Overwriting a non-ambiguous glob import with an ambiguous glob import.
-            old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
-            old_glob_decl.warn_ambiguity.set_unchecked(true);
+            old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, true)));
             old_glob_decl
         } else {
             old_glob_decl
@@ -545,9 +601,7 @@ pub(crate) fn try_plant_decl_into_local_module(
         orig_ident_span: Span,
         ns: Namespace,
         decl: Decl<'ra>,
-        warn_ambiguity: bool,
     ) -> Result<(), Decl<'ra>> {
-        assert!(!decl.warn_ambiguity.get());
         assert!(decl.ambiguity.get().is_none());
         assert!(decl.ambiguity_vis_max.get().is_none());
         assert!(decl.ambiguity_vis_min.get().is_none());
@@ -562,31 +616,21 @@ pub(crate) fn try_plant_decl_into_local_module(
             module.underscore_disambiguator.update_unchecked(|d| d + 1);
             module.underscore_disambiguator.get()
         });
-        self.update_local_resolution(
-            module,
-            key,
-            orig_ident_span,
-            warn_ambiguity,
-            |this, resolution| {
-                if decl.is_glob_import() {
-                    resolution.glob_decl = Some(match resolution.glob_decl {
-                        Some(old_decl) => this.select_glob_decl(
-                            old_decl,
-                            decl,
-                            warn_ambiguity && resolution.non_glob_decl.is_none(),
-                        ),
-                        None => decl,
-                    })
-                } else {
-                    resolution.non_glob_decl = Some(match resolution.non_glob_decl {
-                        Some(old_decl) => return Err(old_decl),
-                        None => decl,
-                    })
-                }
+        self.update_local_resolution(module, key, orig_ident_span, |this, resolution| {
+            if decl.is_glob_import() {
+                resolution.glob_decl = Some(match resolution.glob_decl {
+                    Some(old_decl) => this.select_glob_decl(old_decl, decl),
+                    None => decl,
+                });
+            } else {
+                resolution.non_glob_decl = Some(match resolution.non_glob_decl {
+                    Some(old_decl) => return Err(old_decl),
+                    None => decl,
+                })
+            }
 
-                Ok(())
-            },
-        )
+            Ok(())
+        })
     }
 
     // Use `f` to mutate the resolution of the name in the module.
@@ -596,7 +640,6 @@ fn update_local_resolution<T, F>(
         module: LocalModule<'ra>,
         key: BindingKey,
         orig_ident_span: Span,
-        warn_ambiguity: bool,
         f: F,
     ) -> T
     where
@@ -604,7 +647,7 @@ fn update_local_resolution<T, F>(
     {
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
         // during which the resolution might end up getting re-defined via a glob cycle.
-        let (binding, t, warn_ambiguity) = {
+        let (binding, t) = {
             let resolution = &mut *self
                 .resolution_or_default(module.to_module(), key, orig_ident_span)
                 .borrow_mut_unchecked();
@@ -616,7 +659,7 @@ fn update_local_resolution<T, F>(
             if let Some(binding) = resolution.determined_decl()
                 && (old_decl != Some(binding) || old_vis != Some(binding.vis()))
             {
-                (binding, t, warn_ambiguity || old_decl.is_some())
+                (binding, t)
             } else {
                 return t;
             }
@@ -639,14 +682,8 @@ fn update_local_resolution<T, F>(
             };
             if self.is_accessible_from(binding.vis(), scope) {
                 let import_decl = self.new_import_decl(binding, *import);
-                self.try_plant_decl_into_local_module(
-                    ident,
-                    orig_ident_span,
-                    key.ns,
-                    import_decl,
-                    warn_ambiguity,
-                )
-                .expect("planting a glob cannot fail");
+                self.try_plant_decl_into_local_module(ident, orig_ident_span, key.ns, import_decl)
+                    .expect("planting a glob cannot fail");
             }
         }
 
@@ -665,13 +702,7 @@ fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool)
             self.per_ns(|this, ns| {
                 let ident = IdentKey::new(target);
                 // This can fail, dummies are inserted only in non-occupied slots.
-                let _ = this.try_plant_decl_into_local_module(
-                    ident,
-                    target.span,
-                    ns,
-                    dummy_decl,
-                    false,
-                );
+                let _ = this.try_plant_decl_into_local_module(ident, target.span, ns, dummy_decl);
                 // Don't remove underscores from `single_imports`, they were never added.
                 if target.name != kw::Underscore {
                     let key = BindingKey::new(ident, ns);
@@ -679,7 +710,6 @@ fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool)
                         import.parent_scope.module.expect_local(),
                         key,
                         target.span,
-                        false,
                         |_, resolution| {
                             resolution.single_imports.swap_remove(&import);
                         },
@@ -846,7 +876,7 @@ pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra
                 }
 
                 if let DeclKind::Import { import, .. } = binding.kind
-                    && let Some(amb_binding) = binding.ambiguity.get()
+                    && let Some((amb_binding, _)) = binding.ambiguity.get()
                     && binding.res() != Res::Err
                     && exported_ambiguities.contains(&binding)
                 {
@@ -1134,7 +1164,6 @@ fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>)
                             parent.expect_local(),
                             key,
                             target.span,
-                            false,
                             |_, resolution| {
                                 resolution.single_imports.swap_remove(&import);
                             },
@@ -1820,16 +1849,11 @@ fn resolve_glob_import(&mut self, import: Import<'ra>) {
                 };
             if self.is_accessible_from(binding.vis(), scope) {
                 let import_decl = self.new_import_decl(binding, import);
-                let warn_ambiguity = self
-                    .resolution(import.parent_scope.module, key)
-                    .and_then(|r| r.determined_decl())
-                    .is_some_and(|binding| binding.warn_ambiguity_recursive());
                 self.try_plant_decl_into_local_module(
                     key.ident,
                     orig_ident_span,
                     key.ns,
                     import_decl,
-                    warn_ambiguity,
                 )
                 .expect("planting a glob cannot fail");
             }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fb8de90..58899ff 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -27,7 +27,7 @@
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
-use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
+use rustc_hir::{MissingLifetimeKind, PrimTy};
 use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility};
 use rustc_middle::{bug, span_bug};
@@ -781,8 +781,7 @@ pub(crate) struct DiagMetadata<'ast> {
 
     /// Accumulate the errors due to missed lifetime elision,
     /// and report them all at once for each function.
-    current_elision_failures:
-        Vec<(MissingLifetime, LifetimeElisionCandidate, Either<NodeId, Range<NodeId>>)>,
+    current_elision_failures: Vec<(MissingLifetime, Either<NodeId, Range<NodeId>>)>,
 }
 
 struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
@@ -1749,10 +1748,10 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
         let ident = lifetime.ident;
 
         if ident.name == kw::StaticLifetime {
-            self.record_lifetime_res(
+            self.record_lifetime_use(
                 lifetime.id,
                 LifetimeRes::Static,
-                LifetimeElisionCandidate::Named,
+                LifetimeElisionCandidate::Ignore,
             );
             return;
         }
@@ -1765,7 +1764,7 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
         while let Some(rib) = lifetime_rib_iter.next() {
             let normalized_ident = ident.normalize_to_macros_2_0();
             if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
-                self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
+                self.record_lifetime_use(lifetime.id, res, LifetimeElisionCandidate::Ignore);
 
                 if let LifetimeRes::Param { param, binder } = res {
                     match self.lifetime_uses.entry(param) {
@@ -1831,20 +1830,12 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
                 LifetimeRibKind::Item => break,
                 LifetimeRibKind::ConstParamTy => {
                     let guar = self.emit_non_static_lt_in_const_param_ty_error(lifetime);
-                    self.record_lifetime_res(
-                        lifetime.id,
-                        LifetimeRes::Error(guar),
-                        LifetimeElisionCandidate::Ignore,
-                    );
+                    self.record_lifetime_err(lifetime.id, guar);
                     return;
                 }
                 LifetimeRibKind::ConcreteAnonConst(cause) => {
                     let guar = self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
-                    self.record_lifetime_res(
-                        lifetime.id,
-                        LifetimeRes::Error(guar),
-                        LifetimeElisionCandidate::Ignore,
-                    );
+                    self.record_lifetime_err(lifetime.id, guar);
                     return;
                 }
                 LifetimeRibKind::AnonymousCreateParameter { .. }
@@ -1862,11 +1853,7 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
             .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer));
 
         let guar = self.emit_undeclared_lifetime_error(lifetime, outer_res);
-        self.record_lifetime_res(
-            lifetime.id,
-            LifetimeRes::Error(guar),
-            LifetimeElisionCandidate::Named,
-        );
+        self.record_lifetime_err(lifetime.id, guar);
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1893,7 +1880,7 @@ fn resolve_anonymous_lifetime(
             match rib.kind {
                 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
                     let res = self.create_fresh_lifetime(lifetime.ident, binder, kind);
-                    self.record_lifetime_res(lifetime.id, res, elision_candidate);
+                    self.record_lifetime_use(lifetime.id, res, elision_candidate);
                     return;
                 }
                 LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
@@ -1911,7 +1898,7 @@ fn resolve_anonymous_lifetime(
                         }
                     }
                     if lifetimes_in_scope.is_empty() {
-                        self.record_lifetime_res(
+                        self.record_lifetime_use(
                             lifetime.id,
                             LifetimeRes::Static,
                             elision_candidate,
@@ -2015,23 +2002,17 @@ fn resolve_anonymous_lifetime(
                             span: lifetime.ident.span,
                         })
                     };
-                    self.record_lifetime_res(
-                        lifetime.id,
-                        LifetimeRes::Error(guar),
-                        elision_candidate,
-                    );
+                    self.record_lifetime_err(lifetime.id, guar);
                     return;
                 }
                 LifetimeRibKind::Elided(res) => {
-                    self.record_lifetime_res(lifetime.id, res, elision_candidate);
+                    self.record_lifetime_use(lifetime.id, res, elision_candidate);
                     return;
                 }
                 LifetimeRibKind::ElisionFailure => {
-                    self.diag_metadata.current_elision_failures.push((
-                        missing_lifetime,
-                        elision_candidate,
-                        Either::Left(lifetime.id),
-                    ));
+                    self.diag_metadata
+                        .current_elision_failures
+                        .push((missing_lifetime, Either::Left(lifetime.id)));
                     return;
                 }
                 LifetimeRibKind::Item => break,
@@ -2045,7 +2026,7 @@ fn resolve_anonymous_lifetime(
             }
         }
         let guar = self.report_missing_lifetime_specifiers([&missing_lifetime], None);
-        self.record_lifetime_res(lifetime.id, LifetimeRes::Error(guar), elision_candidate);
+        self.record_lifetime_err(lifetime.id, guar);
     }
 
     fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) {
@@ -2142,7 +2123,7 @@ fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
         let id = self.r.next_node_id();
         let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
 
-        self.record_lifetime_res(
+        self.record_lifetime_use(
             anchor_id,
             LifetimeRes::ElidedAnchor { start: id, end: id + 1 },
             LifetimeElisionCandidate::Ignore,
@@ -2162,15 +2143,15 @@ fn create_fresh_lifetime(
 
         // Leave the responsibility to create the `LocalDefId` to lowering.
         let param = self.r.next_node_id();
-        let res = LifetimeRes::Fresh { param, binder, kind };
-        self.record_lifetime_param(param, res);
+        let res = LifetimeRes::Fresh { param, kind };
+        self.record_lifetime_def(param, res);
 
         // Record the created lifetime parameter so lowering can pick it up and add it to HIR.
         self.r
             .extra_lifetime_params_map
             .entry(binder)
             .or_insert_with(Vec::new)
-            .push((ident, param, res));
+            .push((ident, param, kind));
         res
     }
 
@@ -2226,7 +2207,7 @@ fn resolve_elided_lifetimes_in_path(
             }
 
             let node_ids = self.r.next_node_ids(expected_lifetimes);
-            self.record_lifetime_res(
+            self.record_lifetime_use(
                 segment_id,
                 LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
                 LifetimeElisionCandidate::Ignore,
@@ -2252,10 +2233,10 @@ fn resolve_elided_lifetimes_in_path(
                 // Do not create a parameter for patterns and expressions: type checking can infer
                 // the appropriate lifetime for us.
                 for id in node_ids {
-                    self.record_lifetime_res(
+                    self.record_lifetime_use(
                         id,
                         LifetimeRes::Infer,
-                        LifetimeElisionCandidate::Named,
+                        LifetimeElisionCandidate::Ignore,
                     );
                 }
                 continue;
@@ -2311,11 +2292,7 @@ fn resolve_elided_lifetimes_in_path(
                         should_lint = false;
 
                         for id in node_ids {
-                            self.record_lifetime_res(
-                                id,
-                                LifetimeRes::Error(guar),
-                                LifetimeElisionCandidate::Named,
-                            );
+                            self.record_lifetime_err(id, guar);
                         }
                         break;
                     }
@@ -2325,10 +2302,10 @@ fn resolve_elided_lifetimes_in_path(
                         let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
                         for id in node_ids {
                             let res = self.create_fresh_lifetime(ident, binder, kind);
-                            self.record_lifetime_res(
+                            self.record_lifetime_use(
                                 id,
                                 res,
-                                replace(&mut candidate, LifetimeElisionCandidate::Named),
+                                replace(&mut candidate, LifetimeElisionCandidate::Ignore),
                             );
                         }
                         break;
@@ -2336,7 +2313,7 @@ fn resolve_elided_lifetimes_in_path(
                     LifetimeRibKind::Elided(res) => {
                         let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
                         for id in node_ids {
-                            self.record_lifetime_res(
+                            self.record_lifetime_use(
                                 id,
                                 res,
                                 replace(&mut candidate, LifetimeElisionCandidate::Ignore),
@@ -2345,11 +2322,9 @@ fn resolve_elided_lifetimes_in_path(
                         break;
                     }
                     LifetimeRibKind::ElisionFailure => {
-                        self.diag_metadata.current_elision_failures.push((
-                            missing_lifetime,
-                            LifetimeElisionCandidate::Ignore,
-                            Either::Right(node_ids),
-                        ));
+                        self.diag_metadata
+                            .current_elision_failures
+                            .push((missing_lifetime, Either::Right(node_ids)));
                         break;
                     }
                     // `LifetimeRes::Error`, which would usually be used in the case of
@@ -2360,11 +2335,7 @@ fn resolve_elided_lifetimes_in_path(
                         let guar =
                             self.report_missing_lifetime_specifiers([&missing_lifetime], None);
                         for id in node_ids {
-                            self.record_lifetime_res(
-                                id,
-                                LifetimeRes::Error(guar),
-                                LifetimeElisionCandidate::Ignore,
-                            );
+                            self.record_lifetime_err(id, guar);
                         }
                         break;
                     }
@@ -2405,16 +2376,15 @@ fn resolve_elided_lifetimes_in_path(
         }
     }
 
+    /// Register a use of an already defined lifetime.
     #[instrument(level = "debug", skip(self))]
-    fn record_lifetime_res(
+    fn record_lifetime_use(
         &mut self,
         id: NodeId,
         res: LifetimeRes,
         candidate: LifetimeElisionCandidate,
     ) {
-        if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
-            panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
-        }
+        self.record_lifetime_def(id, res);
 
         match res {
             LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
@@ -2426,9 +2396,17 @@ fn record_lifetime_res(
         }
     }
 
+    /// Can be used for both definitions and uses of lifetimes, as an error
+    /// has already been reported.
     #[instrument(level = "debug", skip(self))]
-    fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
-        if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
+    fn record_lifetime_err(&mut self, id: NodeId, guar: ErrorGuaranteed) {
+        self.record_lifetime_def(id, LifetimeRes::Error(guar));
+    }
+
+    /// Define a new lifetime (e.g. in generics)
+    #[instrument(level = "debug", skip(self))]
+    fn record_lifetime_def(&mut self, id: NodeId, res: LifetimeRes) {
+        if let Some(prev_res) = self.r.current_owner.lifetimes_res_map.insert(id, res) {
             panic!(
                 "lifetime parameter {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)"
             )
@@ -2456,7 +2434,9 @@ fn resolve_fn_signature(
 
             let outer_failures = take(&mut this.diag_metadata.current_elision_failures);
             let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
-                this.r.lifetime_elision_allowed.insert(fn_id);
+                if fn_id == this.r.current_owner.id {
+                    this.r.current_owner.lifetime_elision_allowed = true;
+                }
                 LifetimeRibKind::Elided(*res)
             } else {
                 LifetimeRibKind::ElisionFailure
@@ -2470,15 +2450,13 @@ fn resolve_fn_signature(
                     elision_failures.iter().map(|(missing_lifetime, ..)| missing_lifetime),
                     Some(failure_info),
                 );
-                let mut record_res = |lifetime, candidate| {
-                    this.record_lifetime_res(lifetime, LifetimeRes::Error(guar), candidate)
-                };
-                for (_, candidate, nodes) in elision_failures {
+                let mut record_res = |lifetime| this.record_lifetime_err(lifetime, guar);
+                for (_, nodes) in elision_failures {
                     match nodes {
-                        Either::Left(node_id) => record_res(node_id, candidate),
+                        Either::Left(node_id) => record_res(node_id),
                         Either::Right(node_ids) => {
                             for lifetime in node_ids {
-                                record_res(lifetime, candidate)
+                                record_res(lifetime)
                             }
                         }
                     }
@@ -2553,9 +2531,7 @@ enum Elision {
                     });
                     all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| {
                         match candidate {
-                            LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {
-                                None
-                            }
+                            LifetimeElisionCandidate::Ignore => None,
                             LifetimeElisionCandidate::Missing(missing) => Some(missing),
                         }
                     }));
@@ -2635,11 +2611,11 @@ fn visit_ty(&mut self, ty: &'ra Ty) {
                         let lt_id = if let Some(lt) = lt {
                             lt.id
                         } else {
-                            let res = self.r.lifetimes_res_map[&ty.id];
+                            let res = self.r.current_owner.lifetimes_res_map[&ty.id];
                             let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
                             start
                         };
-                        let lt_res = self.r.lifetimes_res_map[&lt_id];
+                        let lt_res = self.r.current_owner.lifetimes_res_map[&lt_id];
                         trace!("FindReferenceVisitor inserting res={:?}", lt_res);
                         self.lifetime.insert(lt_res);
                     }
@@ -3146,7 +3122,7 @@ fn with_generic_param_rib<F>(
                         param.ident,
                     );
                     // Record lifetime res, so lowering knows there is something fishy.
-                    self.record_lifetime_param(param.id, LifetimeRes::Error(guar));
+                    self.record_lifetime_err(param.id, guar);
                     continue;
                 }
 
@@ -3158,7 +3134,7 @@ fn with_generic_param_rib<F>(
                         let rib = match param.kind {
                             GenericParamKind::Lifetime => {
                                 // Record lifetime res, so lowering knows there is something fishy.
-                                self.record_lifetime_param(param.id, LifetimeRes::Error(guar));
+                                self.record_lifetime_err(param.id, guar);
                                 continue;
                             }
                             GenericParamKind::Type { .. } => &mut function_type_rib,
@@ -3193,7 +3169,7 @@ fn with_generic_param_rib<F>(
                         .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
                         .emit_unless_delay(is_raw_underscore_lifetime);
                     // Record lifetime res, so lowering knows there is something fishy.
-                    self.record_lifetime_param(param.id, LifetimeRes::Error(guar));
+                    self.record_lifetime_err(param.id, guar);
                     continue;
                 }
 
@@ -3203,7 +3179,7 @@ fn with_generic_param_rib<F>(
                         lifetime: param.ident,
                     });
                     // Record lifetime res, so lowering knows there is something fishy.
-                    self.record_lifetime_param(param.id, LifetimeRes::Error(guar));
+                    self.record_lifetime_err(param.id, guar);
                     continue;
                 }
 
@@ -3217,7 +3193,7 @@ fn with_generic_param_rib<F>(
                     }
                     GenericParamKind::Lifetime => {
                         let res = LifetimeRes::Param { param: def_id, binder };
-                        self.record_lifetime_param(param.id, res);
+                        self.record_lifetime_def(param.id, res);
                         function_lifetime_rib.bindings.insert(ident, (param.id, res));
                         continue;
                     }
@@ -3923,12 +3899,24 @@ fn resolve_delegation(
             this.visit_path(&delegation.path);
         });
 
-        self.r.delegation_infos.insert(
-            self.r.current_owner.def_id,
-            DelegationInfo {
-                resolution_node: if is_in_trait_impl { item_id } else { delegation.id },
-            },
-        );
+        let resolution_id = if is_in_trait_impl { item_id } else { delegation.id };
+        let def_id = self
+            .r
+            .partial_res_map
+            .get(&resolution_id)
+            .and_then(|r| r.expect_full_res().opt_def_id());
+        if let Some(resolution_id) = def_id {
+            self.r
+                .delegation_infos
+                .insert(self.r.current_owner.def_id, DelegationInfo { resolution_id });
+        } else {
+            self.r.tcx.dcx().span_delayed_bug(
+                delegation.path.span,
+                format!(
+                    "LoweringContext: couldn't resolve node {resolution_id:?} in delegation item",
+                ),
+            );
+        };
 
         let Some(body) = &delegation.body else { return };
         self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
@@ -4780,8 +4768,7 @@ fn smart_resolve_path_fragment(
                 // it needs to be added to the trait map.
                 if ns == ValueNS {
                     let item_name = path.last().unwrap().ident;
-                    let traits = self.traits_in_scope(item_name, ns);
-                    self.r.trait_map.insert(node_id, traits);
+                    self.record_traits_in_scope(node_id, item_name);
                 }
 
                 if PrimTy::from_name(path[0].ident.name).is_some() {
@@ -5212,7 +5199,7 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
                 match self.resolve_label(label.ident) {
                     Ok((node_id, _)) => {
                         // Since this res is a label, it is never read.
-                        self.r.label_res_map.insert(expr.id, node_id);
+                        self.r.current_owner.label_res_map.insert(expr.id, node_id);
                         self.diag_metadata.unused_labels.swap_remove(&node_id);
                     }
                     Err(error) => {
@@ -5382,13 +5369,11 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
                 // we need to add any trait methods we find that match the
                 // field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.traits_in_scope(ident, ValueNS);
-                self.r.trait_map.insert(expr.id, traits);
+                self.record_traits_in_scope(expr.id, ident);
             }
             ExprKind::MethodCall(ref call) => {
                 debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
-                let traits = self.traits_in_scope(call.seg.ident, ValueNS);
-                self.r.trait_map.insert(expr.id, traits);
+                self.record_traits_in_scope(expr.id, call.seg.ident);
             }
             _ => {
                 // Nothing to do.
@@ -5396,13 +5381,14 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
         }
     }
 
-    fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> &'tcx [TraitCandidate<'tcx>] {
-        self.r.traits_in_scope(
+    fn record_traits_in_scope(&mut self, node_id: NodeId, ident: Ident) {
+        let traits = self.r.traits_in_scope(
             self.current_trait_ref.as_ref().map(|(module, _)| *module),
             &self.parent_scope,
             ident.span,
-            Some((ident.name, ns)),
-        )
+            Some((ident.name, ValueNS)),
+        );
+        self.r.trait_map.insert(node_id, traits);
     }
 
     fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 419a47b..423c13f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -149,10 +149,8 @@ pub(super) struct ElisionFnParameter {
 /// This is used to suggest introducing an explicit lifetime.
 #[derive(Clone, Copy, Debug)]
 pub(super) enum LifetimeElisionCandidate {
-    /// This is not a real lifetime.
+    /// This is not a real lifetime, or it is a named lifetime, in which case we won't suggest anything.
     Ignore,
-    /// There is a named lifetime, we won't suggest anything.
-    Named,
     Missing(MissingLifetime),
 }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index f5f4c9e..ffb2181 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -53,12 +53,11 @@
 use rustc_hir::attrs::StrippedCfgItem;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{
-    self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, MacroKinds, NonMacroAttrKind, PartialRes,
-    PerNS,
+    self, CtorOf, DefKind, DocLinkResMap, MacroKinds, NonMacroAttrKind, PartialRes, PerNS,
 };
 use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
 use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap};
-use rustc_hir::{PrimTy, TraitCandidate, find_attr};
+use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate, find_attr};
 use rustc_index::bit_set::DenseBitSet;
 use rustc_metadata::creader::CStore;
 use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};
@@ -822,7 +821,7 @@ fn for_each_child_mut<'tcx, R: AsMut<Resolver<'ra, 'tcx>>>(
     }
 
     /// This modifies `self` in place. The traits will be stored in `self.traits`.
-    fn ensure_traits<'tcx>(self, resolver: &impl AsRef<Resolver<'ra, 'tcx>>) {
+    fn ensure_traits<'tcx>(self, resolver: &Resolver<'ra, 'tcx>) {
         let mut traits = self.traits.borrow_mut(resolver.as_ref());
         if traits.is_none() {
             let mut collected_traits = Vec::new();
@@ -996,10 +995,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[derive(Clone, Debug)]
 struct DeclData<'ra> {
     kind: DeclKind<'ra>,
-    ambiguity: CmCell<Option<Decl<'ra>>>,
-    /// Produce a warning instead of an error when reporting ambiguities inside this binding.
-    /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
-    warn_ambiguity: CmCell<bool>,
+    ambiguity: CmCell<Option<(Decl<'ra>, bool /*warning*/)>>,
     expansion: LocalExpnId,
     span: Span,
     initial_vis: Visibility<DefId>,
@@ -1160,7 +1156,7 @@ fn import_source(&self) -> Decl<'ra> {
 
     fn descent_to_ambiguity(self: Decl<'ra>) -> Option<(Decl<'ra>, Decl<'ra>)> {
         match self.ambiguity.get() {
-            Some(ambig_binding) => Some((self, ambig_binding)),
+            Some((ambig_binding, _)) => Some((self, ambig_binding)),
             None => match self.kind {
                 DeclKind::Import { source_decl, .. } => source_decl.descent_to_ambiguity(),
                 _ => None,
@@ -1176,14 +1172,6 @@ fn is_ambiguity_recursive(&self) -> bool {
             }
     }
 
-    fn warn_ambiguity_recursive(&self) -> bool {
-        self.warn_ambiguity.get()
-            || match self.kind {
-                DeclKind::Import { source_decl, .. } => source_decl.warn_ambiguity_recursive(),
-                _ => false,
-            }
-    }
-
     fn is_possibly_imported_variant(&self) -> bool {
         match self.kind {
             DeclKind::Import { source_decl, .. } => source_decl.is_possibly_imported_variant(),
@@ -1380,12 +1368,8 @@ pub struct Resolver<'ra, 'tcx> {
     import_res_map: NodeMap<PerNS<Option<Res>>> = Default::default(),
     /// An import will be inserted into this map if it has been used.
     import_use_map: FxHashMap<Import<'ra>, Used> = default::fx_hash_map(),
-    /// Resolutions for labels (node IDs of their corresponding blocks or loops).
-    label_res_map: NodeMap<NodeId> = Default::default(),
-    /// Resolutions for lifetimes.
-    lifetimes_res_map: NodeMap<LifetimeRes> = Default::default(),
     /// Lifetime parameters that lowering will have to introduce.
-    extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>> = Default::default(),
+    extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, MissingLifetimeKind)>> = Default::default(),
 
     /// `CrateNum` resolutions of `extern crate` items.
     extern_crate_map: UnordMap<LocalDefId, CrateNum> = Default::default(),
@@ -1533,8 +1517,6 @@ pub struct Resolver<'ra, 'tcx> {
     /// they are declared in the static array generated by proc_macro_harness.
     proc_macros: Vec<LocalDefId> = Vec::new(),
     confused_type_with_std_module: FxIndexMap<Span, Span>,
-    /// Whether lifetime elision was successful.
-    lifetime_elision_allowed: FxHashSet<NodeId> = default::fx_hash_set(),
 
     /// Names of items that were stripped out via cfg with their corresponding cfg meta item.
     stripped_cfg_items: Vec<StrippedCfgItem<NodeId>> = Vec::new(),
@@ -1595,7 +1577,6 @@ fn new_def_decl(
         self.alloc_decl(DeclData {
             kind: DeclKind::Def(res),
             ambiguity: CmCell::new(None),
-            warn_ambiguity: CmCell::new(false),
             initial_vis: vis,
             ambiguity_vis_max: CmCell::new(None),
             ambiguity_vis_min: CmCell::new(None),
@@ -2017,13 +1998,10 @@ pub fn into_outputs(self) -> ResolverOutputs<'tcx> {
         let ast_lowering = ty::ResolverAstLowering {
             partial_res_map: self.partial_res_map,
             import_res_map: self.import_res_map,
-            label_res_map: self.label_res_map,
-            lifetimes_res_map: self.lifetimes_res_map,
             extra_lifetime_params_map: self.extra_lifetime_params_map,
             next_node_id: self.next_node_id,
             owners: self.owners,
             trait_map: self.trait_map,
-            lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
             delegation_infos: self.delegation_infos,
             disambiguators,
@@ -2261,17 +2239,7 @@ fn matches_previous_ambiguity_error(&self, ambi: &AmbiguityError<'_>) -> bool {
     }
 
     fn record_use(&mut self, ident: Ident, used_decl: Decl<'ra>, used: Used) {
-        self.record_use_inner(ident, used_decl, used, used_decl.warn_ambiguity.get());
-    }
-
-    fn record_use_inner(
-        &mut self,
-        ident: Ident,
-        used_decl: Decl<'ra>,
-        used: Used,
-        warn_ambiguity: bool,
-    ) {
-        if let Some(b2) = used_decl.ambiguity.get() {
+        if let Some((b2, warning)) = used_decl.ambiguity.get() {
             let ambiguity_error = AmbiguityError {
                 kind: AmbiguityKind::GlobVsGlob,
                 ambig_vis: None,
@@ -2280,7 +2248,7 @@ fn record_use_inner(
                 b2,
                 scope1: Scope::ModuleGlobs(used_decl.parent_module.unwrap(), None),
                 scope2: Scope::ModuleGlobs(b2.parent_module.unwrap(), None),
-                warning: if warn_ambiguity { Some(AmbiguityWarning::GlobImport) } else { None },
+                warning: if warning { Some(AmbiguityWarning::GlobImport) } else { None },
             };
             if !self.matches_previous_ambiguity_error(&ambiguity_error) {
                 // avoid duplicated span information to be emit out
@@ -2330,12 +2298,7 @@ fn record_use_inner(
                 self.used_imports.insert(id);
             }
             self.add_to_glob_map(import, ident.name);
-            self.record_use_inner(
-                ident,
-                source_decl,
-                Used::Other,
-                warn_ambiguity || source_decl.warn_ambiguity.get(),
-            );
+            self.record_use(ident, source_decl, Used::Other);
         }
     }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 1b2e24a..de60645 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2252,12 +2252,12 @@ pub(crate) fn parse_assert_incr_state(
         "inject the given attribute in the crate"),
     cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
         "threshold to allow cross crate inlining of functions"),
-    debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
-        "emit discriminators and other data necessary for AutoFDO"),
     debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED],
         "emit type and line information for additional data types (default: no)"),
     debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
         "compress debug info sections (none, zlib, zstd, default: none)"),
+    debuginfo_for_profiling: bool = (false, parse_bool, [TRACKED],
+        "emit discriminators and other data necessary for AutoFDO"),
     deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
         "deduplicate identical diagnostics (default: yes)"),
     default_visibility: Option<SymbolVisibility> = (None, parse_opt_symbol_visibility, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ba8ab39..7263680 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -600,6 +600,7 @@
         cfi,
         cfi_encoding,
         char,
+        clflushopt_target_feature,
         client,
         clippy,
         clobber_abi,
@@ -1039,6 +1040,7 @@
         global_asm,
         global_registration,
         globs,
+        gpu_kernel: "gpu-kernel",
         gpu_launch_sized_workgroup_mem,
         gt,
         guard,
@@ -1423,6 +1425,7 @@
         of,
         off,
         offload,
+        offload_kernel,
         offset,
         offset_of,
         offset_of_enum,
@@ -2162,6 +2165,7 @@
         underscore_imports,
         underscore_lifetimes,
         uniform_paths,
+        unimplemented,
         unit,
         universal_impl_trait,
         unix,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 61c1c83..e68e76d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -646,9 +646,11 @@ fn print_dyn_existential(
                 // could have different bound vars *anyways*.
                 match predicate.as_ref().skip_binder() {
                     ty::ExistentialPredicate::Trait(trait_ref) => {
-                        // Use a type that can't appear in defaults of type parameters.
-                        let dummy_self = Ty::new_fresh(p.tcx, 0);
-                        let trait_ref = trait_ref.with_self_ty(p.tcx, dummy_self);
+                        // Dummy Self is safe to use as it can't appear in generic param defaults
+                        // which is important later on for correctly eliding generic args that
+                        // coincide with their default.
+                        let trait_ref =
+                            trait_ref.with_self_ty(p.tcx, p.tcx.types.trait_object_dummy_self);
                         p.print_def_path(trait_ref.def_id, trait_ref.args)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
@@ -690,8 +692,8 @@ fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
 
             // We may still encounter unevaluated consts due to the printing
             // logic sometimes passing identity-substituted impl headers.
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => {
-                return self.print_def_path(def, args);
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => {
+                return self.print_def_path(kind.def_id(), args);
             }
 
             ty::ConstKind::Expr(_)
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index ecdb6ab..d399bfc 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -5,6 +5,7 @@
 
 [dependencies]
 # tidy-alphabetical-start
+arrayvec = { version = "0.7", default-features = false }
 bitflags = "2.4.1"
 object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] }
 rustc_abi = { path = "../rustc_abi" }
diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs
index 4fafa7b..f17e59c 100644
--- a/compiler/rustc_target/src/callconv/mips64.rs
+++ b/compiler/rustc_target/src/callconv/mips64.rs
@@ -1,3 +1,4 @@
+use arrayvec::ArrayVec;
 use rustc_abi::{
     BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface,
 };
@@ -81,8 +82,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
 {
     let dl = cx.data_layout();
     let size = arg.layout.size;
-    let mut prefix = [None; 8];
-    let mut prefix_index = 0;
+    let mut prefix = ArrayVec::new();
 
     // Detect need for padding
     let align = Ord::clamp(arg.layout.align.abi, dl.i64_align, dl.i128_align);
@@ -107,7 +107,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
                 // doubles not part of another aggregate are passed as floats.
                 let mut last_offset = Size::ZERO;
 
-                for i in 0..arg.layout.fields.count() {
+                'outer: for i in 0..arg.layout.fields.count() {
                     let field = arg.layout.field(cx, i);
                     let offset = arg.layout.fields.offset(i);
 
@@ -117,19 +117,15 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
                             if offset.is_aligned(dl.f64_align) {
                                 // Insert enough integers to cover [last_offset, offset)
                                 assert!(last_offset.is_aligned(dl.f64_align));
-                                for _ in 0..((offset - last_offset).bits() / 64)
-                                    .min((prefix.len() - prefix_index) as u64)
-                                {
-                                    prefix[prefix_index] = Some(Reg::i64());
-                                    prefix_index += 1;
+                                for _ in 0..((offset - last_offset).bits() / 64) {
+                                    if prefix.try_push(Reg::i64()).is_err() {
+                                        break 'outer;
+                                    }
                                 }
 
-                                if prefix_index == prefix.len() {
+                                if prefix.try_push(Reg::f64()).is_err() {
                                     break;
                                 }
-
-                                prefix[prefix_index] = Some(Reg::f64());
-                                prefix_index += 1;
                                 last_offset = offset + Reg::f64().size;
                             }
                         }
@@ -139,7 +135,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
         };
 
         // Extract first 8 chunks as the prefix
-        let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
+        let rest_size = size - Size::from_bytes(8) * prefix.len() as u64;
         arg.cast_to_and_pad_i32(
             CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size)),
             pad_i32,
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index e6eb68c..3013d41 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -1,5 +1,6 @@
 use std::{fmt, iter};
 
+use arrayvec::ArrayVec;
 use rustc_abi::{
     AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, FieldsShape, HasDataLayout, Primitive,
     Reg, RegKind, Scalar, Size, TyAbiInterface, TyAndLayout, Variants,
@@ -264,7 +265,11 @@ pub fn consecutive(unit: Reg, total: Size) -> Self {
 /// (and all data in the padding between the registers is dropped).
 #[derive(Clone, PartialEq, Eq, Hash, Debug, StableHash)]
 pub struct CastTarget {
-    pub prefix: [Option<Reg>; 8],
+    // Note that this is fixed to 8 elements for now as ABIs currently don't
+    // need anything further beyond that, and when this code was originally
+    // refactored to use `ArrayVec` it was already using 8, so that stuck
+    // around.
+    pub prefix: ArrayVec<Reg, 8>,
     /// The offset of `rest` from the start of the value. Currently only implemented for a `Reg`
     /// pair created by the `offset_pair` method.
     pub rest_offset: Option<Size>,
@@ -280,18 +285,20 @@ fn from(unit: Reg) -> CastTarget {
 
 impl From<Uniform> for CastTarget {
     fn from(uniform: Uniform) -> CastTarget {
-        Self::prefixed([None; 8], uniform)
+        Self::prefixed(Default::default(), uniform)
     }
 }
 
 impl CastTarget {
-    pub fn prefixed(prefix: [Option<Reg>; 8], rest: Uniform) -> Self {
+    pub fn prefixed(prefix: ArrayVec<Reg, 8>, rest: Uniform) -> Self {
         Self { prefix, rest_offset: None, rest, attrs: ArgAttributes::new() }
     }
 
     pub fn offset_pair(a: Reg, offset_from_start: Size, b: Reg) -> Self {
+        let mut prefix = ArrayVec::new();
+        prefix.push(a);
         Self {
-            prefix: [Some(a), None, None, None, None, None, None, None],
+            prefix,
             rest_offset: Some(offset_from_start),
             rest: b.into(),
             attrs: ArgAttributes::new(),
@@ -304,7 +311,9 @@ pub fn with_attrs(mut self, attrs: ArgAttributes) -> Self {
     }
 
     pub fn pair(a: Reg, b: Reg) -> CastTarget {
-        Self::prefixed([Some(a), None, None, None, None, None, None, None], Uniform::from(b))
+        let mut prefix = ArrayVec::new();
+        prefix.push(a);
+        Self::prefixed(prefix, Uniform::from(b))
     }
 
     /// When you only access the range containing valid data, you can use this unaligned size;
@@ -314,10 +323,7 @@ pub fn unaligned_size<C: HasDataLayout>(&self, _cx: &C) -> Size {
         let prefix_size = if let Some(offset_from_start) = self.rest_offset {
             offset_from_start
         } else {
-            self.prefix
-                .iter()
-                .filter_map(|x| x.map(|reg| reg.size))
-                .fold(Size::ZERO, |acc, size| acc + size)
+            self.prefix.iter().map(|reg| reg.size).fold(Size::ZERO, |acc, size| acc + size)
         };
         // Remaining arguments are passed in chunks of the unit size
         let rest_size =
@@ -333,7 +339,7 @@ pub fn size<C: HasDataLayout>(&self, cx: &C) -> Size {
     pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
         self.prefix
             .iter()
-            .filter_map(|x| x.map(|reg| reg.align(cx)))
+            .map(|reg| reg.align(cx))
             .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), |acc, align| {
                 acc.max(align)
             })
diff --git a/compiler/rustc_target/src/callconv/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs
index a19b89c..3919b7a 100644
--- a/compiler/rustc_target/src/callconv/nvptx64.rs
+++ b/compiler/rustc_target/src/callconv/nvptx64.rs
@@ -1,3 +1,4 @@
+use arrayvec::ArrayVec;
 use rustc_abi::{HasDataLayout, Reg, Size, TyAbiInterface};
 
 use super::CastTarget;
@@ -41,10 +42,9 @@ fn classify_aggregate<Ty>(arg: &mut ArgAbi<'_, Ty>) {
     };
 
     if align_bytes == size.bytes() {
-        arg.cast_to(CastTarget::prefixed(
-            [Some(reg), None, None, None, None, None, None, None],
-            Uniform::new(Reg::i8(), Size::ZERO),
-        ));
+        let mut prefix = ArrayVec::new();
+        prefix.push(reg);
+        arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(Reg::i8(), Size::ZERO)));
     } else {
         arg.cast_to(Uniform::new(reg, size));
     }
@@ -79,10 +79,9 @@ fn classify_arg_kernel<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
     };
     if arg.layout.size.bytes() / align_bytes == 1 {
         // Make sure we pass the struct as array at the LLVM IR level and not as a single integer.
-        arg.cast_to(CastTarget::prefixed(
-            [Some(unit), None, None, None, None, None, None, None],
-            Uniform::new(unit, Size::ZERO),
-        ));
+        let mut prefix = ArrayVec::new();
+        prefix.push(unit);
+        arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(unit, Size::ZERO)));
     } else {
         arg.cast_to(Uniform::new(unit, arg.layout.size));
     }
diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs
index 55f264d..b5e5c3e 100644
--- a/compiler/rustc_target/src/callconv/sparc64.rs
+++ b/compiler/rustc_target/src/callconv/sparc64.rs
@@ -1,3 +1,4 @@
+use arrayvec::ArrayVec;
 use rustc_abi::{
     Align, BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface,
     TyAndLayout, Variants,
@@ -147,12 +148,7 @@ fn classify_arg<'a, Ty, C>(
     let mut double_words = [DoubleWord::Words([Word::Integer; 2]); ARGUMENT_REGISTERS / 2];
     classify(cx, &arg.layout, Size::ZERO, &mut double_words);
 
-    let mut regs = [None; ARGUMENT_REGISTERS];
-    let mut i = 0;
-    let mut push = |reg| {
-        regs[i] = Some(reg);
-        i += 1;
-    };
+    let mut regs = ArrayVec::new();
     let mut attrs = ArgAttribute::empty();
 
     for (index, double_word) in double_words.into_iter().enumerate() {
@@ -162,7 +158,7 @@ fn classify_arg<'a, Ty, C>(
         match double_word {
             // `f128` must be aligned to be assigned a float register.
             DoubleWord::F128Start if (start_double_word_count + index).is_multiple_of(2) => {
-                push(Reg::f128());
+                regs.push(Reg::f128());
             }
             DoubleWord::F128Start => {
                 // Clang currently handles this case nonsensically, always returning a packed
@@ -170,30 +166,27 @@ fn classify_arg<'a, Ty, C>(
                 // the `long double` isn't aligned on the stack, which also makes all future
                 // arguments get passed in the wrong registers. This passes the `f128` in integer
                 // registers when it is unaligned, same as with `f32` and `f64`.
-                push(Reg::i64());
-                push(Reg::i64());
+                regs.push(Reg::i64());
+                regs.push(Reg::i64());
             }
             DoubleWord::F128End => {} // Already handled by `F128Start`
-            DoubleWord::F64 => push(Reg::f64()),
-            DoubleWord::Words([Word::Integer, Word::Integer]) => push(Reg::i64()),
+            DoubleWord::F64 => regs.push(Reg::f64()),
+            DoubleWord::Words([Word::Integer, Word::Integer]) => regs.push(Reg::i64()),
             DoubleWord::Words(words) => {
                 attrs |= ArgAttribute::InReg;
                 for word in words {
                     match word {
-                        Word::F32 => push(Reg::f32()),
-                        Word::Integer => push(Reg::i32()),
+                        Word::F32 => regs.push(Reg::f32()),
+                        Word::Integer => regs.push(Reg::i32()),
                     }
                 }
             }
         }
     }
 
-    let cast_target = match regs {
-        [Some(reg), None, rest @ ..] => {
-            // Just a single register is needed for this value.
-            debug_assert!(rest.iter().all(|x| x.is_none()));
-            CastTarget::from(reg)
-        }
+    let cast_target = match regs.as_slice() {
+        // Just a single register is needed for this value.
+        [reg] => CastTarget::from(*reg),
         _ => CastTarget::prefixed(regs, Uniform::new(Reg::i8(), Size::ZERO)),
     };
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index d6a9e27..ea6abe5 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -132,8 +132,6 @@ pub enum LinkerFlavor {
     // Below: other linker-like tools with unique interfaces for exotic targets.
     /// Linker tool for BPF.
     Bpf,
-    /// Linker tool for Nvidia PTX.
-    Ptx,
     /// LLVM bitcode linker that can be used as a `self-contained` linker
     Llbc,
 }
@@ -153,7 +151,6 @@ pub enum LinkerFlavorCli {
     Msvc(Lld),
     EmCc,
     Bpf,
-    Ptx,
     Llbc,
 
     // Legacy stable values
@@ -174,8 +171,7 @@ pub fn is_unstable(&self) -> bool {
             | LinkerFlavorCli::Msvc(Lld::Yes)
             | LinkerFlavorCli::EmCc
             | LinkerFlavorCli::Bpf
-            | LinkerFlavorCli::Llbc
-            | LinkerFlavorCli::Ptx => true,
+            | LinkerFlavorCli::Llbc => true,
             LinkerFlavorCli::Gcc
             | LinkerFlavorCli::Ld
             | LinkerFlavorCli::Lld(..)
@@ -211,7 +207,6 @@ fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> L
             LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
             LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
             LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
-            LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
 
             // Below: legacy stable values
             LinkerFlavorCli::Gcc => match lld_flavor {
@@ -251,7 +246,6 @@ fn to_cli(self) -> LinkerFlavorCli {
             LinkerFlavor::EmCc => LinkerFlavorCli::Em,
             LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
             LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
-            LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
         }
     }
 
@@ -266,7 +260,6 @@ fn to_cli_counterpart(self) -> LinkerFlavorCli {
             LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
             LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
             LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
-            LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
         }
     }
 
@@ -279,7 +272,7 @@ fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
             LinkerFlavorCli::Unix(cc) => (Some(cc), None),
             LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
             LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
-            LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
+            LinkerFlavorCli::Bpf => (None, None),
             LinkerFlavorCli::Llbc => (None, None),
 
             // Below: legacy stable values
@@ -336,7 +329,7 @@ fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFla
             LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
             LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
             LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
-            LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
+            LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc => self,
         }
     }
 
@@ -355,7 +348,7 @@ pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
         let compatible = |cli| {
             // The CLI flavor should be compatible with the target if:
             match (self, cli) {
-                // 1. they are counterparts: they have the same principal flavor.
+                // they are counterparts: they have the same principal flavor.
                 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
                 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
                 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
@@ -363,10 +356,7 @@ pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
                 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
                 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
                 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
-                | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
-                | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
-                // 2. The linker flavor is independent of target and compatible
-                (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
+                | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc) => return true,
                 _ => {}
             }
 
@@ -389,8 +379,7 @@ pub fn lld_flavor(self) -> LldFlavor {
             | LinkerFlavor::Unix(..)
             | LinkerFlavor::EmCc
             | LinkerFlavor::Bpf
-            | LinkerFlavor::Llbc
-            | LinkerFlavor::Ptx => LldFlavor::Ld,
+            | LinkerFlavor::Llbc => LldFlavor::Ld,
             LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
             LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
             LinkerFlavor::Msvc(..) => LldFlavor::Link,
@@ -415,8 +404,7 @@ pub fn uses_lld(self) -> bool {
             | LinkerFlavor::Msvc(_)
             | LinkerFlavor::Unix(_)
             | LinkerFlavor::Bpf
-            | LinkerFlavor::Llbc
-            | LinkerFlavor::Ptx => false,
+            | LinkerFlavor::Llbc => false,
         }
     }
 
@@ -435,8 +423,7 @@ pub fn uses_cc(self) -> bool {
             | LinkerFlavor::Msvc(_)
             | LinkerFlavor::Unix(_)
             | LinkerFlavor::Bpf
-            | LinkerFlavor::Llbc
-            | LinkerFlavor::Ptx => false,
+            | LinkerFlavor::Llbc => false,
         }
     }
 
@@ -512,7 +499,6 @@ fn from_str(s: &str) -> Result<LinkerFlavorCli, Self::Err> {
     (LinkerFlavorCli::EmCc) "em-cc"
     (LinkerFlavorCli::Bpf) "bpf"
     (LinkerFlavorCli::Llbc) "llbc"
-    (LinkerFlavorCli::Ptx) "ptx"
 
     // Legacy stable flavors
     (LinkerFlavorCli::Gcc) "gcc"
@@ -2740,8 +2726,7 @@ fn add_link_args_iter(
         | LinkerFlavor::Unix(..)
         | LinkerFlavor::EmCc
         | LinkerFlavor::Bpf
-        | LinkerFlavor::Llbc
-        | LinkerFlavor::Ptx => {}
+        | LinkerFlavor::Llbc => {}
     }
 }
 
@@ -3127,10 +3112,7 @@ macro_rules! check_matches {
                             "mixing MSVC and non-MSVC linker flavors"
                         );
                     }
-                    LinkerFlavor::EmCc
-                    | LinkerFlavor::Bpf
-                    | LinkerFlavor::Ptx
-                    | LinkerFlavor::Llbc => {
+                    LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc => {
                         check_eq!(flavor, self.linker_flavor, "mixing different linker flavors")
                     }
                 }
@@ -3582,6 +3564,19 @@ macro_rules! check_matches {
                     "invalid `target_abi` for CSky"
                 );
             }
+            Arch::Wasm32 | Arch::Wasm64 => {
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on wasm"
+                );
+                check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on wasm");
+                check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on wasm");
+                check_matches!(
+                    self.cfg_abi,
+                    CfgAbi::Unspecified | CfgAbi::Other(_),
+                    "invalid `target_abi` for wasm"
+                );
+            }
             ref arch => {
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on {arch}");
                 // Ensure consistency among built-in targets, but give JSON targets the opportunity
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index d8a0bd5..b74aca4 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -21,7 +21,6 @@ pub(crate) fn target() -> Target {
             vendor: "nvidia".into(),
             linker_flavor: LinkerFlavor::Llbc,
 
-            // With `ptx-linker` approach, it can be later overridden via link flags.
             cpu: "sm_70".into(),
 
             // No longer supported architectures
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index b009c42..85697b1 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -1,6 +1,44 @@
 //! Declares Rust's target feature names for each target.
 //! Note that these are similar to but not always identical to LLVM's feature names,
 //! and Rust adds some features that do not correspond to LLVM features at all.
+//!
+//! The target features listed here can be used in `#[target_feature]` and `#[cfg(target_feature)]`.
+//! They also do not trigger any warnings when used with `-Ctarget-feature`.
+//!
+//! Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature`
+//! on stable. Using a feature not on the list of Rust target features only emits a warning.
+//! Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating.
+//! `cfg(target_feature)` for unstable features just works on nightly without any feature gate.
+//! `#[target_feature]` requires a feature gate.
+//!
+//! When adding features to the below lists
+//! check whether they're named already elsewhere in rust
+//! e.g. in stdarch and whether the given name matches LLVM's
+//! if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted.
+//! Additionally, if the feature is not available in older version of LLVM supported by the current
+//! rust, the same function must be updated to filter out these features to avoid triggering
+//! warnings.
+//!
+//! Also note that all target features listed here must be purely additive: for target_feature 1.1 to
+//! be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a
+//! per-function level, since we would then allow safe calls from functions with `+soft-float` to
+//! functions without that feature!
+//!
+//! It is important for soundness to consider the interaction of target features and the function
+//! call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as
+//! arguments, so letting people toggle that feature would be unsound. To this end, the
+//! [`Target::abi_required_features`] function computes which target features must and must not be
+//! enabled for any given target, and individual features can also be marked as [`Forbidden`]. See
+//! <https://github.com/rust-lang/rust/issues/116344> for some more context.
+//!
+//! The one exception to features that change the ABI is features that enable larger vector
+//! registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store
+//! information about which target feature is ABI-required for which vector size; this is used to
+//! ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For
+//! the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.)
+//! Also see <https://github.com/rust-lang/rust/issues/116558>.
+//!
+//! Stabilizing a target feature requires t-lang approval.
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_macros::StableHash;
 use rustc_span::{Symbol, sym};
@@ -32,9 +70,12 @@ pub enum Stability {
         Symbol,
     ),
     /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be
-    /// set in the target spec. It is never set in `cfg(target_feature)`. Used in
-    /// particular for features are actually ABI configuration flags (not all targets are as nice as
-    /// RISC-V and have an explicit way to set the ABI separate from target features).
+    /// set in the target spec. It is never set in `cfg(target_feature)`. Used in particular for
+    /// features are actually ABI configuration flags (such as "soft-float" on many targets).
+    /// However, "forbidden" target features can still sometimes be enabled via `-Ctarget-cpu` or
+    /// target feature implications (on the Rust/LLVM level). To prevent that, ABI-relevant target
+    /// features are ideally pinned down (required or forbidden) in
+    /// [`Target::abi_required_features`].
     Forbidden {
         reason: &'static str,
         /// True if this is always an error, false if this can be reported as a warning when set via
@@ -102,50 +143,11 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
     }
 }
 
-// Here we list target features that rustc "understands": they can be used in `#[target_feature]`
-// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with
-// `-Ctarget-feature`.
-//
-// Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature`
-// on stable. Using a feature not on the list of Rust target features only emits a warning.
-// Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating.
-// `cfg(target_feature)` for unstable features just works on nightly without any feature gate.
-// `#[target_feature]` requires a feature gate.
-//
-// When adding features to the below lists
-// check whether they're named already elsewhere in rust
-// e.g. in stdarch and whether the given name matches LLVM's
-// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted.
-// Additionally, if the feature is not available in older version of LLVM supported by the current
-// rust, the same function must be updated to filter out these features to avoid triggering
-// warnings.
-//
-// Also note that all target features listed here must be purely additive: for target_feature 1.1 to
-// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a
-// per-function level, since we would then allow safe calls from functions with `+soft-float` to
-// functions without that feature!
-//
-// It is important for soundness to consider the interaction of targets features and the function
-// call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as
-// arguments, so letting people toggle that feature would be unsound. To this end, the
-// `abi_required_features` function computes which target features must and must not be enabled for
-// any given target, and individual features can also be marked as `Forbidden`.
-// See https://github.com/rust-lang/rust/issues/116344 for some more context.
-//
-// The one exception to features that change the ABI is features that enable larger vector
-// registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store
-// information about which target feature is ABI-required for which vector size; this is used to
-// ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For
-// the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.)
-// Also see https://github.com/rust-lang/rust/issues/116558.
-//
-// Stabilizing a target feature requires t-lang approval.
-
-// If feature A "implies" feature B, then:
-// - when A gets enabled (via `-Ctarget-feature` or `#[target_feature]`), we also enable B
-// - when B gets disabled (via `-Ctarget-feature`), we also disable A
-//
-// Both of these are also applied transitively.
+/// If feature A "implies" feature B, then:
+/// - when A gets enabled (via `-Ctarget-feature` or `#[target_feature]`), we also enable B
+/// - when B gets disabled (via `-Ctarget-feature`), we also disable A
+///
+/// Both of these are also applied transitively.
 type ImpliedFeatures = &'static [&'static str];
 
 static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
@@ -464,6 +466,7 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
     ("avxvnniint16", Stable, &["avx2"]),
     ("bmi1", Stable, &[]),
     ("bmi2", Stable, &[]),
+    ("clflushopt", Unstable(sym::clflushopt_target_feature), &[]),
     ("cmpxchg16b", Stable, &[]),
     ("ermsb", Unstable(sym::ermsb_target_feature), &[]),
     ("f16c", Stable, &["avx"]),
@@ -1312,11 +1315,17 @@ pub fn abi_required_features(&self) -> FeatureConstraints {
                 }
             }
             Arch::Avr => {
+                // We only support one ABI on AVR at the moment.
                 // SRAM is minimum requirement for C/C++ in both avr-gcc and Clang,
                 // and backends of them only support assembly for devices have no SRAM.
                 // See the discussion in https://github.com/rust-lang/rust/pull/146900 for more.
                 FeatureConstraints { required: &["sram"], incompatible: &[] }
             }
+            Arch::Wasm32 | Arch::Wasm64 => {
+                // We only support one ABI on wasm at the moment.
+                // No ABI-relevant target features have been identified thus far.
+                NOTHING
+            }
             _ => NOTHING,
         }
     }
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 078658d..236b505 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
@@ -1,8 +1,7 @@
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{Diag, MultiSpan, pluralize};
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::find_attr;
+use rustc_hir::{self as hir, LangItem, find_attr};
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
@@ -140,62 +139,88 @@ pub fn note_and_explain_type_err(
                             let item_name = tcx.item_name(def_id);
                             let item_args = self.format_generic_args(assoc_args);
 
-                            // Here, we try to see if there's an existing
-                            // trait implementation that matches the one that
-                            // we're suggesting to restrict. If so, find the
-                            // "end", whether it be at the end of the trait
-                            // or the end of the generic arguments.
-                            let mut matching_span = None;
-                            let mut matched_end_of_args = false;
-                            for bound in generics.bounds_for_param(local_id) {
-                                let potential_spans = bound.bounds.iter().find_map(|bound| {
-                                    let bound_trait_path = bound.trait_ref()?.path;
-                                    let def_id = bound_trait_path.res.opt_def_id()?;
-                                    let generic_args = bound_trait_path
-                                        .segments
-                                        .iter()
-                                        .last()
-                                        .map(|path| path.args());
-                                    (def_id == trait_ref.def_id)
-                                        .then_some((bound_trait_path.span, generic_args))
-                                });
+                            if
+                            // if we're referencing an async fn trait's output future
+                            //
+                            // AsyncFnOnce
+                            (tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnOnce)
+                                && tcx.is_lang_item(def_id, LangItem::CallOnceFuture))
+                            // AsyncFnMut
+                            ||
+                            (tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnMut)
+                                && tcx.is_lang_item(def_id, LangItem::CallRefFuture))
+                            // AsyncFn
+                            ||
+                            (tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFn)
+                                && tcx.is_lang_item(def_id, LangItem::CallRefFuture))
+                            {
+                                // don't make a suggestion to constrain it, it's not possible in
+                                // current rust. In fact, when something is referring to this, you
+                                // may have just needed to await something.
 
-                                if let Some((end_of_trait, end_of_args)) = potential_spans {
-                                    let args_span = end_of_args.and_then(|args| args.span());
-                                    matched_end_of_args = args_span.is_some();
-                                    matching_span = args_span
-                                        .or_else(|| Some(end_of_trait))
-                                        .map(|span| span.shrink_to_hi());
-                                    break;
-                                }
-                            }
-
-                            if matched_end_of_args {
-                                // Append suggestion to the end of our args
-                                let path = format!(", {item_name}{item_args} = {p}");
-                                note = !suggest_constraining_type_param(
-                                    tcx,
-                                    generics,
-                                    diag,
-                                    &proj.self_ty().to_string(),
-                                    &path,
-                                    None,
-                                    matching_span,
-                                );
+                                diag.help("you may have forgotten to await an async function");
+                                diag.note(format!("it is currently not possible to add bounds constraining the future returned from an async function (`{item_name}`)"));
+                                // don't note, since it's talking about missing bounds. There's
+                                // currently no way to bound the return future
+                                note = false;
                             } else {
-                                // Suggest adding a bound to an existing trait
-                                // or if the trait doesn't exist, add the trait
-                                // and the suggested bounds.
-                                let path = format!("<{item_name}{item_args} = {p}>");
-                                note = !suggest_constraining_type_param(
-                                    tcx,
-                                    generics,
-                                    diag,
-                                    &proj.self_ty().to_string(),
-                                    &path,
-                                    None,
-                                    matching_span,
-                                );
+                                // Here, we try to see if there's an existing
+                                // trait implementation that matches the one that
+                                // we're suggesting to restrict. If so, find the
+                                // "end", whether it be at the end of the trait
+                                // or the end of the generic arguments.
+                                let mut matching_span = None;
+                                let mut matched_end_of_args = false;
+                                for bound in generics.bounds_for_param(local_id) {
+                                    let potential_spans = bound.bounds.iter().find_map(|bound| {
+                                        let bound_trait_path = bound.trait_ref()?.path;
+                                        let def_id = bound_trait_path.res.opt_def_id()?;
+                                        let generic_args = bound_trait_path
+                                            .segments
+                                            .iter()
+                                            .last()
+                                            .map(|path| path.args());
+                                        (def_id == trait_ref.def_id)
+                                            .then_some((bound_trait_path.span, generic_args))
+                                    });
+
+                                    if let Some((end_of_trait, end_of_args)) = potential_spans {
+                                        let args_span = end_of_args.and_then(|args| args.span());
+                                        matched_end_of_args = args_span.is_some();
+                                        matching_span = args_span
+                                            .or_else(|| Some(end_of_trait))
+                                            .map(|span| span.shrink_to_hi());
+                                        break;
+                                    }
+                                }
+
+                                if matched_end_of_args {
+                                    // Append suggestion to the end of our args
+                                    let path = format!(", {item_name}{item_args} = {p}");
+                                    note = !suggest_constraining_type_param(
+                                        tcx,
+                                        generics,
+                                        diag,
+                                        &proj.self_ty().to_string(),
+                                        &path,
+                                        None,
+                                        matching_span,
+                                    );
+                                } else {
+                                    // Suggest adding a bound to an existing trait
+                                    // or if the trait doesn't exist, add the trait
+                                    // and the suggested bounds.
+                                    let path = format!("<{item_name}{item_args} = {p}>");
+                                    note = !suggest_constraining_type_param(
+                                        tcx,
+                                        generics,
+                                        diag,
+                                        &proj.self_ty().to_string(),
+                                        &path,
+                                        None,
+                                        matching_span,
+                                    );
+                                }
                             }
                         }
                         if note {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 4d051a3..9f0e9f4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -448,9 +448,22 @@ pub fn report_selection_error(
                         if let Some((msg, span)) = type_def {
                             err.span_label(span, msg);
                         }
-                        for note in notes {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(note);
+                        // `#[rustc_on_unimplemented]` notes for derivable traits (e.g. `Debug`'s
+                        // "add `#[derive(Debug)]` to `X` or manually `impl Debug for X`") duplicate
+                        // the `consider annotating X with #[derive(..)]` suggestion that
+                        // `suggest_derive` emits below, so skip them when that suggestion will be
+                        // shown. We keep the note otherwise (e.g. when a field isn't `Debug`, so
+                        // the derive can't be suggested) to avoid leaving the diagnostic without
+                        // actionable guidance.
+                        let derive_suggestion_will_be_shown = main_trait_predicate
+                            == leaf_trait_predicate
+                            && self.can_suggest_derive(&obligation, leaf_trait_predicate);
+                        if !derive_suggestion_will_be_shown {
+                            for note in notes {
+                                // If it has a custom `#[rustc_on_unimplemented]` note, let's display
+                                // it.
+                                err.note(note);
+                            }
                         }
                         if let Some(s) = parent_label {
                             let body = obligation.cause.body_id;
@@ -1651,7 +1664,7 @@ pub(super) fn report_projection_error(
                             }
                         };
 
-                    if let Some(lhs) = lhs.to_alias_term(self.tcx)
+                    if let Some(lhs) = lhs.to_alias_term()
                         && let ty::AliasTermKind::ProjectionTy { .. }
                         | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind(self.tcx)
                         && let Some((better_type_err, expected_term)) =
@@ -1661,7 +1674,7 @@ pub(super) fn report_projection_error(
                             Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)),
                             better_type_err,
                         )
-                    } else if let Some(rhs) = rhs.to_alias_term(self.tcx)
+                    } else if let Some(rhs) = rhs.to_alias_term()
                         && let ty::AliasTermKind::ProjectionTy { .. }
                         | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind(self.tcx)
                         && let Some((better_type_err, expected_term)) =
@@ -3732,10 +3745,13 @@ fn report_not_const_evaluatable_error(
                 ty::ConstKind::Unevaluated(uv) => {
                     let mut err =
                         self.dcx().struct_span_err(span, "unconstrained generic constant");
-                    let const_span = self.tcx.def_span(uv.def);
+                    let const_span = self.tcx.def_span(uv.kind.def_id());
 
-                    let const_ty =
-                        self.tcx.type_of(uv.def).instantiate(self.tcx, uv.args).skip_norm_wip();
+                    let const_ty = self
+                        .tcx
+                        .type_of(uv.kind.def_id())
+                        .instantiate(self.tcx, uv.args)
+                        .skip_norm_wip();
                     let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" };
                     let msg = "try adding a `where` bound";
                     match self.tcx.sess.source_map().span_to_snippet(const_span) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 2613992..ef454f5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2648,7 +2648,7 @@ pub(crate) fn build_fn_sig_ty<'tcx>(
         ) -> Ty<'tcx> {
             let inputs = trait_ref.args.type_at(1);
             let sig = match inputs.kind() {
-                ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
+                ty::Tuple(inputs) if infcx.tcx.is_callable_trait(trait_ref.def_id) => {
                     infcx.tcx.mk_fn_sig_safe_rust_abi(*inputs, infcx.next_ty_var(DUMMY_SP))
                 }
                 _ => infcx.tcx.mk_fn_sig_safe_rust_abi([inputs], infcx.next_ty_var(DUMMY_SP)),
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 12dfe73..1aa9af4 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -34,9 +34,11 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>(
         }
         ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => {
             let ct_ty = match ct.kind() {
-                ty::ConstKind::Unevaluated(uv) => {
-                    infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).skip_norm_wip()
-                }
+                ty::ConstKind::Unevaluated(uv) => infcx
+                    .tcx
+                    .type_of(uv.kind.def_id())
+                    .instantiate(infcx.tcx, uv.args)
+                    .skip_norm_wip(),
                 ty::ConstKind::Param(param_ct) => {
                     param_ct.find_const_ty_from_env(obligation.param_env)
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index af104a5..3da4e84 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -774,7 +774,7 @@ fn evaluate_nested_obligations(
 
                             if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct {
                                 self.tcx.dcx().emit_err(UnableToConstructConstantValue {
-                                    span: self.tcx.def_span(unevaluated.def),
+                                    span: self.tcx.def_span(unevaluated.kind.def_id()),
                                     unevaluated,
                                 });
                             }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 45f30cd..90e795f 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -9,7 +9,6 @@
 //! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
 
-use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::bug;
 use rustc_middle::traits::ObligationCause;
@@ -43,11 +42,13 @@ pub fn is_const_evaluatable<'tcx>(
     if tcx.features().generic_const_exprs() {
         let ct = tcx.expand_abstract_consts(unexpanded_ct);
 
-        let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
-            tcx.def_kind(uv.def) == DefKind::AnonConst
-        } else {
-            false
-        };
+        let is_anon_ct = matches!(
+            ct.kind(),
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
+                kind: ty::UnevaluatedConstKind::Anon { .. },
+                ..
+            })
+        );
 
         if !is_anon_ct {
             if satisfied_from_param_env(tcx, infcx, ct, param_env) {
@@ -116,7 +117,7 @@ pub fn is_const_evaluatable<'tcx>(
                 tcx.dcx()
                     .struct_span_fatal(
                         // Slightly better span than just using `span` alone
-                        if span == DUMMY_SP { tcx.def_span(uv.def) } else { span },
+                        if span == DUMMY_SP { tcx.def_span(uv.kind.def_id()) } else { span },
                         "failed to evaluate generic const expression",
                     )
                     .with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index a018a15..1d3c9be 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -7,7 +7,6 @@
 use std::ops::ControlFlow;
 
 use rustc_errors::FatalError;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, LangItem};
 use rustc_middle::query::Providers;
@@ -887,13 +886,15 @@ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
         let ct = self.tcx.expand_abstract_consts(ct);
 
         match ct.kind() {
-            ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => {
+            ty::ConstKind::Unevaluated(
+                proj @ ty::UnevaluatedConst {
+                    kind: ty::UnevaluatedConstKind::Projection { .. },
+                    ..
+                },
+            ) if self.tcx.features().min_generic_const_args() => {
                 match self.allow_self_projections {
-                    AllowSelfProjections::Yes
-                        if matches!(self.tcx.def_kind(proj.def), DefKind::AssocConst { .. })
-                            && let trait_def_id = self.tcx.parent(proj.def)
-                            && self.tcx.def_kind(trait_def_id) == DefKind::Trait =>
-                    {
+                    AllowSelfProjections::Yes => {
+                        let trait_def_id = self.tcx.parent(proj.kind.def_id());
                         let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
 
                         // Only walk contained consts if the parent trait is not a supertrait.
@@ -903,7 +904,7 @@ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
                             ct.super_visit_with(self)
                         }
                     }
-                    _ => ct.super_visit_with(self),
+                    AllowSelfProjections::No => ct.super_visit_with(self),
                 }
             }
             _ => ct.super_visit_with(self),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 914e103..11944a8 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -560,7 +560,7 @@ fn process_obligation(
                         ty::ConstKind::Value(cv) => cv.ty,
                         ty::ConstKind::Unevaluated(uv) => infcx
                             .tcx
-                            .type_of(uv.def)
+                            .type_of(uv.kind.def_id())
                             .instantiate(infcx.tcx, uv.args)
                             .skip_norm_wip(),
                         // FIXME(generic_const_exprs): we should construct an alias like
@@ -719,13 +719,13 @@ fn process_obligation(
                         let c2 = tcx.expand_abstract_consts(c2);
                         debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
 
-                        use rustc_hir::def::DefKind;
                         match (c1.kind(), c2.kind()) {
                             (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
-                                if a.def == b.def
+                                if a.kind == b.kind
                                     && matches!(
-                                        tcx.def_kind(a.def),
-                                        DefKind::AssocConst { .. }
+                                        a.kind,
+                                        ty::UnevaluatedConstKind::Projection { .. }
+                                            | ty::UnevaluatedConstKind::Inherent { .. }
                                     ) =>
                             {
                                 if let Ok(new_obligations) = infcx
@@ -734,8 +734,8 @@ fn process_obligation(
                                     // `generic_const_exprs`
                                     .eq(
                                         DefineOpaqueTypes::Yes,
-                                        ty::AliasTerm::from_unevaluated_const(tcx, a),
-                                        ty::AliasTerm::from_unevaluated_const(tcx, b),
+                                        ty::AliasTerm::from(a),
+                                        ty::AliasTerm::from(b),
                                     )
                                 {
                                     return ProcessResult::Changed(mk_pending(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index a834dbd..c37b50e 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -27,7 +27,6 @@
 use std::ops::ControlFlow;
 
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::DefKind;
 pub use rustc_infer::traits::*;
 use rustc_macros::TypeVisitable;
 use rustc_middle::query::Providers;
@@ -368,7 +367,7 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
                     // const arguments that have a non-empty param env are array repeat counts. These
                     // do not appear in the type system though.
                     if let ty::ConstKind::Unevaluated(uv) = c.kind()
-                        && self.0.def_kind(uv.def) == DefKind::AnonConst
+                        && matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. })
                     {
                         let infcx = self.0.infer_ctxt().build(TypingMode::non_body_analysis());
                         let c = evaluate_const(&infcx, c, ty::ParamEnv::empty());
@@ -607,8 +606,8 @@ pub fn try_evaluate_const<'tcx>(
         | ty::ConstKind::Placeholder(_)
         | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers),
         ty::ConstKind::Unevaluated(uv) => {
-            let opt_anon_const_kind =
-                (tcx.def_kind(uv.def) == DefKind::AnonConst).then(|| tcx.anon_const_kind(uv.def));
+            let opt_anon_const_kind = matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. })
+                .then(|| tcx.anon_const_kind(uv.kind.def_id()));
 
             // Postpone evaluation of constants that depend on generic parameters or
             // inference variables.
@@ -630,7 +629,7 @@ pub fn try_evaluate_const<'tcx>(
                         // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
                         // inference variables and generic parameters to show up in `ty::Const` even though the anon const
                         // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
-                        match tcx.thir_abstract_const(uv.def) {
+                        match tcx.thir_abstract_const(uv.kind.def_id()) {
                             Ok(Some(ct)) => {
                                 let ct = tcx.expand_abstract_consts(
                                     ct.instantiate(tcx, uv.args).skip_norm_wip(),
@@ -651,8 +650,9 @@ pub fn try_evaluate_const<'tcx>(
                                 }
                             }
                             Err(_) | Ok(None) => {
-                                let args = GenericArgs::identity_for_item(tcx, uv.def);
-                                let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
+                                let args = GenericArgs::identity_for_item(tcx, uv.kind.def_id());
+                                let typing_env =
+                                    ty::TypingEnv::post_analysis(tcx, uv.kind.def_id());
                                 (args, typing_env)
                             }
                         }
@@ -680,8 +680,8 @@ pub fn try_evaluate_const<'tcx>(
                     // affect evaluation of the constant as this would make it a "truly" generic const arg.
                     // To prevent this we discard all the generic arguments and evalaute with identity args
                     // and in its own environment instead of the current environment we are normalizing in.
-                    let args = GenericArgs::identity_for_item(tcx, uv.def);
-                    let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
+                    let args = GenericArgs::identity_for_item(tcx, uv.kind.def_id());
+                    let typing_env = ty::TypingEnv::post_analysis(tcx, uv.kind.def_id());
 
                     (args, typing_env)
                 }
@@ -716,17 +716,21 @@ pub fn try_evaluate_const<'tcx>(
                 }
             };
 
-            let uv = ty::UnevaluatedConst::new(uv.def, args);
+            let uv = ty::UnevaluatedConst::new(tcx, uv.kind, args);
             let erased_uv = tcx.erase_and_anonymize_regions(uv);
 
             use rustc_middle::mir::interpret::ErrorHandled;
             // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at
             // where it gets used as a const generic.
-            match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, tcx.def_span(uv.def)) {
+            match tcx.const_eval_resolve_for_typeck(
+                typing_env,
+                erased_uv,
+                tcx.def_span(uv.kind.def_id()),
+            ) {
                 Ok(Ok(val)) => Ok(ty::Const::new_value(
                     tcx,
                     val,
-                    tcx.type_of(uv.def).instantiate(tcx, uv.args).skip_norm_wip(),
+                    tcx.type_of(uv.kind.def_id()).instantiate(tcx, uv.args).skip_norm_wip(),
                 )),
                 Ok(Err(_)) => {
                     let e = tcx.dcx().delayed_bug(
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 84dbd53..fa2cfda 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -2,7 +2,6 @@
 
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::msg;
-use rustc_hir::def::DefKind;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::{
@@ -450,7 +449,7 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
 
         if tcx.features().generic_const_exprs()
             // Normalize type_const items even with feature `generic_const_exprs`.
-            && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if tcx.is_type_const(uv.def))
+            && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if tcx.is_type_const(uv.kind.def_id()))
             || !needs_normalization(self.selcx.infcx, &ct)
         {
             return ct;
@@ -461,30 +460,24 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
             _ => return ct.super_fold_with(self),
         };
 
-        // Note that the AssocConst and Const cases are unreachable on stable,
+        // Note that the Projection/Inherent/Free cases are unreachable on stable,
         // unless a `min_generic_const_args` feature gate error has already
         // been emitted earlier in compilation.
         //
         // That's because we can only end up with an Unevaluated ty::Const for a const item
         // if it was marked with `type const`. Using this attribute without the mgca
         // feature gate causes a parse error.
-        let ct = match tcx.def_kind(uv.def) {
-            DefKind::AssocConst { .. } => match tcx.def_kind(tcx.parent(uv.def)) {
-                DefKind::Trait => self
-                    .normalize_trait_projection(ty::AliasTerm::from_unevaluated_const(tcx, uv))
-                    .expect_const(),
-                DefKind::Impl { of_trait: false } => self
-                    .normalize_inherent_projection(ty::AliasTerm::from_unevaluated_const(tcx, uv))
-                    .expect_const(),
-                kind => unreachable!(
-                    "unexpected `DefKind` for const alias' resolution's parent def: {:?}",
-                    kind
-                ),
-            },
-            DefKind::Const { .. } => self
-                .normalize_free_alias(ty::AliasTerm::from_unevaluated_const(tcx, uv))
-                .expect_const(),
-            DefKind::AnonConst => {
+        let ct = match uv.kind {
+            ty::UnevaluatedConstKind::Projection { .. } => {
+                self.normalize_trait_projection(uv.into()).expect_const()
+            }
+            ty::UnevaluatedConstKind::Inherent { .. } => {
+                self.normalize_inherent_projection(uv.into()).expect_const()
+            }
+            ty::UnevaluatedConstKind::Free { .. } => {
+                self.normalize_free_alias(uv.into()).expect_const()
+            }
+            ty::UnevaluatedConstKind::Anon { .. } => {
                 let ct = ct.super_fold_with(self);
                 super::with_replaced_escaping_bound_vars(
                     self.selcx.infcx,
@@ -493,9 +486,6 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
                     |ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env),
                 )
             }
-            kind => {
-                unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind)
-            }
         };
 
         // We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 900d55c..46c1c8e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -469,7 +469,7 @@ fn normalize_to_error<'a, 'tcx>(
         | ty::AliasTermKind::FreeTy { .. } => selcx.infcx.next_ty_var(cause.span).into(),
         ty::AliasTermKind::FreeConst { .. }
         | ty::AliasTermKind::InherentConst { .. }
-        | ty::AliasTermKind::UnevaluatedConst { .. }
+        | ty::AliasTermKind::AnonConst { .. }
         | ty::AliasTermKind::ProjectionConst { .. } => {
             selcx.infcx.next_const_var(cause.span).into()
         }
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index e8c5d10..5b1f2e3 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -4,7 +4,6 @@
 
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir::def::DefKind;
 use rustc_infer::traits::PredicateObligations;
 use rustc_macros::extension;
 pub use rustc_middle::traits::query::NormalizationResult;
@@ -278,16 +277,16 @@ fn try_fold_const(
             _ => return constant.try_super_fold_with(self),
         };
 
-        let constant = match self.cx().def_kind(uv.def) {
-            DefKind::AnonConst => crate::traits::with_replaced_escaping_bound_vars(
-                self.infcx,
-                &mut self.universes,
-                constant,
-                |constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env),
-            ),
-            _ => self
-                .try_fold_free_or_assoc(ty::AliasTerm::from_unevaluated_const(self.cx(), uv))?
-                .expect_const(),
+        let constant = match uv.kind {
+            ty::UnevaluatedConstKind::Anon { .. } => {
+                crate::traits::with_replaced_escaping_bound_vars(
+                    self.infcx,
+                    &mut self.universes,
+                    constant,
+                    |constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env),
+                )
+            }
+            _ => self.try_fold_free_or_assoc(uv.into())?.expect_const(),
         };
         debug!(?constant, ?self.param_env);
         constant.try_super_fold_with(self)
@@ -338,8 +337,7 @@ fn try_fold_free_or_assoc(
             ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => {
                 tcx.normalize_canonicalized_inherent_projection(c_term)
             }
-            kind @ (ty::AliasTermKind::OpaqueTy { .. }
-            | ty::AliasTermKind::UnevaluatedConst { .. }) => {
+            kind @ (ty::AliasTermKind::OpaqueTy { .. } | ty::AliasTermKind::AnonConst { .. }) => {
                 unreachable!("did not expect {kind:?} due to match arm above")
             }
         }?;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index eadc937..6900024 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -881,13 +881,13 @@ fn evaluate_predicate_recursively<'o>(
                             c1, c2
                         );
 
-                        use rustc_hir::def::DefKind;
                         match (c1.kind(), c2.kind()) {
                             (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
-                                if a.def == b.def
+                                if a.kind == b.kind
                                     && matches!(
-                                        tcx.def_kind(a.def),
-                                        DefKind::AssocConst { .. }
+                                        a.kind,
+                                        ty::UnevaluatedConstKind::Projection { .. }
+                                            | ty::UnevaluatedConstKind::Inherent { .. }
                                     ) =>
                             {
                                 if let Ok(InferOk { obligations, value: () }) = self
@@ -897,8 +897,8 @@ fn evaluate_predicate_recursively<'o>(
                                     // `generic_const_exprs`
                                     .eq(
                                         DefineOpaqueTypes::Yes,
-                                        ty::AliasTerm::from_unevaluated_const(tcx, a),
-                                        ty::AliasTerm::from_unevaluated_const(tcx, b),
+                                        ty::AliasTerm::from(a),
+                                        ty::AliasTerm::from(b),
                                     )
                                 {
                                     return self.evaluate_predicates_recursively(
@@ -989,7 +989,7 @@ fn evaluate_predicate_recursively<'o>(
                         ty::ConstKind::Value(cv) => cv.ty,
                         ty::ConstKind::Unevaluated(uv) => self
                             .tcx()
-                            .type_of(uv.def)
+                            .type_of(uv.kind.def_id())
                             .instantiate(self.tcx(), uv.args)
                             .skip_norm_wip(),
                         // FIXME(generic_const_exprs): See comment in `fulfill.rs`
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index fe00e9b..03edfeb 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -41,7 +41,7 @@ fn structurally_normalize_term<E: 'tcx>(
 
         if self.infcx.next_trait_solver() {
             let term = term.skip_normalization();
-            if let None = term.to_alias_term(self.infcx.tcx) {
+            if let None = term.to_alias_term() {
                 return Ok(term);
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index fdf32d3..a2143a7 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -6,7 +6,6 @@
 use std::iter;
 
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
 use rustc_middle::bug;
@@ -1065,7 +1064,8 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
             ty::ConstKind::Unevaluated(uv) => {
                 if !c.has_escaping_bound_vars() {
                     // Skip type consts as mGCA doesn't support evaluatable clauses
-                    if !tcx.is_type_const(uv.def) && !tcx.features().generic_const_args() {
+                    if !tcx.is_type_const(uv.kind.def_id()) && !tcx.features().generic_const_args()
+                    {
                         let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
                             ty::ClauseKind::ConstEvaluatable(c),
                         ));
@@ -1079,15 +1079,11 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
                         ));
                     }
 
-                    if matches!(tcx.def_kind(uv.def), DefKind::AssocConst { .. })
-                        && tcx.def_kind(tcx.parent(uv.def)) == (DefKind::Impl { of_trait: false })
-                    {
-                        self.add_wf_preds_for_inherent_projection(
-                            ty::AliasTerm::from_unevaluated_const(tcx, uv),
-                        );
+                    if matches!(uv.kind, ty::UnevaluatedConstKind::Inherent { .. }) {
+                        self.add_wf_preds_for_inherent_projection(uv.into());
                         return; // Subtree is handled by above function
                     } else {
-                        let obligations = self.nominal_obligations(uv.def, uv.args);
+                        let obligations = self.nominal_obligations(uv.kind.def_id(), uv.args);
                         self.out.extend(obligations);
                     }
                 }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index b63baa7..d7aeb6b 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -421,12 +421,12 @@ fn from_enum(
                 )
             };
 
-            match layout.variants() {
+            match *layout.variants() {
                 Variants::Empty => Ok(Self::uninhabited()),
                 Variants::Single { index } => {
                     // `Variants::Single` on enums with variants denotes that
                     // the enum delegates its layout to the variant at `index`.
-                    layout_of_variant(*index, None)
+                    layout_of_variant(index, None)
                 }
                 Variants::Multiple { tag: _, tag_encoding, tag_field, .. } => {
                     // `Variants::Multiple` denotes an enum with multiple
@@ -435,12 +435,12 @@ fn from_enum(
 
                     // For enums (but not coroutines), the tag field is
                     // currently always the first field of the layout.
-                    assert_eq!(*tag_field, FieldIdx::ZERO);
+                    assert_eq!(tag_field, FieldIdx::ZERO);
 
                     let variants = def.discriminants(cx.tcx()).try_fold(
                         Self::uninhabited(),
                         |variants, (idx, _discriminant)| {
-                            let variant = layout_of_variant(idx, Some(tag_encoding.clone()))?;
+                            let variant = layout_of_variant(idx, Some(tag_encoding))?;
                             Result::<Self, Err>::Ok(variants.or(variant))
                         },
                     )?;
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 24415c5..b459582 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -70,7 +70,11 @@ fn recurse_build<'tcx>(
         }
         &ExprKind::ZstLiteral { user_ty: _ } => ty::Const::zero_sized(tcx, node.ty),
         &ExprKind::NamedConst { def_id, args, user_ty: _ } => {
-            let uneval = ty::UnevaluatedConst::new(def_id, args);
+            let uneval = ty::UnevaluatedConst::new(
+                tcx,
+                ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id),
+                args,
+            );
             ty::Const::new_unevaluated(tcx, uneval)
         }
         ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param),
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 4017aab..0a13dd5 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -75,16 +75,63 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
 )]
 pub struct UnevaluatedConst<I: Interner> {
-    pub def: I::UnevaluatedConstId,
+    #[type_foldable(identity)]
+    #[type_visitable(ignore)]
+    pub kind: UnevaluatedConstKind<I>,
     pub args: I::GenericArgs,
+
+    /// This field exists to prevent the creation of `UnevaluatedConst` without using [`UnevaluatedConst::new`].
+    #[derive_where(skip(Debug))]
+    pub(crate) _use_unevaluated_const_new_instead: (),
 }
 
 impl<I: Interner> Eq for UnevaluatedConst<I> {}
 
 impl<I: Interner> UnevaluatedConst<I> {
     #[inline]
-    pub fn new(def: I::UnevaluatedConstId, args: I::GenericArgs) -> UnevaluatedConst<I> {
-        UnevaluatedConst { def, args }
+    pub fn new(
+        interner: I,
+        kind: UnevaluatedConstKind<I>,
+        args: I::GenericArgs,
+    ) -> UnevaluatedConst<I> {
+        interner.debug_assert_args_compatible(kind.def_id(), args);
+        UnevaluatedConst { kind, args, _use_unevaluated_const_new_instead: () }
+    }
+}
+
+/// UnevaluatedConstKind is extremely similar to AliasTyKind, and likely should be reasoned about
+/// and handled in very similar ways. The documentation for AliasTyKind/etc. may be helpful when
+/// learning about UnevaluatedConstKind.
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
+#[derive(GenericTypeVisitable, Lift_Generic)]
+#[cfg_attr(
+    feature = "nightly",
+    derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
+)]
+pub enum UnevaluatedConstKind<I: Interner> {
+    /// A projection `<Type as Trait>::AssocConst`
+    Projection { def_id: I::TraitAssocConstId },
+    /// An associated constant in an inherent `impl`
+    Inherent { def_id: I::InherentAssocConstId },
+    /// A free constant, outside an impl block.
+    Free { def_id: I::FreeConstAliasId },
+    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`.
+    Anon { def_id: I::UnevaluatedConstId },
+}
+
+impl<I: Interner> UnevaluatedConstKind<I> {
+    pub fn new_from_def_id(interner: I, def_id: I::DefId) -> Self {
+        interner.unevaluated_const_kind_from_def_id(def_id)
+    }
+
+    pub fn def_id(self) -> I::DefId {
+        match self {
+            UnevaluatedConstKind::Projection { def_id } => def_id.into(),
+            UnevaluatedConstKind::Inherent { def_id } => def_id.into(),
+            UnevaluatedConstKind::Free { def_id } => def_id.into(),
+            UnevaluatedConstKind::Anon { def_id } => def_id.into(),
+            //UnevaluatedConstKind::Expr { def_id } => def_id.into(),
+        }
     }
 }
 
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 8859ab7..e0fe608 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -400,16 +400,14 @@ fn is_error(self) -> bool {
         }
     }
 
-    fn to_alias_term(self, interner: I) -> Option<ty::AliasTerm<I>> {
+    fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
         match self.kind() {
             ty::TermKind::Ty(ty) => match ty.kind() {
                 ty::Alias(alias_ty) => Some(alias_ty.into()),
                 _ => None,
             },
             ty::TermKind::Const(ct) => match ct.kind() {
-                ty::ConstKind::Unevaluated(uv) => {
-                    Some(ty::AliasTerm::from_unevaluated_const(interner, uv))
-                }
+                ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
                 _ => None,
             },
         }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 09def02..a4737cf 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -244,6 +244,11 @@ fn type_of_opaque_hir_typeck(
 
     fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> ty::AliasTyKind<Self>;
 
+    fn unevaluated_const_kind_from_def_id(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::UnevaluatedConstKind<Self>;
+
     // FIXME: remove in favor of explicit construction
     fn alias_term_kind_from_def_id(self, def_id: Self::DefId) -> ty::AliasTermKind<Self>;
 
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 301cf7d..59c5f69 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -12,7 +12,7 @@
 use crate::lift::Lift;
 use crate::upcast::{Upcast, UpcastFrom};
 use crate::visit::TypeVisitableExt as _;
-use crate::{self as ty, AliasTyKind, Interner};
+use crate::{self as ty, AliasTyKind, Interner, UnevaluatedConstKind};
 
 /// `A: 'region`
 #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)]
@@ -388,14 +388,13 @@ pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
     }
 }
 
-/// An existential reference to a trait, where `Self` is erased.
+/// An existential reference to a trait where the self type `Self` is erased.
 ///
-/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
+/// For example, the trait object type `Trait<'a, T, N>` can be understood as:
 /// ```ignore (illustrative)
-/// exists T. T: Trait<'a, 'b, X, Y>
+/// exists<X> X: Trait<'a, T, N>
 /// ```
-/// The generic parameters don't include the erased `Self`, only trait
-/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
+/// The generic arguments don't include the erased self type (so it's only `['a, T, N]`).
 #[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
@@ -438,13 +437,18 @@ pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef
         }
     }
 
-    /// Object types don't have a self type specified. Therefore, when
-    /// we convert the principal trait-ref into a normal trait-ref,
-    /// you must give *some* self type. A common choice is `mk_err()`
-    /// or some placeholder type.
+    /// Convert the *existential* trait ref into a normal one by providing a self type.
+    ///
+    /// Existential trait refs don't contain a self type, it's erased.
+    /// Therefore, you must specify *some* self type to perform the conversion.
+    /// A common choice is the trait object type itself or some kind of dummy type.
     pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
+        // FIXME(#157122): This assertion was accidentally commented out in refactoring PR #53816
+        //                 back in 2018 but nowadays it can actually trigger. Either remove this
+        //                 comment entirely if the assertion is incorrect or uncomment it and fix
+        //                 the fallout!
         // otherwise the escaping vars would be captured by the binder
-        // debug_assert!(!self_ty.has_escaping_bound_vars());
+        //debug_assert!(!self_ty.has_escaping_bound_vars());
 
         TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
     }
@@ -455,10 +459,9 @@ pub fn def_id(&self) -> I::TraitId {
         self.skip_binder().def_id
     }
 
-    /// Object types don't have a self type specified. Therefore, when
-    /// we convert the principal trait-ref into a normal trait-ref,
-    /// you must give *some* self type. A common choice is `mk_err()`
-    /// or some placeholder type.
+    /// Convert the *existential* polymorphic trait ref into a normal one by providing a self type.
+    ///
+    /// See also [`ExistentialTraitRef::with_self_ty`].
     pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
         self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty))
     }
@@ -594,7 +597,7 @@ pub enum AliasTermKind<I: Interner> {
     FreeTy { def_id: I::FreeTyAliasId },
 
     /// An unevaluated anonymous constants.
-    UnevaluatedConst { def_id: I::UnevaluatedConstId },
+    AnonConst { def_id: I::UnevaluatedConstId },
     /// An unevaluated const coming from an associated const.
     ProjectionConst { def_id: I::TraitAssocConstId },
     /// A top level const item not part of a trait or impl.
@@ -613,7 +616,7 @@ pub fn descr(self) -> &'static str {
             AliasTermKind::OpaqueTy { .. } => "opaque type",
             AliasTermKind::FreeTy { .. } => "type alias",
             AliasTermKind::FreeConst { .. } => "unevaluated constant",
-            AliasTermKind::UnevaluatedConst { .. } => "unevaluated constant",
+            AliasTermKind::AnonConst { .. } => "unevaluated constant",
         }
     }
 
@@ -624,7 +627,7 @@ pub fn is_type(self) -> bool {
             | AliasTermKind::OpaqueTy { .. }
             | AliasTermKind::FreeTy { .. } => true,
 
-            AliasTermKind::UnevaluatedConst { .. }
+            AliasTermKind::AnonConst { .. }
             | AliasTermKind::ProjectionConst { .. }
             | AliasTermKind::InherentConst { .. }
             | AliasTermKind::FreeConst { .. } => false,
@@ -638,7 +641,7 @@ pub fn def_id(self) -> I::DefId {
             AliasTermKind::InherentTy { def_id } => def_id.into(),
             AliasTermKind::OpaqueTy { def_id } => def_id.into(),
             AliasTermKind::FreeTy { def_id } => def_id.into(),
-            AliasTermKind::UnevaluatedConst { def_id } => def_id.into(),
+            AliasTermKind::AnonConst { def_id } => def_id.into(),
             AliasTermKind::ProjectionConst { def_id } => def_id.into(),
             AliasTermKind::FreeConst { def_id } => def_id.into(),
             AliasTermKind::InherentConst { def_id } => def_id.into(),
@@ -657,6 +660,21 @@ fn from(value: ty::AliasTyKind<I>) -> Self {
     }
 }
 
+impl<I: Interner> From<ty::UnevaluatedConstKind<I>> for AliasTermKind<I> {
+    fn from(value: ty::UnevaluatedConstKind<I>) -> Self {
+        match value {
+            ty::UnevaluatedConstKind::Projection { def_id } => {
+                AliasTermKind::ProjectionConst { def_id }
+            }
+            ty::UnevaluatedConstKind::Inherent { def_id } => {
+                AliasTermKind::InherentConst { def_id }
+            }
+            ty::UnevaluatedConstKind::Free { def_id } => AliasTermKind::FreeConst { def_id },
+            ty::UnevaluatedConstKind::Anon { def_id } => AliasTermKind::AnonConst { def_id },
+        }
+    }
+}
+
 /// Represents the unprojected term of a projection goal.
 ///
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
@@ -716,11 +734,6 @@ pub fn new_from_def_id(interner: I, def_id: I::DefId, args: I::GenericArgs) -> A
         Self::new_from_args(interner, kind, args)
     }
 
-    pub fn from_unevaluated_const(interner: I, ct: ty::UnevaluatedConst<I>) -> Self {
-        let kind = interner.alias_term_kind_from_def_id(ct.def.into());
-        AliasTerm::new_from_args(interner, kind, ct.args)
-    }
-
     pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
         let kind = match self.kind(interner) {
             AliasTermKind::ProjectionTy { def_id } => AliasTyKind::Projection { def_id },
@@ -729,7 +742,7 @@ pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
             AliasTermKind::FreeTy { def_id } => AliasTyKind::Free { def_id },
             kind @ (AliasTermKind::InherentConst { .. }
             | AliasTermKind::FreeConst { .. }
-            | AliasTermKind::UnevaluatedConst { .. }
+            | AliasTermKind::AnonConst { .. }
             | AliasTermKind::ProjectionConst { .. }) => {
                 panic!("Cannot turn `{}` into `AliasTy`", kind.descr())
             }
@@ -739,10 +752,12 @@ pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
 
     pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst<I> {
         let def = match self.kind(interner) {
-            AliasTermKind::InherentConst { def_id } => def_id.into(),
-            AliasTermKind::FreeConst { def_id } => def_id.into(),
-            AliasTermKind::UnevaluatedConst { def_id } => def_id,
-            AliasTermKind::ProjectionConst { def_id } => def_id.into(),
+            AliasTermKind::InherentConst { def_id } => UnevaluatedConstKind::Inherent { def_id },
+            AliasTermKind::FreeConst { def_id } => UnevaluatedConstKind::Free { def_id },
+            AliasTermKind::AnonConst { def_id } => UnevaluatedConstKind::Anon { def_id },
+            AliasTermKind::ProjectionConst { def_id } => {
+                UnevaluatedConstKind::Projection { def_id }
+            }
             kind @ (AliasTermKind::ProjectionTy { .. }
             | AliasTermKind::InherentTy { .. }
             | AliasTermKind::OpaqueTy { .. }
@@ -750,7 +765,7 @@ pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst<I> {
                 panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr())
             }
         };
-        ty::UnevaluatedConst { def, args: self.args }
+        ty::UnevaluatedConst::new(interner, def, self.args)
     }
 
     // FIXME: remove this function (access the field instead)
@@ -764,23 +779,34 @@ pub fn def_id(self) -> I::DefId {
     }
 
     pub fn to_term(self, interner: I) -> I::Term {
-        let unevaluated_const = |def_id| {
-            I::Const::new_unevaluated(interner, ty::UnevaluatedConst::new(def_id, self.args)).into()
+        let alias_ty = |kind| {
+            Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, kind, self.args)).into()
         };
-        let alias_ty_kind = match self.kind(interner) {
-            AliasTermKind::FreeConst { def_id } => return unevaluated_const(def_id.into()),
-            AliasTermKind::InherentConst { def_id } => return unevaluated_const(def_id.into()),
-            AliasTermKind::UnevaluatedConst { def_id } => return unevaluated_const(def_id),
-            AliasTermKind::ProjectionConst { def_id } => return unevaluated_const(def_id.into()),
-
-            AliasTermKind::ProjectionTy { def_id } => ty::Projection { def_id },
-            AliasTermKind::InherentTy { def_id } => ty::Inherent { def_id },
-            AliasTermKind::OpaqueTy { def_id } => ty::Opaque { def_id },
-            AliasTermKind::FreeTy { def_id } => ty::Free { def_id },
-        };
-
-        Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args))
+        let unevaluated_const = |kind| {
+            I::Const::new_unevaluated(
+                interner,
+                ty::UnevaluatedConst::new(interner, kind, self.args),
+            )
             .into()
+        };
+        match self.kind(interner) {
+            AliasTermKind::FreeConst { def_id } => {
+                unevaluated_const(UnevaluatedConstKind::Free { def_id })
+            }
+            AliasTermKind::InherentConst { def_id } => {
+                unevaluated_const(UnevaluatedConstKind::Inherent { def_id })
+            }
+            AliasTermKind::AnonConst { def_id } => {
+                unevaluated_const(UnevaluatedConstKind::Anon { def_id })
+            }
+            AliasTermKind::ProjectionConst { def_id } => {
+                unevaluated_const(UnevaluatedConstKind::Projection { def_id })
+            }
+            AliasTermKind::ProjectionTy { def_id } => alias_ty(ty::Projection { def_id }),
+            AliasTermKind::InherentTy { def_id } => alias_ty(ty::Inherent { def_id }),
+            AliasTermKind::OpaqueTy { def_id } => alias_ty(ty::Opaque { def_id }),
+            AliasTermKind::FreeTy { def_id } => alias_ty(ty::Free { def_id }),
+        }
     }
 
     pub fn with_args(self, interner: I, args: I::GenericArgs) -> Self {
@@ -809,7 +835,7 @@ fn projection_def_id(self) -> Option<I::TraitAssocTermId> {
             AliasTermKind::InherentTy { .. }
             | AliasTermKind::OpaqueTy { .. }
             | AliasTermKind::FreeTy { .. }
-            | AliasTermKind::UnevaluatedConst { .. }
+            | AliasTermKind::AnonConst { .. }
             | AliasTermKind::FreeConst { .. }
             | AliasTermKind::InherentConst { .. } => None,
         }
@@ -885,6 +911,16 @@ fn from(ty: ty::AliasTy<I>) -> Self {
     }
 }
 
+impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> {
+    fn from(ty: ty::UnevaluatedConst<I>) -> Self {
+        AliasTerm {
+            args: ty.args,
+            kind: AliasTermKind::from(ty.kind),
+            _use_alias_term_new_instead: (),
+        }
+    }
+}
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index 51de99e..d1c9a5c 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -251,7 +251,7 @@ fn relate<R: TypeRelation<I>>(
                 | ty::AliasTermKind::FreeTy { .. }
                 | ty::AliasTermKind::InherentTy { .. }
                 | ty::AliasTermKind::InherentConst { .. }
-                | ty::AliasTermKind::UnevaluatedConst { .. }
+                | ty::AliasTermKind::AnonConst { .. }
                 | ty::AliasTermKind::ProjectionConst { .. } => {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }
@@ -591,11 +591,11 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
         // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
         // and is the better alternative to waiting until `generic_const_exprs` can
         // be stabilized.
-        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
+        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.kind == bu.kind => {
             // FIXME(mgca): remove this
             if cfg!(debug_assertions) {
-                let a_ty = cx.type_of(au.def.into()).instantiate(cx, au.args).skip_norm_wip();
-                let b_ty = cx.type_of(bu.def.into()).instantiate(cx, bu.args).skip_norm_wip();
+                let a_ty = cx.type_of(au.kind.def_id()).instantiate(cx, au.args).skip_norm_wip();
+                let b_ty = cx.type_of(bu.kind.def_id()).instantiate(cx, bu.args).skip_norm_wip();
                 assert_eq!(a_ty, b_ty);
             }
 
@@ -605,7 +605,7 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
                 au.args,
                 bu.args,
             )?;
-            return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst { def: au.def, args }));
+            return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst::new(cx, au.kind, args)));
         }
         (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
             let expr = relation.relate(ae, be)?;
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 52f099e..8729e98 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -204,12 +204,12 @@ impl Global {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     fn alloc_impl_runtime(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
         match layout.size() {
-            0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
+            0 => Ok(layout.dangling_ptr().cast_slice(0)),
             // SAFETY: `layout` is non-zero in size,
             size => unsafe {
                 let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) };
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
-                Ok(NonNull::slice_from_raw_parts(ptr, size))
+                Ok(ptr.cast_slice(size))
             },
         }
     }
@@ -261,7 +261,7 @@ fn grow_impl_runtime(
                 if zeroed {
                     raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
                 }
-                Ok(NonNull::slice_from_raw_parts(ptr, new_size))
+                Ok(ptr.cast_slice(new_size))
             },
 
             // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
@@ -297,7 +297,7 @@ fn shrink_impl_runtime(
             // SAFETY: conditions must be upheld by the caller
             0 => unsafe {
                 self.deallocate(ptr, old_layout);
-                Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
+                Ok(new_layout.dangling_ptr().cast_slice(0))
             },
 
             // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
@@ -307,7 +307,7 @@ fn shrink_impl_runtime(
 
                 let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
-                Ok(NonNull::slice_from_raw_parts(ptr, new_size))
+                Ok(ptr.cast_slice(new_size))
             },
 
             // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
@@ -388,7 +388,7 @@ const fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     const fn alloc_impl_const(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
         match layout.size() {
-            0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
+            0 => Ok(layout.dangling_ptr().cast_slice(0)),
             // SAFETY: `layout` is non-zero in size,
             size => unsafe {
                 let raw_ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
@@ -397,7 +397,7 @@ const fn alloc_impl_const(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>,
                     // SAFETY: the pointer returned by `const_allocate` is valid to write to.
                     ptr.write_bytes(0, size);
                 }
-                Ok(NonNull::slice_from_raw_parts(ptr, size))
+                Ok(ptr.cast_slice(size))
             },
         }
     }
@@ -442,7 +442,7 @@ const fn grow_shrink_impl_const(
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
-unsafe impl const Allocator for Global {
+const unsafe impl Allocator for Global {
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs
index d11cf5a..2cc6b8e 100644
--- a/library/alloc/src/collections/mod.rs
+++ b/library/alloc/src/collections/mod.rs
@@ -129,7 +129,7 @@ pub enum TryReserveErrorKind {
 )]
 #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
 #[cfg(not(test))]
-impl const Clone for TryReserveErrorKind {
+const impl Clone for TryReserveErrorKind {
     fn clone(&self) -> Self {
         match self {
             TryReserveErrorKind::CapacityOverflow => TryReserveErrorKind::CapacityOverflow,
@@ -150,7 +150,7 @@ fn clone(&self) -> Self {
 )]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 #[cfg(not(test))]
-impl const From<TryReserveErrorKind> for TryReserveError {
+const impl From<TryReserveErrorKind> for TryReserveError {
     #[inline]
     fn from(kind: TryReserveErrorKind) -> Self {
         Self { kind }
@@ -160,7 +160,7 @@ fn from(kind: TryReserveErrorKind) -> Self {
 #[unstable(feature = "try_reserve_kind", issue = "48043")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 #[cfg(not(test))]
-impl const From<LayoutError> for TryReserveErrorKind {
+const impl From<LayoutError> for TryReserveErrorKind {
     /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`].
     #[inline]
     fn from(_: LayoutError) -> Self {
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index d91b35c..5a900db 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -226,9 +226,7 @@ unsafe fn buffer_write(&mut self, off: WrappedIndex, value: T) -> &mut T {
     /// `range` must lie inside `0..self.capacity()`.
     #[inline]
     unsafe fn buffer_range(&self, range: Range<usize>) -> *mut [T] {
-        unsafe {
-            ptr::slice_from_raw_parts_mut(self.ptr().add(range.start), range.end - range.start)
-        }
+        unsafe { self.ptr().add(range.start).cast_slice(range.end - range.start) }
     }
 
     /// Returns `true` if the buffer is at full capacity.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 5fe5464..f66dc64 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -73,6 +73,7 @@
 // Lints:
 #![deny(unsafe_op_in_unsafe_fn)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 #![warn(deprecated_in_future)]
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
@@ -140,6 +141,7 @@
 #![feature(pattern)]
 #![feature(pin_coerce_unsized_trait)]
 #![feature(ptr_alignment_type)]
+#![feature(ptr_cast_slice)]
 #![feature(ptr_internals)]
 #![feature(ptr_metadata)]
 #![feature(rev_into_inner)]
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index 0309d63c..2f7d26c 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -244,7 +244,7 @@ pub(crate) unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>], A> {
 
         let me = ManuallyDrop::new(self);
         unsafe {
-            let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
+            let slice = me.ptr().cast::<MaybeUninit<T>>().cast_slice(len);
             Box::from_raw_in(slice, ptr::read(&me.inner.alloc))
         }
     }
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 2491489..523c9b8 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1160,10 +1160,7 @@ pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
             Rc::from_ptr(Rc::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| Global.allocate_zeroed(layout),
-                |mem| {
-                    ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len)
-                        as *mut RcInner<[mem::MaybeUninit<T>]>
-                },
+                |mem| mem.cast::<T>().cast_slice(len) as *mut RcInner<[mem::MaybeUninit<T>]>,
             ))
         }
     }
@@ -1231,10 +1228,7 @@ pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit<T>], A>
                 Rc::allocate_for_layout(
                     Layout::array::<T>(len).unwrap(),
                     |layout| alloc.allocate_zeroed(layout),
-                    |mem| {
-                        ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len)
-                            as *mut RcInner<[mem::MaybeUninit<T>]>
-                    },
+                    |mem| mem.cast::<T>().cast_slice(len) as *mut RcInner<[mem::MaybeUninit<T>]>,
                 ),
                 alloc,
             )
@@ -2327,7 +2321,7 @@ unsafe fn allocate_for_slice(len: usize) -> *mut RcInner<[T]> {
             Self::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| Global.allocate(layout),
-                |mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcInner<[T]>,
+                |mem| mem.cast::<T>().cast_slice(len) as *mut RcInner<[T]>,
             )
         }
     }
@@ -2404,7 +2398,7 @@ unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcInner<[T]> {
             Rc::<[T]>::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| alloc.allocate(layout),
-                |mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcInner<[T]>,
+                |mem| mem.cast::<T>().cast_slice(len) as *mut RcInner<[T]>,
             )
         }
     }
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 1d9a434..7c6befa 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2710,7 +2710,7 @@ fn ne(&self, other: &$lhs) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for String {
+const impl Default for String {
     /// Creates an empty `String`.
     #[inline]
     fn default() -> String {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 597d26d..4a9878d 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1306,10 +1306,7 @@ pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
             Arc::from_ptr(Arc::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| Global.allocate_zeroed(layout),
-                |mem| {
-                    ptr::slice_from_raw_parts_mut(mem as *mut T, len)
-                        as *mut ArcInner<[mem::MaybeUninit<T>]>
-                },
+                |mem| mem.cast::<T>().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit<T>]>,
             ))
         }
     }
@@ -1378,10 +1375,7 @@ pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit<T>], A
                 Arc::allocate_for_layout(
                     Layout::array::<T>(len).unwrap(),
                     |layout| alloc.allocate_zeroed(layout),
-                    |mem| {
-                        ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len)
-                            as *mut ArcInner<[mem::MaybeUninit<T>]>
-                    },
+                    |mem| mem.cast::<T>().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit<T>]>,
                 ),
                 alloc,
             )
@@ -2272,7 +2266,7 @@ unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> {
             Self::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| Global.allocate(layout),
-                |mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut ArcInner<[T]>,
+                |mem| mem.cast::<T>().cast_slice(len) as *mut ArcInner<[T]>,
             )
         }
     }
@@ -2351,7 +2345,7 @@ unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut ArcInner<[T]> {
             Arc::allocate_for_layout(
                 Layout::array::<T>(len).unwrap(),
                 |layout| alloc.allocate(layout),
-                |mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut ArcInner<[T]>,
+                |mem| mem.cast::<T>().cast_slice(len) as *mut ArcInner<[T]>,
             )
         }
     }
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index 9a6bfa8..d12dea2 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -232,7 +232,7 @@ fn drop(&mut self) {
             // invalidate raw pointers to it which some unsafe code might rely on.
             let vec_ptr = vec.as_mut().as_mut_ptr();
             let drop_offset = drop_ptr.offset_from_unsigned(vec_ptr);
-            let to_drop = ptr::slice_from_raw_parts_mut(vec_ptr.add(drop_offset), drop_len);
+            let to_drop = vec_ptr.add(drop_offset).cast_slice(drop_len);
             ptr::drop_in_place(to_drop);
         }
     }
diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs
index c8cc758..5c3d598 100644
--- a/library/alloc/src/vec/in_place_drop.rs
+++ b/library/alloc/src/vec/in_place_drop.rs
@@ -1,5 +1,5 @@
 use core::marker::PhantomData;
-use core::ptr::{self, NonNull, drop_in_place};
+use core::ptr::NonNull;
 
 use crate::alloc::Global;
 use crate::raw_vec::RawVec;
@@ -20,9 +20,7 @@ fn len(&self) -> usize {
 impl<T> Drop for InPlaceDrop<T> {
     #[inline]
     fn drop(&mut self) {
-        unsafe {
-            ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.inner, self.len()));
-        }
+        unsafe { self.inner.cast_slice(self.len()).drop_in_place() }
     }
 }
 
@@ -42,7 +40,7 @@ fn drop(&mut self) {
         unsafe {
             let _drop_allocation =
                 RawVec::<Src>::from_nonnull_in(self.ptr.cast::<Src>(), self.src_cap, Global);
-            drop_in_place(core::ptr::slice_from_raw_parts_mut::<Dest>(self.ptr.as_ptr(), self.len));
+            self.ptr.as_ptr().cast_slice(self.len).drop_in_place();
         };
     }
 }
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 9c4b24b..97e4912 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -115,7 +115,7 @@ pub fn allocator(&self) -> &A {
     }
 
     fn as_raw_mut_slice(&mut self) -> *mut [T] {
-        ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len())
+        self.ptr.as_ptr().cast_slice(self.len())
     }
 
     /// Drops remaining elements and relinquishes the backing allocation.
@@ -282,7 +282,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     #[inline]
     fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         let step_size = self.len().min(n);
-        let to_drop = ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), step_size);
+        let to_drop = self.ptr.as_ptr().cast_slice(step_size);
         if T::IS_ZST {
             // See `next` for why we sub `end` here.
             self.end = self.end.wrapping_byte_sub(step_size);
@@ -457,9 +457,9 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         }
         let to_drop = if T::IS_ZST {
             // ZST may cause unalignment
-            ptr::slice_from_raw_parts_mut(ptr::NonNull::<T>::dangling().as_ptr(), step_size)
+            ptr::NonNull::<T>::dangling().as_ptr().cast_slice(step_size)
         } else {
-            ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size)
+            self.end.cast::<T>().cast_mut().cast_slice(step_size)
         };
         // SAFETY: same as for advance_by()
         unsafe {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index d2b7837..197b28d 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1830,7 +1830,7 @@ pub fn truncate(&mut self, len: usize) {
                 return;
             }
             let remaining_len = self.len - len;
-            let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
+            let s = self.as_mut_ptr().add(len).cast_slice(remaining_len);
             self.len = len;
             ptr::drop_in_place(s);
         }
@@ -3786,7 +3786,7 @@ unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, A: Allocator> const ops::Deref for Vec<T, A> {
+const impl<T, A: Allocator> ops::Deref for Vec<T, A> {
     type Target = [T];
 
     #[inline]
@@ -3797,7 +3797,7 @@ fn deref(&self) -> &[T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, A: Allocator> const ops::DerefMut for Vec<T, A> {
+const impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
     #[inline]
     fn deref_mut(&mut self) -> &mut [T] {
         self.as_mut_slice()
@@ -3863,7 +3863,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I: [const] SliceIndex<[T]>, A: Allocator> const Index<I> for Vec<T, A> {
+const impl<T, I: [const] SliceIndex<[T]>, A: Allocator> Index<I> for Vec<T, A> {
     type Output = I::Output;
 
     #[inline]
@@ -3874,7 +3874,7 @@ fn index(&self, index: I) -> &Self::Output {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I: [const] SliceIndex<[T]>, A: Allocator> const IndexMut<I> for Vec<T, A> {
+const impl<T, I: [const] SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut Self::Output {
         IndexMut::index_mut(&mut **self, index)
@@ -4289,7 +4289,7 @@ fn drop(&mut self) {
             // use drop for [T]
             // use a raw slice to refer to the elements of the vector as weakest necessary type;
             // could avoid questions of validity in certain cases
-            ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len))
+            self.as_mut_ptr().cast_slice(self.len).drop_in_place()
         }
         // RawVec handles deallocation
     }
@@ -4297,7 +4297,7 @@ fn drop(&mut self) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for Vec<T> {
+const impl<T> Default for Vec<T> {
     /// Creates an empty `Vec<T>`.
     ///
     /// The vector will not allocate until elements are pushed onto it.
diff --git a/library/alloctests/benches/lib.rs b/library/alloctests/benches/lib.rs
index b7e09fc2e..2be7a24 100644
--- a/library/alloctests/benches/lib.rs
+++ b/library/alloctests/benches/lib.rs
@@ -7,6 +7,7 @@
 #![feature(strict_provenance_lints)]
 #![feature(test)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 
 extern crate test;
 
diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs
index 936d60f..db643cc 100644
--- a/library/alloctests/lib.rs
+++ b/library/alloctests/lib.rs
@@ -36,6 +36,7 @@
 #![feature(iter_next_chunk)]
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(ptr_alignment_type)]
+#![feature(ptr_cast_slice)]
 #![feature(ptr_internals)]
 #![feature(rev_into_inner)]
 #![feature(sized_type_properties)]
diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs
index a562041..4b4d178 100644
--- a/library/alloctests/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
@@ -107,7 +107,7 @@ fn eq(&self, other: &TestEq<T>) -> bool {
 fn eq_unsized_slice() {
     let a: Arc<[()]> = Arc::new([(); 3]);
     let ptr: *const () = Arc::into_raw(a.clone()).cast();
-    let b: Arc<[()]> = unsafe { Arc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
+    let b: Arc<[()]> = unsafe { Arc::from_raw(ptr.cast_slice(42)) };
     assert!(a == a);
     assert!(!(a != a));
     assert!(a != b);
diff --git a/library/alloctests/tests/boxed.rs b/library/alloctests/tests/boxed.rs
index 83fd1ef..c73b710 100644
--- a/library/alloctests/tests/boxed.rs
+++ b/library/alloctests/tests/boxed.rs
@@ -47,9 +47,9 @@ fn box_clone_from_ptr_stability() {
     for size in (0..8).map(|i| 2usize.pow(i)) {
         let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
         let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
-        let copy_raw = copy.as_ptr() as usize;
+        let copy_raw = copy.as_ptr();
         copy.clone_from(&control);
-        assert_eq!(copy.as_ptr() as usize, copy_raw);
+        assert_eq!(copy.as_ptr(), copy_raw);
     }
 }
 
@@ -104,7 +104,7 @@ fn drop(&mut self) {
 unsafe impl Allocator for ConstAllocator {
     fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
         match layout.size() {
-            0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
+            0 => Ok(layout.dangling_ptr().cast_slice(0)),
             _ => unsafe {
                 let ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
                 Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8]))
diff --git a/library/alloctests/tests/heap.rs b/library/alloctests/tests/heap.rs
index 246b341..8eb5626 100644
--- a/library/alloctests/tests/heap.rs
+++ b/library/alloctests/tests/heap.rs
@@ -25,7 +25,7 @@ fn check_overalign_requests<T: Allocator>(allocator: T) {
                     .collect();
                 for &ptr in &pointers {
                     assert_eq!(
-                        (ptr.as_non_null_ptr().as_ptr() as usize) % align,
+                        ptr.as_non_null_ptr().as_ptr().addr() % align,
                         0,
                         "Got a pointer less aligned than requested"
                     )
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index 699a501..b7c3e39 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -41,8 +41,10 @@
 #![feature(macro_metavar_expr_concat)]
 #![feature(vec_peek_mut)]
 #![feature(vec_try_remove)]
+#![feature(ptr_cast_slice)]
 #![allow(internal_features)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate alloc;
diff --git a/library/alloctests/tests/rc.rs b/library/alloctests/tests/rc.rs
index 5be0e8f..0417206 100644
--- a/library/alloctests/tests/rc.rs
+++ b/library/alloctests/tests/rc.rs
@@ -108,7 +108,7 @@ fn eq(&self, other: &TestEq<T>) -> bool {
 fn eq_unsized_slice() {
     let a: Rc<[()]> = Rc::new([(); 3]);
     let ptr: *const () = Rc::into_raw(a.clone()).cast();
-    let b: Rc<[()]> = unsafe { Rc::from_raw(core::ptr::slice_from_raw_parts(ptr, 42)) };
+    let b: Rc<[()]> = unsafe { Rc::from_raw(ptr.cast_slice(42)) };
     assert!(a == a);
     assert!(!(a != a));
     assert!(a != b);
diff --git a/library/alloctests/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs
index 09b7677..ec4c4fa 100644
--- a/library/alloctests/tests/sort/tests.rs
+++ b/library/alloctests/tests/sort/tests.rs
@@ -746,7 +746,7 @@ fn self_cmp<T: Ord + Clone + Debug, S: Sort>(
         pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::<Vec<_>>();
 
     let comparison_fn = |a: &T, b: &T| {
-        assert_ne!(a as *const T as usize, b as *const T as usize);
+        assert_ne!(a as *const T, b as *const T);
         a.cmp(b)
     };
 
diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs
index d85d2e4..ccf9b80 100644
--- a/library/alloctests/tests/vec.rs
+++ b/library/alloctests/tests/vec.rs
@@ -1110,7 +1110,7 @@ fn test_into_iter_zst() {
     struct AlignedZstWithDrop([u64; 0]);
     impl Drop for AlignedZstWithDrop {
         fn drop(&mut self) {
-            let addr = self as *mut _ as usize;
+            let addr = (self as *mut Self).addr();
             assert!(hint::black_box(addr) % align_of::<u64>() == 0);
         }
     }
@@ -1356,10 +1356,10 @@ fn overaligned_allocations() {
     for i in 0..0x1000 {
         v.reserve_exact(i);
         assert!(v[0].0 == 273);
-        assert!(v.as_ptr() as usize & 0xff == 0);
+        assert!(v.as_ptr().addr() & 0xff == 0);
         v.shrink_to_fit();
         assert!(v[0].0 == 273);
-        assert!(v.as_ptr() as usize & 0xff == 0);
+        assert!(v.as_ptr().addr() & 0xff == 0);
     }
 }
 
@@ -2569,12 +2569,12 @@ fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
             } else {
                 unsafe { std::alloc::alloc(layout) }
             };
-            Ok(NonNull::slice_from_raw_parts(NonNull::new(ptr).ok_or(AllocError)?, layout.size()))
+            Ok(NonNull::new(ptr).ok_or(AllocError)?.cast_slice(layout.size()))
         }
 
         unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
             if layout.size() == 0 {
-                let addr = ptr.as_ptr() as usize;
+                let addr = ptr.as_ptr().addr();
                 let mut state = self.state.borrow_mut();
                 std::println!("freeing {addr}");
                 assert!(state.0.remove(&addr), "ZST free that wasn't allocated");
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 18310cf..102fb19 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -377,7 +377,7 @@ fn by_ref(&self) -> &Self
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
-unsafe impl<A> const Allocator for &A
+const unsafe impl<A> Allocator for &A
 where
     A: [const] Allocator + ?Sized,
 {
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index fc5f60e..862f01e 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -739,7 +739,7 @@ unsafe impl Sync for TypeId {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialEq for TypeId {
+const impl PartialEq for TypeId {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
         crate::intrinsics::type_id_eq(*self, *other)
diff --git a/library/core/src/array/drain.rs b/library/core/src/array/drain.rs
index 329b0e1..96a5a31 100644
--- a/library/core/src/array/drain.rs
+++ b/library/core/src/array/drain.rs
@@ -52,7 +52,7 @@ pub(super) struct Drain<'l, 'f, T, F> {
 
 #[rustc_const_unstable(feature = "array_try_map", issue = "79711")]
 #[unstable(feature = "array_try_map", issue = "79711")]
-impl<T, U, F> const FnOnce<(usize,)> for &mut Drain<'_, '_, T, F>
+const impl<T, U, F> FnOnce<(usize,)> for &mut Drain<'_, '_, T, F>
 where
     F: [const] FnMut(T) -> U,
 {
@@ -65,7 +65,7 @@ extern "rust-call" fn call_once(mut self, args: (usize,)) -> Self::Output {
 }
 #[rustc_const_unstable(feature = "array_try_map", issue = "79711")]
 #[unstable(feature = "array_try_map", issue = "79711")]
-impl<T, U, F> const FnMut<(usize,)> for &mut Drain<'_, '_, T, F>
+const impl<T, U, F> FnMut<(usize,)> for &mut Drain<'_, '_, T, F>
 where
     F: [const] FnMut(T) -> U,
 {
@@ -100,7 +100,7 @@ extern "rust-call" fn call_mut(
 }
 #[rustc_const_unstable(feature = "array_try_map", issue = "79711")]
 #[unstable(feature = "array_try_map", issue = "79711")]
-impl<T: [const] Destruct, F> const Drop for Drain<'_, '_, T, F> {
+const impl<T: [const] Destruct, F> Drop for Drain<'_, '_, T, F> {
     fn drop(&mut self) {
         let slice = if T::IS_ZST {
             from_raw_parts_mut::<[T]>(
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs
index ec79a65..d4692ca 100644
--- a/library/core/src/array/equality.rs
+++ b/library/core/src/array/equality.rs
@@ -2,7 +2,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<[U; N]> for [T; N]
+const impl<T, U, const N: usize> PartialEq<[U; N]> for [T; N]
 where
     T: [const] PartialEq<U>,
 {
@@ -18,7 +18,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<[U]> for [T; N]
+const impl<T, U, const N: usize> PartialEq<[U]> for [T; N]
 where
     T: [const] PartialEq<U>,
 {
@@ -40,7 +40,7 @@ fn ne(&self, other: &[U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<[U; N]> for [T]
+const impl<T, U, const N: usize> PartialEq<[U; N]> for [T]
 where
     T: [const] PartialEq<U>,
 {
@@ -62,7 +62,7 @@ fn ne(&self, other: &[U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<&[U]> for [T; N]
+const impl<T, U, const N: usize> PartialEq<&[U]> for [T; N]
 where
     T: [const] PartialEq<U>,
 {
@@ -78,7 +78,7 @@ fn ne(&self, other: &&[U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<[U; N]> for &[T]
+const impl<T, U, const N: usize> PartialEq<[U; N]> for &[T]
 where
     T: [const] PartialEq<U>,
 {
@@ -94,7 +94,7 @@ fn ne(&self, other: &&[U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<&mut [U]> for [T; N]
+const impl<T, U, const N: usize> PartialEq<&mut [U]> for [T; N]
 where
     T: [const] PartialEq<U>,
 {
@@ -110,7 +110,7 @@ fn ne(&self, other: &&mut [U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U, const N: usize> const PartialEq<[U; N]> for &mut [T]
+const impl<T, U, const N: usize> PartialEq<[U; N]> for &mut [T]
 where
     T: [const] PartialEq<U>,
 {
@@ -130,7 +130,7 @@ fn ne(&self, other: &&mut [U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Eq, const N: usize> const Eq for [T; N] {}
+const impl<T: [const] Eq, const N: usize> Eq for [T; N] {}
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
 const trait SpecArrayEq<Other, const N: usize>: Sized {
@@ -139,7 +139,7 @@ const trait SpecArrayEq<Other, const N: usize>: Sized {
 }
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialEq<Other>, Other, const N: usize> const SpecArrayEq<Other, N> for T {
+const impl<T: [const] PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
     default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool {
         a[..] == b[..]
     }
@@ -149,7 +149,7 @@ impl<T: [const] PartialEq<Other>, Other, const N: usize> const SpecArrayEq<Other
 }
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] BytewiseEq<U>, U, const N: usize> const SpecArrayEq<U, N> for T {
+const impl<T: [const] BytewiseEq<U>, U, const N: usize> SpecArrayEq<U, N> for T {
     fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
         // SAFETY: Arrays are compared element-wise, and don't add any padding
         // between elements, so when the elements are `BytewiseEq`, we can
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 56f188c..5784dbe 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -195,7 +195,7 @@ impl Error for TryFromSliceError {}
 
 #[stable(feature = "try_from_slice_error", since = "1.36.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Infallible> for TryFromSliceError {
+const impl From<Infallible> for TryFromSliceError {
     fn from(x: Infallible) -> TryFromSliceError {
         match x {}
     }
@@ -203,7 +203,7 @@ fn from(x: Infallible) -> TryFromSliceError {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const AsRef<[T]> for [T; N] {
+const impl<T, const N: usize> AsRef<[T]> for [T; N] {
     #[inline]
     fn as_ref(&self) -> &[T] {
         &self[..]
@@ -212,7 +212,7 @@ fn as_ref(&self) -> &[T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const AsMut<[T]> for [T; N] {
+const impl<T, const N: usize> AsMut<[T]> for [T; N] {
     #[inline]
     fn as_mut(&mut self) -> &mut [T] {
         &mut self[..]
@@ -221,7 +221,7 @@ fn as_mut(&mut self) -> &mut [T] {
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const Borrow<[T]> for [T; N] {
+const impl<T, const N: usize> Borrow<[T]> for [T; N] {
     fn borrow(&self) -> &[T] {
         self
     }
@@ -229,7 +229,7 @@ fn borrow(&self) -> &[T] {
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
+const impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
     fn borrow_mut(&mut self) -> &mut [T] {
         self
     }
@@ -249,7 +249,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const TryFrom<&[T]> for [T; N]
+const impl<T, const N: usize> TryFrom<&[T]> for [T; N]
 where
     T: Copy,
 {
@@ -275,7 +275,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 /// ```
 #[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, const N: usize> const TryFrom<&mut [T]> for [T; N]
+const impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
 where
     T: Copy,
 {
@@ -301,7 +301,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a, T, const N: usize> const TryFrom<&'a [T]> for &'a [T; N] {
+const impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
     type Error = TryFromSliceError;
 
     #[inline]
@@ -324,7 +324,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 /// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a, T, const N: usize> const TryFrom<&'a mut [T]> for &'a mut [T; N] {
+const impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
     type Error = TryFromSliceError;
 
     #[inline]
@@ -380,7 +380,7 @@ fn into_iter(self) -> IterMut<'a, T> {
 
 #[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I, const N: usize> const Index<I> for [T; N]
+const impl<T, I, const N: usize> Index<I> for [T; N]
 where
     [T]: [const] Index<I>,
 {
@@ -394,7 +394,7 @@ fn index(&self, index: I) -> &Self::Output {
 
 #[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I, const N: usize> const IndexMut<I> for [T; N]
+const impl<T, I, const N: usize> IndexMut<I> for [T; N]
 where
     [T]: [const] IndexMut<I>,
 {
@@ -407,7 +407,7 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
 /// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialOrd, const N: usize> const PartialOrd for [T; N] {
+const impl<T: [const] PartialOrd, const N: usize> PartialOrd for [T; N] {
     #[inline]
     fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
         PartialOrd::partial_cmp(&&self[..], &&other[..])
@@ -433,7 +433,7 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
 /// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Ord, const N: usize> const Ord for [T; N] {
+const impl<T: [const] Ord, const N: usize> Ord for [T; N] {
     #[inline]
     fn cmp(&self, other: &[T; N]) -> Ordering {
         Ord::cmp(&&self[..], &&other[..])
@@ -958,7 +958,7 @@ impl<T> Guard<'_, T> {
 }
 
 #[rustc_const_unstable(feature = "array_try_from_fn", issue = "89379")]
-impl<T: [const] Destruct> const Drop for Guard<'_, T> {
+const impl<T: [const] Destruct> Drop for Guard<'_, T> {
     #[inline]
     fn drop(&mut self) {
         debug_assert!(self.initialized <= self.array_mut.len());
@@ -993,7 +993,7 @@ pub(crate) const trait SpecNextChunk<T, const N: usize>: Iterator<Item = T> {
     fn spec_next_chunk(&mut self) -> Result<[T; N], IntoIter<T, N>>;
 }
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<I: [const] Iterator<Item = T>, T, const N: usize> const SpecNextChunk<T, N> for I {
+const impl<I: [const] Iterator<Item = T>, T, const N: usize> SpecNextChunk<T, N> for I {
     #[inline]
     default fn spec_next_chunk(&mut self) -> Result<[T; N], IntoIter<T, N>> {
         let mut array = [const { MaybeUninit::uninit() }; N];
@@ -1011,7 +1011,7 @@ impl<I: [const] Iterator<Item = T>, T, const N: usize> const SpecNextChunk<T, N>
     }
 }
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<I: [const] Iterator<Item = T> + TrustedLen, T, const N: usize> const SpecNextChunk<T, N>
+const impl<I: [const] Iterator<Item = T> + TrustedLen, T, const N: usize> SpecNextChunk<T, N>
     for I
 {
     fn spec_next_chunk(&mut self) -> Result<[T; N], IntoIter<T, N>> {
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index eb4562b..fe844e3 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -209,7 +209,7 @@ pub const trait BorrowMut<Borrowed: ?Sized>: [const] Borrow<Borrowed> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Borrow<T> for T {
+const impl<T: ?Sized> Borrow<T> for T {
     #[rustc_diagnostic_item = "noop_method_borrow"]
     fn borrow(&self) -> &T {
         self
@@ -218,7 +218,7 @@ fn borrow(&self) -> &T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const BorrowMut<T> for T {
+const impl<T: ?Sized> BorrowMut<T> for T {
     fn borrow_mut(&mut self) -> &mut T {
         self
     }
@@ -226,7 +226,7 @@ fn borrow_mut(&mut self) -> &mut T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Borrow<T> for &T {
+const impl<T: ?Sized> Borrow<T> for &T {
     fn borrow(&self) -> &T {
         self
     }
@@ -234,7 +234,7 @@ fn borrow(&self) -> &T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Borrow<T> for &mut T {
+const impl<T: ?Sized> Borrow<T> for &mut T {
     fn borrow(&self) -> &T {
         self
     }
@@ -242,7 +242,7 @@ fn borrow(&self) -> &T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const BorrowMut<T> for &mut T {
+const impl<T: ?Sized> BorrowMut<T> for &mut T {
     fn borrow_mut(&mut self) -> &mut T {
         self
     }
diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs
index 9d623d3..26a7f9c 100644
--- a/library/core/src/bstr/mod.rs
+++ b/library/core/src/bstr/mod.rs
@@ -131,7 +131,7 @@ pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const Deref for ByteStr {
+const impl Deref for ByteStr {
     type Target = [u8];
 
     #[inline]
@@ -142,7 +142,7 @@ fn deref(&self) -> &[u8] {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const DerefMut for ByteStr {
+const impl DerefMut for ByteStr {
     #[inline]
     fn deref_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -258,7 +258,7 @@ fn emit(byte_str: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<[u8]> for ByteStr {
+const impl AsRef<[u8]> for ByteStr {
     #[inline]
     fn as_ref(&self) -> &[u8] {
         &self.0
@@ -267,7 +267,7 @@ fn as_ref(&self) -> &[u8] {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<ByteStr> for ByteStr {
+const impl AsRef<ByteStr> for ByteStr {
     #[inline]
     fn as_ref(&self) -> &ByteStr {
         self
@@ -278,7 +278,7 @@ fn as_ref(&self) -> &ByteStr {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<ByteStr> for str {
+const impl AsRef<ByteStr> for str {
     #[inline]
     fn as_ref(&self) -> &ByteStr {
         ByteStr::new(self)
@@ -287,7 +287,7 @@ fn as_ref(&self) -> &ByteStr {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsMut<[u8]> for ByteStr {
+const impl AsMut<[u8]> for ByteStr {
     #[inline]
     fn as_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -302,7 +302,7 @@ fn as_mut(&mut self) -> &mut [u8] {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const Borrow<[u8]> for ByteStr {
+const impl Borrow<[u8]> for ByteStr {
     #[inline]
     fn borrow(&self) -> &[u8] {
         &self.0
@@ -313,7 +313,7 @@ fn borrow(&self) -> &[u8] {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const BorrowMut<[u8]> for ByteStr {
+const impl BorrowMut<[u8]> for ByteStr {
     #[inline]
     fn borrow_mut(&mut self) -> &mut [u8] {
         &mut self.0
@@ -382,7 +382,7 @@ fn default() -> Self {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a> const TryFrom<&'a ByteStr> for &'a str {
+const impl<'a> TryFrom<&'a ByteStr> for &'a str {
     type Error = crate::str::Utf8Error;
 
     #[inline]
@@ -393,7 +393,7 @@ fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
 
 #[unstable(feature = "bstr", issue = "134915")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a> const TryFrom<&'a mut ByteStr> for &'a mut str {
+const impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
     type Error = crate::str::Utf8Error;
 
     #[inline]
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index d67693f..1c79cf6 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -334,7 +334,7 @@ fn clone(&self) -> Cell<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: [const] Default> const Default for Cell<T> {
+const impl<T: [const] Default> Default for Cell<T> {
     /// Creates a `Cell<T>`, with the `Default` value for T.
     #[inline]
     fn default() -> Cell<T> {
@@ -391,7 +391,7 @@ fn cmp(&self, other: &Cell<T>) -> Ordering {
 
 #[stable(feature = "cell_from", since = "1.12.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for Cell<T> {
+const impl<T> From<T> for Cell<T> {
     /// Creates a new `Cell<T>` containing the given value.
     fn from(t: T) -> Cell<T> {
         Cell::new(t)
@@ -1461,7 +1461,7 @@ fn clone_from(&mut self, source: &Self) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: [const] Default> const Default for RefCell<T> {
+const impl<T: [const] Default> Default for RefCell<T> {
     /// Creates a `RefCell<T>`, with the `Default` value for T.
     #[inline]
     fn default() -> RefCell<T> {
@@ -1539,7 +1539,7 @@ fn cmp(&self, other: &RefCell<T>) -> Ordering {
 
 #[stable(feature = "cell_from", since = "1.12.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for RefCell<T> {
+const impl<T> From<T> for RefCell<T> {
     /// Creates a new `RefCell<T>` containing the given value.
     fn from(t: T) -> RefCell<T> {
         RefCell::new(t)
@@ -1579,7 +1579,7 @@ const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> {
 }
 
 #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
-impl const Drop for BorrowRef<'_> {
+const impl Drop for BorrowRef<'_> {
     #[inline]
     fn drop(&mut self) {
         let borrow = self.borrow.get();
@@ -1589,7 +1589,7 @@ fn drop(&mut self) {
 }
 
 #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
-impl const Clone for BorrowRef<'_> {
+const impl Clone for BorrowRef<'_> {
     #[inline]
     fn clone(&self) -> Self {
         // Since this Ref exists, we know the borrow flag
@@ -1621,7 +1621,7 @@ pub struct Ref<'b, T: ?Sized + 'b> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Deref for Ref<'_, T> {
+const impl<T: ?Sized> Deref for Ref<'_, T> {
     type Target = T;
 
     #[inline]
@@ -2047,7 +2047,7 @@ struct BorrowRefMut<'b> {
 }
 
 #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
-impl const Drop for BorrowRefMut<'_> {
+const impl Drop for BorrowRefMut<'_> {
     #[inline]
     fn drop(&mut self) {
         let borrow = self.borrow.get();
@@ -2105,7 +2105,7 @@ pub struct RefMut<'b, T: ?Sized + 'b> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Deref for RefMut<'_, T> {
+const impl<T: ?Sized> Deref for RefMut<'_, T> {
     type Target = T;
 
     #[inline]
@@ -2117,7 +2117,7 @@ fn deref(&self) -> &T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const DerefMut for RefMut<'_, T> {
+const impl<T: ?Sized> DerefMut for RefMut<'_, T> {
     #[inline]
     fn deref_mut(&mut self) -> &mut T {
         // SAFETY: the value is accessible as long as we hold our borrow.
@@ -2567,7 +2567,7 @@ pub const fn raw_get(this: *const Self) -> *mut T {
 
 #[stable(feature = "unsafe_cell_default", since = "1.10.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: [const] Default> const Default for UnsafeCell<T> {
+const impl<T: [const] Default> Default for UnsafeCell<T> {
     /// Creates an `UnsafeCell`, with the `Default` value for T.
     fn default() -> UnsafeCell<T> {
         UnsafeCell::new(Default::default())
@@ -2576,7 +2576,7 @@ fn default() -> UnsafeCell<T> {
 
 #[stable(feature = "cell_from", since = "1.12.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for UnsafeCell<T> {
+const impl<T> From<T> for UnsafeCell<T> {
     /// Creates a new `UnsafeCell<T>` containing the given value.
     fn from(t: T) -> UnsafeCell<T> {
         UnsafeCell::new(t)
@@ -2674,7 +2674,7 @@ pub const fn raw_get(this: *const Self) -> *mut T {
 
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: [const] Default> const Default for SyncUnsafeCell<T> {
+const impl<T: [const] Default> Default for SyncUnsafeCell<T> {
     /// Creates an `SyncUnsafeCell`, with the `Default` value for T.
     fn default() -> SyncUnsafeCell<T> {
         SyncUnsafeCell::new(Default::default())
@@ -2683,7 +2683,7 @@ fn default() -> SyncUnsafeCell<T> {
 
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for SyncUnsafeCell<T> {
+const impl<T> From<T> for SyncUnsafeCell<T> {
     /// Creates a new `SyncUnsafeCell<T>` containing the given value.
     fn from(t: T) -> SyncUnsafeCell<T> {
         SyncUnsafeCell::new(t)
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 66436ed..ba32fff 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -347,7 +347,7 @@ fn deref_mut(&mut self) -> &mut T {
 
 #[stable(feature = "lazy_cell", since = "1.80.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: Default> const Default for LazyCell<T> {
+const impl<T: Default> Default for LazyCell<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
     fn default() -> LazyCell<T> {
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index af4469f..799e19c 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -354,7 +354,7 @@ pub fn take(&mut self) -> Option<T> {
 
 #[stable(feature = "once_cell", since = "1.70.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for OnceCell<T> {
+const impl<T> Default for OnceCell<T> {
     #[inline]
     fn default() -> Self {
         Self::new()
@@ -397,7 +397,7 @@ impl<T: Eq> Eq for OnceCell<T> {}
 
 #[stable(feature = "once_cell", since = "1.70.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for OnceCell<T> {
+const impl<T> From<T> for OnceCell<T> {
     /// Creates a new `OnceCell<T>` which already contains the given `value`.
     #[inline]
     fn from(value: T) -> Self {
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 90c09d4..a60fc68 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -37,7 +37,7 @@ pub(super) const fn from_u32(i: u32) -> Option<char> {
 
 #[stable(feature = "char_convert", since = "1.13.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<char> for u32 {
+const impl From<char> for u32 {
     /// Converts a [`char`] into a [`u32`].
     ///
     /// # Examples
@@ -56,7 +56,7 @@ fn from(c: char) -> Self {
 
 #[stable(feature = "more_char_conversions", since = "1.51.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<char> for u64 {
+const impl From<char> for u64 {
     /// Converts a [`char`] into a [`u64`].
     ///
     /// # Examples
@@ -77,7 +77,7 @@ fn from(c: char) -> Self {
 
 #[stable(feature = "more_char_conversions", since = "1.51.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<char> for u128 {
+const impl From<char> for u128 {
     /// Converts a [`char`] into a [`u128`].
     ///
     /// # Examples
@@ -102,7 +102,7 @@ fn from(c: char) -> Self {
 /// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
 #[stable(feature = "u8_from_char", since = "1.59.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<char> for u8 {
+const impl TryFrom<char> for u8 {
     type Error = TryFromCharError;
 
     /// Tries to convert a [`char`] into a [`u8`].
@@ -132,7 +132,7 @@ fn try_from(c: char) -> Result<u8, Self::Error> {
 /// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003.
 #[stable(feature = "u16_from_char", since = "1.74.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<char> for u16 {
+const impl TryFrom<char> for u16 {
     type Error = TryFromCharError;
 
     /// Tries to convert a [`char`] into a [`u16`].
@@ -164,7 +164,7 @@ fn try_from(c: char) -> Result<u16, Self::Error> {
 /// UTF-32 code point to the extent representable by pointer addresses.
 #[stable(feature = "usize_try_from_char", since = "1.94.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<char> for usize {
+const impl TryFrom<char> for usize {
     type Error = TryFromCharError;
 
     /// Tries to convert a [`char`] into a [`usize`].
@@ -214,7 +214,7 @@ fn try_from(c: char) -> Result<usize, Self::Error> {
 /// C0 and C1 control codes.
 #[stable(feature = "char_convert", since = "1.13.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<u8> for char {
+const impl From<u8> for char {
     /// Converts a [`u8`] into a [`char`].
     ///
     /// # Examples
@@ -300,7 +300,7 @@ const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
 
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<u32> for char {
+const impl TryFrom<u32> for char {
     type Error = CharTryFromError;
 
     #[inline]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 13c2090..d8b7fe4 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1050,7 +1050,7 @@ pub fn is_alphanumeric(self) -> bool {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_is_control", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_is_control", since = "1.97.0")]
     #[inline]
     pub const fn is_control(self) -> bool {
         // According to
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 0c3e90b..93e7742 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -717,7 +717,7 @@ unsafe impl const TrivialClone for $t {}
 
     #[unstable(feature = "never_type", issue = "35121")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    impl const Clone for ! {
+    const impl Clone for ! {
         #[inline]
         fn clone(&self) -> Self {
             *self
@@ -727,11 +727,11 @@ fn clone(&self) -> Self {
     #[doc(hidden)]
     #[unstable(feature = "trivial_clone", issue = "none")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    unsafe impl const TrivialClone for ! {}
+    const unsafe impl TrivialClone for ! {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    impl<T: PointeeSized> const Clone for *const T {
+    const impl<T: PointeeSized> Clone for *const T {
         #[inline(always)]
         fn clone(&self) -> Self {
             *self
@@ -741,11 +741,11 @@ fn clone(&self) -> Self {
     #[doc(hidden)]
     #[unstable(feature = "trivial_clone", issue = "none")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    unsafe impl<T: PointeeSized> const TrivialClone for *const T {}
+    const unsafe impl<T: PointeeSized> TrivialClone for *const T {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    impl<T: PointeeSized> const Clone for *mut T {
+    const impl<T: PointeeSized> Clone for *mut T {
         #[inline(always)]
         fn clone(&self) -> Self {
             *self
@@ -755,12 +755,12 @@ fn clone(&self) -> Self {
     #[doc(hidden)]
     #[unstable(feature = "trivial_clone", issue = "none")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    unsafe impl<T: PointeeSized> const TrivialClone for *mut T {}
+    const unsafe impl<T: PointeeSized> TrivialClone for *mut T {}
 
     /// Shared references can be cloned, but mutable references *cannot*!
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    impl<T: PointeeSized> const Clone for &T {
+    const impl<T: PointeeSized> Clone for &T {
         #[inline(always)]
         #[rustc_diagnostic_item = "noop_method_clone"]
         fn clone(&self) -> Self {
@@ -771,7 +771,7 @@ fn clone(&self) -> Self {
     #[doc(hidden)]
     #[unstable(feature = "trivial_clone", issue = "none")]
     #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-    unsafe impl<T: PointeeSized> const TrivialClone for &T {}
+    const unsafe impl<T: PointeeSized> TrivialClone for &T {}
 
     #[unstable(feature = "share_trait", issue = "156756")]
     impl<T: PointeeSized> Share for &T {}
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 4e6cddc..b699c7a 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -685,7 +685,7 @@ pub const fn then_with<F>(self, f: F) -> Ordering
 
 #[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialOrd> const PartialOrd for Reverse<T> {
+const impl<T: [const] PartialOrd> PartialOrd for Reverse<T> {
     #[inline]
     fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
         other.0.partial_cmp(&self.0)
@@ -711,7 +711,7 @@ fn ge(&self, other: &Self) -> bool {
 
 #[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Ord> const Ord for Reverse<T> {
+const impl<T: [const] Ord> Ord for Reverse<T> {
     #[inline]
     fn cmp(&self, other: &Reverse<T>) -> Ordering {
         other.0.cmp(&self.0)
@@ -1884,7 +1884,7 @@ fn ne(&self, other: &Self) -> bool { *self != *other }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const PartialEq for () {
+    const impl PartialEq for () {
         #[inline]
         fn eq(&self, _other: &()) -> bool {
             true
@@ -1970,7 +1970,7 @@ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const PartialOrd for () {
+    const impl PartialOrd for () {
         #[inline]
         fn partial_cmp(&self, _: &()) -> Option<Ordering> {
             Some(Equal)
@@ -1979,7 +1979,7 @@ fn partial_cmp(&self, _: &()) -> Option<Ordering> {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const PartialOrd for bool {
+    const impl PartialOrd for bool {
         #[inline]
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
             Some(self.cmp(other))
@@ -2036,7 +2036,7 @@ fn clamp(self, min: Self, max: Self) -> Self
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const Ord for () {
+    const impl Ord for () {
         #[inline]
         fn cmp(&self, _other: &()) -> Ordering {
             Equal
@@ -2045,7 +2045,7 @@ fn cmp(&self, _other: &()) -> Ordering {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const Ord for bool {
+    const impl Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
             // Casting to i8's and converting the difference to an Ordering generates
@@ -2081,7 +2081,7 @@ fn clamp(self, min: bool, max: bool) -> bool {
 
     #[unstable(feature = "never_type", issue = "35121")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const PartialEq for ! {
+    const impl PartialEq for ! {
         #[inline]
         fn eq(&self, _: &!) -> bool {
             *self
@@ -2090,11 +2090,11 @@ fn eq(&self, _: &!) -> bool {
 
     #[unstable(feature = "never_type", issue = "35121")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const Eq for ! {}
+    const impl Eq for ! {}
 
     #[unstable(feature = "never_type", issue = "35121")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const PartialOrd for ! {
+    const impl PartialOrd for ! {
         #[inline]
         fn partial_cmp(&self, _: &!) -> Option<Ordering> {
             *self
@@ -2103,7 +2103,7 @@ fn partial_cmp(&self, _: &!) -> Option<Ordering> {
 
     #[unstable(feature = "never_type", issue = "35121")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl const Ord for ! {
+    const impl Ord for ! {
         #[inline]
         fn cmp(&self, _: &!) -> Ordering {
             *self
@@ -2114,7 +2114,7 @@ fn cmp(&self, _: &!) -> Ordering {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &A
+    const impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &A
     where
         A: [const] PartialEq<B>,
     {
@@ -2129,7 +2129,7 @@ fn ne(&self, other: &&B) -> bool {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&B> for &A
+    const impl<A: PointeeSized, B: PointeeSized> PartialOrd<&B> for &A
     where
         A: [const] PartialOrd<B>,
     {
@@ -2172,7 +2172,7 @@ fn __chaining_ge(&self, other: &&B) -> ControlFlow<bool> {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized> const Ord for &A
+    const impl<A: PointeeSized> Ord for &A
     where
         A: [const] Ord,
     {
@@ -2183,13 +2183,13 @@ fn cmp(&self, other: &Self) -> Ordering {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized> const Eq for &A where A: [const] Eq {}
+    const impl<A: PointeeSized> Eq for &A where A: [const] Eq {}
 
     // &mut pointers
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &mut A
+    const impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &mut A
     where
         A: [const] PartialEq<B>,
     {
@@ -2204,7 +2204,7 @@ fn ne(&self, other: &&mut B) -> bool {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&mut B> for &mut A
+    const impl<A: PointeeSized, B: PointeeSized> PartialOrd<&mut B> for &mut A
     where
         A: [const] PartialOrd<B>,
     {
@@ -2247,7 +2247,7 @@ fn __chaining_ge(&self, other: &&mut B) -> ControlFlow<bool> {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized> const Ord for &mut A
+    const impl<A: PointeeSized> Ord for &mut A
     where
         A: [const] Ord,
     {
@@ -2258,11 +2258,11 @@ fn cmp(&self, other: &Self) -> Ordering {
     }
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized> const Eq for &mut A where A: [const] Eq {}
+    const impl<A: PointeeSized> Eq for &mut A where A: [const] Eq {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &A
+    const impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &A
     where
         A: [const] PartialEq<B>,
     {
@@ -2278,7 +2278,7 @@ fn ne(&self, other: &&mut B) -> bool {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-    impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &mut A
+    const impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &mut A
     where
         A: [const] PartialEq<B>,
     {
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 46b0e8c..34cf9c5 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -709,7 +709,7 @@ pub const trait TryFrom<T>: Sized {
 // As lifts over &
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &T
+const impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &T
 where
     T: [const] AsRef<U>,
 {
@@ -722,7 +722,7 @@ fn as_ref(&self) -> &U {
 // As lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized, U: PointeeSized> const AsRef<U> for &mut T
+const impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &mut T
 where
     T: [const] AsRef<U>,
 {
@@ -743,7 +743,7 @@ fn as_ref(&self) -> &U {
 // AsMut lifts over &mut
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized, U: PointeeSized> const AsMut<U> for &mut T
+const impl<T: PointeeSized, U: PointeeSized> AsMut<U> for &mut T
 where
     T: [const] AsMut<U>,
 {
@@ -764,7 +764,7 @@ fn as_mut(&mut self) -> &mut U {
 // From implies Into
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, U> const Into<U> for T
+const impl<T, U> Into<U> for T
 where
     U: [const] From<T>,
 {
@@ -782,7 +782,7 @@ fn into(self) -> U {
 // From (and thus Into) is reflexive
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for T {
+const impl<T> From<T> for T {
     /// Returns the argument unchanged.
     #[inline(always)]
     fn from(t: T) -> T {
@@ -799,7 +799,7 @@ fn from(t: T) -> T {
 #[rustc_reservation_impl = "permitting this impl would forbid us from adding \
                             `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<!> for T {
+const impl<T> From<!> for T {
     fn from(t: !) -> T {
         t
     }
@@ -808,7 +808,7 @@ fn from(t: !) -> T {
 // TryFrom implies TryInto
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, U> const TryInto<U> for T
+const impl<T, U> TryInto<U> for T
 where
     U: [const] TryFrom<T>,
 {
@@ -824,7 +824,7 @@ fn try_into(self) -> Result<U, U::Error> {
 // with an uninhabited error type.
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, U> const TryFrom<U> for T
+const impl<T, U> TryFrom<U> for T
 where
     U: [const] Into<T>,
 {
@@ -842,7 +842,7 @@ fn try_from(value: U) -> Result<Self, Self::Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const AsRef<[T]> for [T] {
+const impl<T> AsRef<[T]> for [T] {
     #[inline(always)]
     fn as_ref(&self) -> &[T] {
         self
@@ -851,7 +851,7 @@ fn as_ref(&self) -> &[T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const AsMut<[T]> for [T] {
+const impl<T> AsMut<[T]> for [T] {
     #[inline(always)]
     fn as_mut(&mut self) -> &mut [T] {
         self
@@ -860,7 +860,7 @@ fn as_mut(&mut self) -> &mut [T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<str> for str {
+const impl AsRef<str> for str {
     #[inline(always)]
     fn as_ref(&self) -> &str {
         self
@@ -869,7 +869,7 @@ fn as_ref(&self) -> &str {
 
 #[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsMut<str> for str {
+const impl AsMut<str> for str {
     #[inline(always)]
     fn as_mut(&mut self) -> &mut str {
         self
@@ -931,7 +931,7 @@ pub enum Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl const Clone for Infallible {
+const impl Clone for Infallible {
     fn clone(&self) -> Infallible {
         match *self {}
     }
@@ -956,7 +956,7 @@ impl Error for Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialEq for Infallible {
+const impl PartialEq for Infallible {
     fn eq(&self, _: &Infallible) -> bool {
         match *self {}
     }
@@ -964,11 +964,11 @@ fn eq(&self, _: &Infallible) -> bool {
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const Eq for Infallible {}
+const impl Eq for Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialOrd for Infallible {
+const impl PartialOrd for Infallible {
     fn partial_cmp(&self, _other: &Self) -> Option<crate::cmp::Ordering> {
         match *self {}
     }
@@ -976,7 +976,7 @@ fn partial_cmp(&self, _other: &Self) -> Option<crate::cmp::Ordering> {
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const Ord for Infallible {
+const impl Ord for Infallible {
     fn cmp(&self, _other: &Self) -> crate::cmp::Ordering {
         match *self {}
     }
@@ -984,7 +984,7 @@ fn cmp(&self, _other: &Self) -> crate::cmp::Ordering {
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<!> for Infallible {
+const impl From<!> for Infallible {
     #[inline]
     fn from(x: !) -> Self {
         x
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index a56ce18..2e968e8 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -503,7 +503,7 @@ macro_rules! impl_nonzero_int_from_nonzero_int {
     ($Small:ty => $Large:ty) => {
         #[stable(feature = "nz_int_conv", since = "1.41.0")]
         #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-        impl const From<NonZero<$Small>> for NonZero<$Large> {
+        const impl From<NonZero<$Small>> for NonZero<$Large> {
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
             // Rustdocs on functions do not.
             #[doc = concat!("Converts <code>[NonZero]\\<[", stringify!($Small), "]></code> ")]
@@ -562,7 +562,7 @@ macro_rules! impl_nonzero_int_try_from_int {
     ($Int:ty) => {
         #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")]
         #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-        impl const TryFrom<$Int> for NonZero<$Int> {
+        const impl TryFrom<$Int> for NonZero<$Int> {
             type Error = TryFromIntError;
 
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 1cc4fb6..359ef29 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -151,7 +151,7 @@ macro_rules! default_impl {
     ($t:ty, $v:expr, $doc:tt) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-        impl const Default for $t {
+        const impl Default for $t {
             #[inline(always)]
             #[doc = $doc]
             fn default() -> $t {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index c2d6f7b..d3318b0 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -177,7 +177,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[stable(feature = "cstr_default", since = "1.10.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for &CStr {
+const impl Default for &CStr {
     #[inline]
     fn default() -> Self {
         c""
@@ -729,7 +729,7 @@ fn index(&self, index: range::RangeFrom<usize>) -> &CStr {
 
 #[stable(feature = "cstring_asref", since = "1.7.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<CStr> for CStr {
+const impl AsRef<CStr> for CStr {
     #[inline]
     fn as_ref(&self) -> &CStr {
         self
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index 871943a..d5b83a2 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -250,7 +250,7 @@ pub(crate) const fn duplicate(&self) -> Self {
 }
 
 #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
-impl<'f> const Clone for VaList<'f> {
+const impl<'f> Clone for VaList<'f> {
     /// Clone the [`VaList`], producing a second independent cursor into the variable argument list.
     ///
     /// Corresponds to `va_copy` in C.
@@ -265,7 +265,7 @@ fn clone(&self) -> Self {
 }
 
 #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
-impl<'f> const Drop for VaList<'f> {
+const impl<'f> Drop for VaList<'f> {
     /// Drop the [`VaList`].
     ///
     /// Corresponds to `va_end` in C.
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index eea6118..c7c8d57 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -784,7 +784,7 @@ fn clone(&self) -> BuildHasherDefault<H> {
 
 #[stable(since = "1.7.0", feature = "build_hasher")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<H> const Default for BuildHasherDefault<H> {
+const impl<H> Default for BuildHasherDefault<H> {
     fn default() -> BuildHasherDefault<H> {
         Self::new()
     }
diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs
index eed1044..bc74bd0 100644
--- a/library/core/src/hash/sip.rs
+++ b/library/core/src/hash/sip.rs
@@ -340,7 +340,7 @@ fn clone(&self) -> Hasher<S> {
 }
 
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<S: Sip> const Default for Hasher<S> {
+const impl<S: Sip> Default for Hasher<S> {
     /// Creates a `Hasher<S>` with the two initial keys set to 0.
     #[inline]
     fn default() -> Hasher<S> {
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index a8e01e6..90326e6 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -778,6 +778,9 @@ pub const fn unlikely(b: bool) -> bool {
 #[stable(feature = "cold_path", since = "1.95.0")]
 #[rustc_const_stable(feature = "cold_path", since = "1.95.0")]
 #[inline(always)]
+// Even if for some reason the cold_path intrinsic is not visible to codegen, the coldness will
+// ensure that branches this is in are still known to be cold.
+#[cold]
 pub const fn cold_path() {
     crate::intrinsics::cold_path()
 }
diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs
index aa9033ee..bc415ec 100644
--- a/library/core/src/intrinsics/fallback.rs
+++ b/library/core/src/intrinsics/fallback.rs
@@ -80,7 +80,7 @@ const fn wide_mul_u128(a: u128, b: u128) -> (u128, u128) {
 }
 
 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
-impl const CarryingMulAdd for u128 {
+const impl CarryingMulAdd for u128 {
     type Unsigned = u128;
     #[inline]
     fn carrying_mul_add(self, b: u128, c: u128, d: u128) -> (u128, u128) {
@@ -94,7 +94,7 @@ fn carrying_mul_add(self, b: u128, c: u128, d: u128) -> (u128, u128) {
 }
 
 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
-impl const CarryingMulAdd for i128 {
+const impl CarryingMulAdd for i128 {
     type Unsigned = u128;
     #[inline]
     fn carrying_mul_add(self, b: i128, c: i128, d: i128) -> (u128, i128) {
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 05edd8a..78d7314 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3569,6 +3569,7 @@ pub const fn offload<F, T: crate::marker::Tuple, R>(
     f: F,
     workgroup_dim: [u32; 3],
     thread_dim: [u32; 3],
+    dyn_cache: u32,
     args: T,
 ) -> R;
 
diff --git a/library/core/src/io/io_slice.rs b/library/core/src/io/io_slice.rs
new file mode 100644
index 0000000..0bdd410
--- /dev/null
+++ b/library/core/src/io/io_slice.rs
@@ -0,0 +1,339 @@
+use crate::fmt;
+use crate::mem::take;
+use crate::ops::{Deref, DerefMut};
+
+cfg_select! {
+    any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => {
+        #[path = "io_slice/repr_iovec.rs"]
+        mod repr;
+    }
+    target_os = "windows" => {
+        #[path = "io_slice/repr_windows.rs"]
+        mod repr;
+    }
+    target_os = "uefi" => {
+        #[path = "io_slice/repr_uefi.rs"]
+        mod repr;
+    }
+    _ => {
+        #[path = "io_slice/repr_generic.rs"]
+        mod repr;
+    }
+}
+
+/// A buffer type used with `Read::read_vectored`.
+///
+/// It is semantically a wrapper around a `&mut [u8]`, but is guaranteed to be
+/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
+/// Windows.
+#[stable(feature = "iovec", since = "1.36.0")]
+#[repr(transparent)]
+pub struct IoSliceMut<'a>(repr::IoSliceMut<'a>);
+
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
+unsafe impl<'a> Send for IoSliceMut<'a> {}
+
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
+unsafe impl<'a> Sync for IoSliceMut<'a> {}
+
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> fmt::Debug for IoSliceMut<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.0.as_slice(), fmt)
+    }
+}
+
+impl<'a> IoSliceMut<'a> {
+    /// Creates a new `IoSliceMut` wrapping a byte slice.
+    ///
+    /// # Panics
+    ///
+    /// Panics on Windows if the slice is larger than 4GB.
+    #[stable(feature = "iovec", since = "1.36.0")]
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(repr::IoSliceMut::new(buf))
+    }
+
+    /// Advance the internal cursor of the slice.
+    ///
+    /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
+    /// multiple buffers.
+    ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::IoSliceMut;
+    /// use std::ops::Deref;
+    ///
+    /// let mut data = [1; 8];
+    /// let mut buf = IoSliceMut::new(&mut data);
+    ///
+    /// // Mark 3 bytes as read.
+    /// buf.advance(3);
+    /// assert_eq!(buf.deref(), [1; 5].as_ref());
+    /// ```
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.0.advance(n)
+    }
+
+    /// Advance a slice of slices.
+    ///
+    /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over.
+    /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified
+    /// to start at that cursor.
+    ///
+    /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes,
+    /// the result will only include the second `IoSliceMut`, advanced by 2 bytes.
+    ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::IoSliceMut;
+    /// use std::ops::Deref;
+    ///
+    /// let mut buf1 = [1; 8];
+    /// let mut buf2 = [2; 16];
+    /// let mut buf3 = [3; 8];
+    /// let mut bufs = &mut [
+    ///     IoSliceMut::new(&mut buf1),
+    ///     IoSliceMut::new(&mut buf2),
+    ///     IoSliceMut::new(&mut buf3),
+    /// ][..];
+    ///
+    /// // Mark 10 bytes as read.
+    /// IoSliceMut::advance_slices(&mut bufs, 10);
+    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
+    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+    /// ```
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
+    #[inline]
+    pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
+        // Number of buffers to remove.
+        let mut remove = 0;
+        // Remaining length before reaching n.
+        let mut left = n;
+        for buf in bufs.iter() {
+            if let Some(remainder) = left.checked_sub(buf.len()) {
+                left = remainder;
+                remove += 1;
+            } else {
+                break;
+            }
+        }
+
+        *bufs = &mut take(bufs)[remove..];
+        if bufs.is_empty() {
+            assert!(left == 0, "advancing io slices beyond their length");
+        } else {
+            bufs[0].advance(left);
+        }
+    }
+
+    /// Get the underlying bytes as a mutable slice with the original lifetime.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_as_bytes)]
+    /// use std::io::IoSliceMut;
+    ///
+    /// let mut data = *b"abcdef";
+    /// let io_slice = IoSliceMut::new(&mut data);
+    /// io_slice.into_slice()[0] = b'A';
+    ///
+    /// assert_eq!(&data, b"Abcdef");
+    /// ```
+    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
+    pub const fn into_slice(self) -> &'a mut [u8] {
+        self.0.into_slice()
+    }
+}
+
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> Deref for IoSliceMut<'a> {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        self.0.as_slice()
+    }
+}
+
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> DerefMut for IoSliceMut<'a> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut [u8] {
+        self.0.as_mut_slice()
+    }
+}
+
+/// A buffer type used with `Write::write_vectored`.
+///
+/// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be
+/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
+/// Windows.
+#[stable(feature = "iovec", since = "1.36.0")]
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct IoSlice<'a>(repr::IoSlice<'a>);
+
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
+unsafe impl<'a> Send for IoSlice<'a> {}
+
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
+unsafe impl<'a> Sync for IoSlice<'a> {}
+
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> fmt::Debug for IoSlice<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.0.as_slice(), fmt)
+    }
+}
+
+impl<'a> IoSlice<'a> {
+    /// Creates a new `IoSlice` wrapping a byte slice.
+    ///
+    /// # Panics
+    ///
+    /// Panics on Windows if the slice is larger than 4GB.
+    #[stable(feature = "iovec", since = "1.36.0")]
+    #[must_use]
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(repr::IoSlice::new(buf))
+    }
+
+    /// Advance the internal cursor of the slice.
+    ///
+    /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
+    /// buffers.
+    ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::IoSlice;
+    /// use std::ops::Deref;
+    ///
+    /// let data = [1; 8];
+    /// let mut buf = IoSlice::new(&data);
+    ///
+    /// // Mark 3 bytes as read.
+    /// buf.advance(3);
+    /// assert_eq!(buf.deref(), [1; 5].as_ref());
+    /// ```
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.0.advance(n)
+    }
+
+    /// Advance a slice of slices.
+    ///
+    /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over.
+    /// If the cursor ends up in the middle of an `IoSlice`, it is modified
+    /// to start at that cursor.
+    ///
+    /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes,
+    /// the result will only include the second `IoSlice`, advanced by 2 bytes.
+    ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::IoSlice;
+    /// use std::ops::Deref;
+    ///
+    /// let buf1 = [1; 8];
+    /// let buf2 = [2; 16];
+    /// let buf3 = [3; 8];
+    /// let mut bufs = &mut [
+    ///     IoSlice::new(&buf1),
+    ///     IoSlice::new(&buf2),
+    ///     IoSlice::new(&buf3),
+    /// ][..];
+    ///
+    /// // Mark 10 bytes as written.
+    /// IoSlice::advance_slices(&mut bufs, 10);
+    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
+    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
+    #[inline]
+    pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
+        // Number of buffers to remove.
+        let mut remove = 0;
+        // Remaining length before reaching n. This prevents overflow
+        // that could happen if the length of slices in `bufs` were instead
+        // accumulated. Those slice may be aliased and, if they are large
+        // enough, their added length may overflow a `usize`.
+        let mut left = n;
+        for buf in bufs.iter() {
+            if let Some(remainder) = left.checked_sub(buf.len()) {
+                left = remainder;
+                remove += 1;
+            } else {
+                break;
+            }
+        }
+
+        *bufs = &mut take(bufs)[remove..];
+        if bufs.is_empty() {
+            assert!(left == 0, "advancing io slices beyond their length");
+        } else {
+            bufs[0].advance(left);
+        }
+    }
+
+    /// Get the underlying bytes as a slice with the original lifetime.
+    ///
+    /// This doesn't borrow from `self`, so is less restrictive than calling
+    /// `.deref()`, which does.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_as_bytes)]
+    /// use std::io::IoSlice;
+    ///
+    /// let data = b"abcdef";
+    ///
+    /// let mut io_slice = IoSlice::new(data);
+    /// let tail = &io_slice.as_slice()[3..];
+    ///
+    /// // This works because `tail` doesn't borrow `io_slice`
+    /// io_slice = IoSlice::new(tail);
+    ///
+    /// assert_eq!(io_slice.as_slice(), b"def");
+    /// ```
+    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
+    pub const fn as_slice(self) -> &'a [u8] {
+        self.0.as_slice()
+    }
+}
+
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> Deref for IoSlice<'a> {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        self.0.as_slice()
+    }
+}
diff --git a/library/core/src/io/io_slice/repr_generic.rs b/library/core/src/io/io_slice/repr_generic.rs
new file mode 100644
index 0000000..fdeb497
--- /dev/null
+++ b/library/core/src/io/io_slice/repr_generic.rs
@@ -0,0 +1,52 @@
+use crate::mem;
+
+#[derive(Copy, Clone)]
+pub(crate) struct IoSlice<'a>(&'a [u8]);
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(buf)
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        self.0 = &self.0[n..]
+    }
+
+    #[inline]
+    pub(crate) const fn as_slice(&self) -> &'a [u8] {
+        self.0
+    }
+}
+
+pub(crate) struct IoSliceMut<'a>(&'a mut [u8]);
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(buf)
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        let slice = mem::take(&mut self.0);
+        let (_, remaining) = slice.split_at_mut(n);
+        self.0 = remaining;
+    }
+
+    #[inline]
+    pub(crate) fn as_slice(&self) -> &[u8] {
+        self.0
+    }
+
+    #[inline]
+    pub(crate) const fn into_slice(self) -> &'a mut [u8] {
+        self.0
+    }
+
+    #[inline]
+    pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
+        self.0
+    }
+}
diff --git a/library/core/src/io/io_slice/repr_iovec.rs b/library/core/src/io/io_slice/repr_iovec.rs
new file mode 100644
index 0000000..cd8f5d5
--- /dev/null
+++ b/library/core/src/io/io_slice/repr_iovec.rs
@@ -0,0 +1,101 @@
+use crate::ffi::c_void;
+use crate::marker::PhantomData;
+use crate::slice;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+struct iovec {
+    iov_base: *mut c_void,
+    iov_len: usize,
+}
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub(crate) struct IoSlice<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice {
+            vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        // SAFETY:
+        //  * `n <= iov_len` as asserted above.
+        //  * The allocation pointed to by `iov_base` is valid up to `iov_base + iov_len`.
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub(crate) const fn as_slice(&self) -> &'a [u8] {
+        // SAFETY:
+        //  * `iov_base` and `iov_len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+}
+
+#[repr(transparent)]
+pub(crate) struct IoSliceMut<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut {
+            vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        // SAFETY:
+        //  * `n <= iov_len` as asserted above.
+        //  * The allocation pointed to by `iov_base` is valid up to `iov_base + iov_len`.
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub(crate) fn as_slice(&self) -> &[u8] {
+        // SAFETY:
+        //  * `iov_base` and `iov_len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+
+    #[inline]
+    pub(crate) const fn into_slice(self) -> &'a mut [u8] {
+        // SAFETY:
+        //  * `iov_base` and `iov_len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+
+    #[inline]
+    pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
+        // SAFETY:
+        //  * `iov_base` and `iov_len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+}
diff --git a/library/core/src/io/io_slice/repr_uefi.rs b/library/core/src/io/io_slice/repr_uefi.rs
new file mode 100644
index 0000000..3698eea
--- /dev/null
+++ b/library/core/src/io/io_slice/repr_uefi.rs
@@ -0,0 +1,90 @@
+//! A buffer type used with `Write::write_vectored` for UEFI Networking APIs. Vectored writing to
+//! File is not supported as of UEFI Spec 2.11.
+
+use crate::marker::PhantomData;
+use crate::slice;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub(crate) struct IoSlice<'a> {
+    len: u32,
+    data: *const u8,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        let len = buf.len().try_into().unwrap();
+        Self { len, data: buf.as_ptr(), _p: PhantomData }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        self.len = u32::try_from(n)
+            .ok()
+            .and_then(|n| self.len.checked_sub(n))
+            .expect("advancing IoSlice beyond its length");
+
+        // SAFETY:
+        //  * `n <= len` as asserted above.
+        //  * The allocation pointed to by `data` is valid up to `data + len`.
+        unsafe { self.data = self.data.add(n) };
+    }
+
+    #[inline]
+    pub(crate) const fn as_slice(&self) -> &'a [u8] {
+        // SAFETY:
+        //  * `data` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
+    }
+}
+
+#[repr(C)]
+pub(crate) struct IoSliceMut<'a> {
+    len: u32,
+    data: *mut u8,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        let len = buf.len().try_into().unwrap();
+        Self { len, data: buf.as_mut_ptr(), _p: PhantomData }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        self.len = u32::try_from(n)
+            .ok()
+            .and_then(|n| self.len.checked_sub(n))
+            .expect("advancing IoSlice beyond its length");
+
+        // SAFETY:
+        //  * `n <= len` as asserted above.
+        //  * The allocation pointed to by `data` is valid up to `data + len`.
+        unsafe { self.data = self.data.add(n) };
+    }
+
+    #[inline]
+    pub(crate) fn as_slice(&self) -> &[u8] {
+        // SAFETY:
+        //  * `data` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
+    }
+
+    #[inline]
+    pub(crate) const fn into_slice(self) -> &'a mut [u8] {
+        // SAFETY:
+        //  * `data` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
+    }
+
+    #[inline]
+    pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
+        // SAFETY:
+        //  * `data` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
+    }
+}
diff --git a/library/core/src/io/io_slice/repr_windows.rs b/library/core/src/io/io_slice/repr_windows.rs
new file mode 100644
index 0000000..6162d86
--- /dev/null
+++ b/library/core/src/io/io_slice/repr_windows.rs
@@ -0,0 +1,99 @@
+use crate::marker::PhantomData;
+use crate::slice;
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct WSABUF {
+    len: u32,
+    buf: *mut u8,
+}
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub(crate) struct IoSlice<'a> {
+    vec: WSABUF,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        assert!(buf.len() <= u32::MAX as usize);
+        IoSlice {
+            vec: WSABUF { len: buf.len() as u32, buf: buf.as_ptr() as *mut u8 },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        if (self.vec.len as usize) < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        // SAFETY:
+        //  * `n <= len` as asserted above.
+        //  * The allocation pointed to by `buf` is valid up to `buf + len`.
+        unsafe {
+            self.vec.len -= n as u32;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
+    pub(crate) const fn as_slice(&self) -> &'a [u8] {
+        // SAFETY:
+        //  * `buf` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) }
+    }
+}
+
+#[repr(transparent)]
+pub(crate) struct IoSliceMut<'a> {
+    vec: WSABUF,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub(crate) fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        assert!(buf.len() <= u32::MAX as usize);
+        IoSliceMut { vec: WSABUF { len: buf.len() as u32, buf: buf.as_mut_ptr() }, _p: PhantomData }
+    }
+
+    #[inline]
+    pub(crate) fn advance(&mut self, n: usize) {
+        if (self.vec.len as usize) < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        // SAFETY:
+        //  * `n <= len` as asserted above.
+        //  * The allocation pointed to by `buf` is valid up to `buf + len`.
+        unsafe {
+            self.vec.len -= n as u32;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
+    pub(crate) fn as_slice(&self) -> &[u8] {
+        // SAFETY:
+        //  * `buf` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) }
+    }
+
+    #[inline]
+    pub(crate) const fn into_slice(self) -> &'a mut [u8] {
+        // SAFETY:
+        //  * `buf` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
+    }
+
+    #[inline]
+    pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
+        // SAFETY:
+        //  * `buf` and `len` come from a prior decomposition of a valid slice.
+        unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
+    }
+}
diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs
index 822b24a..43b6e09 100644
--- a/library/core/src/io/mod.rs
+++ b/library/core/src/io/mod.rs
@@ -3,6 +3,7 @@
 mod borrowed_buf;
 mod cursor;
 mod error;
+mod io_slice;
 mod util;
 
 #[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
@@ -14,6 +15,8 @@
 #[unstable(feature = "raw_os_error_ty", issue = "107792")]
 pub use self::error::RawOsError;
 #[unstable(feature = "core_io", issue = "154046")]
+pub use self::io_slice::{IoSlice, IoSliceMut};
+#[unstable(feature = "core_io", issue = "154046")]
 pub use self::util::{Chain, Empty, Repeat, Sink, Take, empty, repeat, sink};
 #[doc(hidden)]
 #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
diff --git a/library/core/src/iter/adapters/map_windows.rs b/library/core/src/iter/adapters/map_windows.rs
index 5d96de5..5c12600 100644
--- a/library/core/src/iter/adapters/map_windows.rs
+++ b/library/core/src/iter/adapters/map_windows.rs
@@ -1,5 +1,5 @@
 use crate::iter::FusedIterator;
-use crate::mem::{MaybeUninit, SizedTypeProperties};
+use crate::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
 use crate::{fmt, ptr};
 
 /// An iterator over the mapped windows of another iterator.
@@ -30,14 +30,17 @@ struct MapWindowsInner<I: Iterator, const N: usize> {
     buffer: Option<Buffer<I::Item, N>>,
 }
 
-// `Buffer` uses two times of space to reduce moves among the iterations.
-// `Buffer<T, N>` is semantically `[MaybeUninit<T>; 2 * N]`. However, due
-// to limitations of const generics, we use this different type. Note that
-// it has the same underlying memory layout.
+/// `Buffer<T, N>` is semantically `[MaybeUninit<T>; 2 * N]`. This helps
+/// reduce moves while iterating. However, due
+/// to limitations of const generics, we use this different type. Note that
+/// it has the same underlying memory layout.
+///
+/// # Safety invariant
+///
+/// `self.buffer[self.start..self.start + N]` must be initialized,
+/// with all other elements being uninitialized. This also
+/// implies that `self.start <= N`.
 struct Buffer<T, const N: usize> {
-    // Invariant: `self.buffer[self.start..self.start + N]` is initialized,
-    // with all other elements being uninitialized. This also
-    // implies that `self.start <= N`.
     buffer: [[MaybeUninit<T>; N]; 2],
     start: usize,
 }
@@ -194,12 +197,18 @@ fn push(&mut self, next: T) {
 
 impl<T: Clone, const N: usize> Clone for Buffer<T, N> {
     fn clone(&self) -> Self {
-        let mut buffer = Buffer {
+        // Use `ManuallyDrop` until buffer is fully written to avoid dropping uninitialized elements on panic.
+        // (See `Buffer` rustdoc for safety invariant)
+        let mut buffer = ManuallyDrop::new(Buffer {
             buffer: [[const { MaybeUninit::uninit() }; N], [const { MaybeUninit::uninit() }; N]],
             start: self.start,
-        };
+        });
+
+        // `clone()` could panic; `ManuallyDrop` guards against that.
         buffer.as_uninit_array_mut().write(self.as_array_ref().clone());
-        buffer
+
+        // We initialized the buffer above, so we are good now
+        ManuallyDrop::into_inner(buffer)
     }
 }
 
@@ -218,10 +227,8 @@ fn drop(&mut self) {
         // SAFETY: our invariant guarantees that N elements starting from
         // `self.start` are initialized. We drop them here.
         unsafe {
-            let initialized_part: *mut [T] = crate::ptr::slice_from_raw_parts_mut(
-                self.buffer_mut_ptr().add(self.start).cast(),
-                N,
-            );
+            let initialized_part: *mut [T] =
+                self.buffer_mut_ptr().add(self.start).cast::<T>().cast_slice(N);
             ptr::drop_in_place(initialized_part);
         }
     }
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 3b025fd..949295a 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -574,7 +574,7 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
 
 #[unstable(feature = "step_trait", issue = "42168")]
 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
-impl const Step for char {
+const impl Step for char {
     #[inline]
     fn steps_between(&start: &char, &end: &char) -> (usize, Option<usize>) {
         let start = start as u32;
@@ -662,7 +662,7 @@ unsafe fn backward_unchecked(start: char, count: usize) -> char {
 
 #[unstable(feature = "step_trait", issue = "42168")]
 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
-impl const Step for AsciiChar {
+const impl Step for AsciiChar {
     #[inline]
     fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> (usize, Option<usize>) {
         Step::steps_between(&start.to_u8(), &end.to_u8())
@@ -705,7 +705,7 @@ unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
 
 #[unstable(feature = "step_trait", issue = "42168")]
 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
-impl const Step for Ipv4Addr {
+const impl Step for Ipv4Addr {
     #[inline]
     fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> (usize, Option<usize>) {
         u32::steps_between(&start.to_bits(), &end.to_bits())
@@ -738,7 +738,7 @@ unsafe fn backward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
 
 #[unstable(feature = "step_trait", issue = "42168")]
 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
-impl const Step for Ipv6Addr {
+const impl Step for Ipv6Addr {
     #[inline]
     fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> (usize, Option<usize>) {
         u128::steps_between(&start.to_bits(), &end.to_bits())
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 1844c76..7733c2b 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -82,7 +82,7 @@ fn clone(&self) -> Empty<T> {
 // which isn't necessary.
 #[stable(feature = "iter_empty", since = "1.2.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for Empty<T> {
+const impl<T> Default for Empty<T> {
     fn default() -> Empty<T> {
         Empty(marker::PhantomData)
     }
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 0d4ced1..c89026c 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -104,7 +104,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 /// Creates an empty iterator, like [`repeat_n(value, 0)`][`repeat_n`]
 /// but without needing any such value at hand.
-#[stable(feature = "iter_repeat_n_default", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n_default", since = "1.97.0")]
 impl<A> Default for RepeatN<A> {
     fn default() -> Self {
         RepeatN { inner: None }
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 9c3edfd..e7e5e30 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -314,7 +314,7 @@ pub const trait IntoIterator {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<I: [const] Iterator> const IntoIterator for I {
+const impl<I: [const] Iterator> IntoIterator for I {
     type Item = I::Item;
     type IntoIter = I;
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index acc758a..1cdf52d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -80,6 +80,7 @@
 #![deny(rust_2021_incompatible_or_patterns)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 #![warn(deprecated_in_future)]
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
@@ -234,6 +235,10 @@ pub mod autodiff {
     pub use crate::macros::builtin::{autodiff_forward, autodiff_reverse};
 }
 
+#[unstable(feature = "gpu_offload", issue = "131513")]
+#[doc = include_str!("../../core/src/offload.md")]
+pub mod offload;
+
 #[unstable(feature = "contracts", issue = "128044")]
 pub mod contracts;
 
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 6d7923b..c21191d 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1628,6 +1628,48 @@ macro_rules! include {
         /* compiler built-in */
     }
 
+    /// The `offload_kernel` macro is applied to a function to generate two separate
+    /// definitions: a host-side wrapper for dispatch and a device-side kernel.
+    ///
+    /// The macro does not perform the offload itself. It generates the necessary
+    /// code required by the compiler's offloading infrastructure.
+    ///
+    /// ### Usage example:
+    ///
+    /// ```rust,ignore (offload requires a -Z flag)
+    /// #[offload_kernel]
+    /// fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+    ///     *c = a[0] + b[0];
+    /// }
+    /// ```
+    ///
+    /// This expands to the host-side function:
+    ///
+    /// ```rust,ignore (offload requires a -Z flag)
+    /// #[unsafe(no_mangle)]
+    /// #[inline(never)]
+    /// fn foo(_: &[f32], _: &[f32], _: *mut f32) {
+    ///     ::core::panicking::panic("not implemented")
+    /// }
+    /// ```
+    ///
+    /// And the device-side kernel:
+    ///
+    /// ```rust,ignore (offload requires a -Z flag)
+    /// #[rustc_offload_kernel]
+    /// #[unsafe(no_mangle)]
+    /// unsafe extern "gpu-kernel" fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+    ///     *c = a[0] + b[0];
+    /// }
+    /// ```
+    #[unstable(feature = "gpu_offload", issue = "131513")]
+    #[allow_internal_unstable(rustc_attrs)]
+    #[allow_internal_unstable(core_intrinsics)]
+    #[rustc_builtin_macro]
+    pub macro offload_kernel($item:item) {
+        /* compiler built-in */
+    }
+
     /// Asserts that a boolean expression is `true` at runtime.
     ///
     /// This will invoke the [`panic!`] macro if the provided expression cannot be
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 9e6b02f..53141aa 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -856,7 +856,7 @@ unsafe impl<T: PointeeSized> TrivialClone for PhantomData<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: PointeeSized> const Default for PhantomData<T> {
+const impl<T: PointeeSized> Default for PhantomData<T> {
     fn default() -> Self {
         Self
     }
diff --git a/library/core/src/mem/alignment.rs b/library/core/src/mem/alignment.rs
index a57d8e8..08ce7fc 100644
--- a/library/core/src/mem/alignment.rs
+++ b/library/core/src/mem/alignment.rs
@@ -265,7 +265,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<NonZero<usize>> for Alignment {
+const impl TryFrom<NonZero<usize>> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
@@ -276,7 +276,7 @@ fn try_from(align: NonZero<usize>) -> Result<Alignment, Self::Error> {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const TryFrom<usize> for Alignment {
+const impl TryFrom<usize> for Alignment {
     type Error = num::TryFromIntError;
 
     #[inline]
@@ -287,7 +287,7 @@ fn try_from(align: usize) -> Result<Alignment, Self::Error> {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Alignment> for NonZero<usize> {
+const impl From<Alignment> for NonZero<usize> {
     #[inline]
     fn from(align: Alignment) -> NonZero<usize> {
         align.as_nonzero_usize()
@@ -296,7 +296,7 @@ fn from(align: Alignment) -> NonZero<usize> {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Alignment> for usize {
+const impl From<Alignment> for usize {
     #[inline]
     fn from(align: Alignment) -> usize {
         align.as_usize()
@@ -305,7 +305,7 @@ fn from(align: Alignment) -> usize {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const cmp::Ord for Alignment {
+const impl cmp::Ord for Alignment {
     #[inline]
     fn cmp(&self, other: &Self) -> cmp::Ordering {
         self.as_nonzero_usize().cmp(&other.as_nonzero_usize())
@@ -314,7 +314,7 @@ fn cmp(&self, other: &Self) -> cmp::Ordering {
 
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const cmp::PartialOrd for Alignment {
+const impl cmp::PartialOrd for Alignment {
     #[inline]
     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
         Some(self.cmp(other))
@@ -332,7 +332,7 @@ fn hash<H: hash::Hasher>(&self, state: &mut H) {
 /// Returns [`Alignment::MIN`], which is valid for any type.
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for Alignment {
+const impl Default for Alignment {
     fn default() -> Alignment {
         Alignment::MIN
     }
diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs
index 74bf353..70658f0 100644
--- a/library/core/src/mem/drop_guard.rs
+++ b/library/core/src/mem/drop_guard.rs
@@ -109,7 +109,7 @@ pub const fn dismiss(guard: Self) -> T
 
 #[unstable(feature = "drop_guard", issue = "144426")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, F> const Deref for DropGuard<T, F>
+const impl<T, F> Deref for DropGuard<T, F>
 where
     F: FnOnce(T),
 {
@@ -122,7 +122,7 @@ fn deref(&self) -> &T {
 
 #[unstable(feature = "drop_guard", issue = "144426")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T, F> const DerefMut for DropGuard<T, F>
+const impl<T, F> DerefMut for DropGuard<T, F>
 where
     F: FnOnce(T),
 {
@@ -133,7 +133,7 @@ fn deref_mut(&mut self) -> &mut T {
 
 #[unstable(feature = "drop_guard", issue = "144426")]
 #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")]
-impl<T, F> const Drop for DropGuard<T, F>
+const impl<T, F> Drop for DropGuard<T, F>
 where
     F: [const] FnOnce(T),
 {
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index ca008a8..4616c3d 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -270,7 +270,7 @@ impl<T: ?Sized> ManuallyDrop<T> {
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Deref for ManuallyDrop<T> {
+const impl<T: ?Sized> Deref for ManuallyDrop<T> {
     type Target = T;
     #[inline(always)]
     fn deref(&self) -> &T {
@@ -280,7 +280,7 @@ fn deref(&self) -> &T {
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
+const impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
     #[inline(always)]
     fn deref_mut(&mut self) -> &mut T {
         self.value.as_mut()
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index db94f52..f2d91b9 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1136,7 +1136,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Ipv4Addr> for IpAddr {
+const impl From<Ipv4Addr> for IpAddr {
     /// Copies this address to a new `IpAddr::V4`.
     ///
     /// # Examples
@@ -1159,7 +1159,7 @@ fn from(ipv4: Ipv4Addr) -> IpAddr {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Ipv6Addr> for IpAddr {
+const impl From<Ipv6Addr> for IpAddr {
     /// Copies this address to a new `IpAddr::V6`.
     ///
     /// # Examples
@@ -1232,7 +1232,7 @@ fn eq(&self, other: &IpAddr) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialOrd for Ipv4Addr {
+const impl PartialOrd for Ipv4Addr {
     #[inline]
     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -1263,7 +1263,7 @@ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const Ord for Ipv4Addr {
+const impl Ord for Ipv4Addr {
     #[inline]
     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
         self.octets.cmp(&other.octets)
@@ -1272,7 +1272,7 @@ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Ipv4Addr> for u32 {
+const impl From<Ipv4Addr> for u32 {
     /// Uses [`Ipv4Addr::to_bits`] to convert an IPv4 address to a host byte order `u32`.
     #[inline]
     fn from(ip: Ipv4Addr) -> u32 {
@@ -1282,7 +1282,7 @@ fn from(ip: Ipv4Addr) -> u32 {
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<u32> for Ipv4Addr {
+const impl From<u32> for Ipv4Addr {
     /// Uses [`Ipv4Addr::from_bits`] to convert a host byte order `u32` into an IPv4 address.
     #[inline]
     fn from(ip: u32) -> Ipv4Addr {
@@ -1292,7 +1292,7 @@ fn from(ip: u32) -> Ipv4Addr {
 
 #[stable(feature = "from_slice_v4", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u8; 4]> for Ipv4Addr {
+const impl From<[u8; 4]> for Ipv4Addr {
     /// Creates an `Ipv4Addr` from a four element byte array.
     ///
     /// # Examples
@@ -1311,7 +1311,7 @@ fn from(ip: u32) -> Ipv4Addr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u8; 4]> for IpAddr {
+const impl From<[u8; 4]> for IpAddr {
     /// Creates an `IpAddr::V4` from a four element byte array.
     ///
     /// # Examples
@@ -2237,7 +2237,7 @@ fn eq(&self, other: &Ipv6Addr) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialOrd for Ipv6Addr {
+const impl PartialOrd for Ipv6Addr {
     #[inline]
     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -2268,7 +2268,7 @@ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const Ord for Ipv6Addr {
+const impl Ord for Ipv6Addr {
     #[inline]
     fn cmp(&self, other: &Ipv6Addr) -> Ordering {
         self.segments().cmp(&other.segments())
@@ -2277,7 +2277,7 @@ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
 
 #[stable(feature = "i128", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Ipv6Addr> for u128 {
+const impl From<Ipv6Addr> for u128 {
     /// Uses [`Ipv6Addr::to_bits`] to convert an IPv6 address to a host byte order `u128`.
     #[inline]
     fn from(ip: Ipv6Addr) -> u128 {
@@ -2286,7 +2286,7 @@ fn from(ip: Ipv6Addr) -> u128 {
 }
 #[stable(feature = "i128", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<u128> for Ipv6Addr {
+const impl From<u128> for Ipv6Addr {
     /// Uses [`Ipv6Addr::from_bits`] to convert a host byte order `u128` to an IPv6 address.
     #[inline]
     fn from(ip: u128) -> Ipv6Addr {
@@ -2296,7 +2296,7 @@ fn from(ip: u128) -> Ipv6Addr {
 
 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u8; 16]> for Ipv6Addr {
+const impl From<[u8; 16]> for Ipv6Addr {
     /// Creates an `Ipv6Addr` from a sixteen element byte array.
     ///
     /// # Examples
@@ -2324,7 +2324,7 @@ fn from(ip: u128) -> Ipv6Addr {
 
 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u16; 8]> for Ipv6Addr {
+const impl From<[u16; 8]> for Ipv6Addr {
     /// Creates an `Ipv6Addr` from an eight element 16-bit array.
     ///
     /// # Examples
@@ -2353,7 +2353,7 @@ fn from(ip: u128) -> Ipv6Addr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u8; 16]> for IpAddr {
+const impl From<[u8; 16]> for IpAddr {
     /// Creates an `IpAddr::V6` from a sixteen element byte array.
     ///
     /// # Examples
@@ -2381,7 +2381,7 @@ fn from(ip: u128) -> Ipv6Addr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<[u16; 8]> for IpAddr {
+const impl From<[u16; 8]> for IpAddr {
     /// Creates an `IpAddr::V6` from an eight element 16-bit array.
     ///
     /// # Examples
@@ -2409,7 +2409,7 @@ fn from(ip: u128) -> Ipv6Addr {
 
 #[stable(feature = "ip_bitops", since = "1.75.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Not for Ipv4Addr {
+const impl Not for Ipv4Addr {
     type Output = Ipv4Addr;
 
     #[inline]
@@ -2425,7 +2425,7 @@ fn not(mut self) -> Ipv4Addr {
 
 #[stable(feature = "ip_bitops", since = "1.75.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Not for &'_ Ipv4Addr {
+const impl Not for &'_ Ipv4Addr {
     type Output = Ipv4Addr;
 
     #[inline]
@@ -2436,7 +2436,7 @@ fn not(self) -> Ipv4Addr {
 
 #[stable(feature = "ip_bitops", since = "1.75.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Not for Ipv6Addr {
+const impl Not for Ipv6Addr {
     type Output = Ipv6Addr;
 
     #[inline]
@@ -2452,7 +2452,7 @@ fn not(mut self) -> Ipv6Addr {
 
 #[stable(feature = "ip_bitops", since = "1.75.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Not for &'_ Ipv6Addr {
+const impl Not for &'_ Ipv6Addr {
     type Output = Ipv6Addr;
 
     #[inline]
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index ccc53c1..4f126b2 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -593,7 +593,7 @@ pub const fn set_scope_id(&mut self, new_scope_id: u32) {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<SocketAddrV4> for SocketAddr {
+const impl From<SocketAddrV4> for SocketAddr {
     /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
     #[inline]
     fn from(sock4: SocketAddrV4) -> SocketAddr {
@@ -603,7 +603,7 @@ fn from(sock4: SocketAddrV4) -> SocketAddr {
 
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<SocketAddrV6> for SocketAddr {
+const impl From<SocketAddrV6> for SocketAddr {
     /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
     #[inline]
     fn from(sock6: SocketAddrV6) -> SocketAddr {
@@ -613,7 +613,7 @@ fn from(sock6: SocketAddrV6) -> SocketAddr {
 
 #[stable(feature = "addr_from_into_ip", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<I: [const] Into<IpAddr>> const From<(I, u16)> for SocketAddr {
+const impl<I: [const] Into<IpAddr>> From<(I, u16)> for SocketAddr {
     /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
     ///
     /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index 8cd0656..d8d66cf 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -30,7 +30,7 @@ impl Error for TryFromIntError {}
 
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<Infallible> for TryFromIntError {
+const impl From<Infallible> for TryFromIntError {
     fn from(x: Infallible) -> TryFromIntError {
         match x {}
     }
@@ -38,7 +38,7 @@ fn from(x: Infallible) -> TryFromIntError {
 
 #[unstable(feature = "never_type", issue = "35121")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<!> for TryFromIntError {
+const impl From<!> for TryFromIntError {
     #[inline]
     fn from(never: !) -> TryFromIntError {
         // Match rather than coerce to make sure that code like
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 4e7be6f..01b8465 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -178,8 +178,8 @@ pub const fn trailing_ones(self) -> u32 {
         /// assert_eq!(n.isolate_highest_one(), 0b_01000000);
         #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_highest_one(), 0);")]
         /// ```
-        #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -198,8 +198,8 @@ pub const fn isolate_highest_one(self) -> Self {
         /// assert_eq!(n.isolate_lowest_one(), 0b_00000100);
         #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_lowest_one(), 0);")]
         /// ```
-        #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -218,8 +218,8 @@ pub const fn isolate_lowest_one(self) -> Self {
         #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")]
         #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")]
         /// ```
-        #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -238,8 +238,8 @@ pub const fn highest_one(self) -> Option<u32> {
         #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")]
         #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")]
         /// ```
-        #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs
index 33b2a67..df1cdf0 100644
--- a/library/core/src/num/niche_types.rs
+++ b/library/core/src/num/niche_types.rs
@@ -103,7 +103,7 @@ impl Nanoseconds {
 }
 
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for Nanoseconds {
+const impl Default for Nanoseconds {
     #[inline]
     fn default() -> Self {
         Self::ZERO
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 59c37a7..de2d10a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -185,7 +185,7 @@ impl<T> $Trait for NonZero<T> where T: ZeroablePrimitive + $Trait {}
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl<T> const Clone for NonZero<T>
+const impl<T> Clone for NonZero<T>
 where
     T: ZeroablePrimitive,
 {
@@ -204,11 +204,11 @@ impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {}
 #[doc(hidden)]
 #[unstable(feature = "trivial_clone", issue = "none")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-unsafe impl<T> const TrivialClone for NonZero<T> where T: ZeroablePrimitive {}
+const unsafe impl<T> TrivialClone for NonZero<T> where T: ZeroablePrimitive {}
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const PartialEq for NonZero<T>
+const impl<T> PartialEq for NonZero<T>
 where
     T: ZeroablePrimitive + [const] PartialEq,
 {
@@ -228,11 +228,11 @@ impl<T> StructuralPartialEq for NonZero<T> where T: ZeroablePrimitive + Structur
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const Eq for NonZero<T> where T: ZeroablePrimitive + [const] Eq {}
+const impl<T> Eq for NonZero<T> where T: ZeroablePrimitive + [const] Eq {}
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const PartialOrd for NonZero<T>
+const impl<T> PartialOrd for NonZero<T>
 where
     T: ZeroablePrimitive + [const] PartialOrd,
 {
@@ -264,7 +264,7 @@ fn ge(&self, other: &Self) -> bool {
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const Ord for NonZero<T>
+const impl<T> Ord for NonZero<T>
 where
     // FIXME(const_hack): the T: ~const Destruct should be inferred from the Self: ~const Destruct.
     // See https://github.com/rust-lang/rust/issues/144207
@@ -310,7 +310,7 @@ fn hash<H>(&self, state: &mut H)
 
 #[stable(feature = "from_nonzero", since = "1.31.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<NonZero<T>> for T
+const impl<T> From<NonZero<T>> for T
 where
     T: ZeroablePrimitive,
 {
@@ -323,7 +323,7 @@ fn from(nonzero: NonZero<T>) -> Self {
 
 #[stable(feature = "nonzero_bitor", since = "1.45.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl<T> const BitOr for NonZero<T>
+const impl<T> BitOr for NonZero<T>
 where
     T: ZeroablePrimitive + [const] BitOr<Output = T>,
 {
@@ -338,7 +338,7 @@ fn bitor(self, rhs: Self) -> Self::Output {
 
 #[stable(feature = "nonzero_bitor", since = "1.45.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl<T> const BitOr<T> for NonZero<T>
+const impl<T> BitOr<T> for NonZero<T>
 where
     T: ZeroablePrimitive + [const] BitOr<Output = T>,
 {
@@ -353,7 +353,7 @@ fn bitor(self, rhs: T) -> Self::Output {
 
 #[stable(feature = "nonzero_bitor", since = "1.45.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl<T> const BitOr<NonZero<T>> for T
+const impl<T> BitOr<NonZero<T>> for T
 where
     T: ZeroablePrimitive + [const] BitOr<Output = T>,
 {
@@ -368,7 +368,7 @@ fn bitor(self, rhs: NonZero<T>) -> Self::Output {
 
 #[stable(feature = "nonzero_bitor", since = "1.45.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl<T> const BitOrAssign for NonZero<T>
+const impl<T> BitOrAssign for NonZero<T>
 where
     T: ZeroablePrimitive,
     Self: [const] BitOr<Output = Self>,
@@ -381,7 +381,7 @@ fn bitor_assign(&mut self, rhs: Self) {
 
 #[stable(feature = "nonzero_bitor", since = "1.45.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl<T> const BitOrAssign<T> for NonZero<T>
+const impl<T> BitOrAssign<T> for NonZero<T>
 where
     T: ZeroablePrimitive,
     Self: [const] BitOr<T, Output = Self>,
@@ -660,8 +660,8 @@ pub const fn trailing_zeros(self) -> u32 {
             /// # Some(())
             /// # }
             /// ```
-            #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-            #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+            #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+            #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
             #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
             #[inline(always)]
@@ -692,8 +692,8 @@ pub const fn isolate_highest_one(self) -> Self {
             /// # Some(())
             /// # }
             /// ```
-            #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-            #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+            #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+            #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
             #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
             #[inline(always)]
@@ -720,8 +720,8 @@ pub const fn isolate_lowest_one(self) -> Self {
             /// # Some(())
             /// # }
             /// ```
-            #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-            #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+            #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+            #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline(always)]
@@ -743,8 +743,8 @@ pub const fn highest_one(self) -> u32 {
             /// # Some(())
             /// # }
             /// ```
-            #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-            #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+            #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+            #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline(always)]
@@ -1479,7 +1479,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
     (unsigned $Int:ty) => {
         #[stable(feature = "nonzero_div", since = "1.51.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Div<NonZero<$Int>> for $Int {
+        const impl Div<NonZero<$Int>> for $Int {
             type Output = $Int;
 
             /// Same as `self / other.get()`, but because `other` is a `NonZero<_>`,
@@ -1498,7 +1498,7 @@ fn div(self, other: NonZero<$Int>) -> $Int {
 
         #[stable(feature = "nonzero_div_assign", since = "1.79.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const DivAssign<NonZero<$Int>> for $Int {
+        const impl DivAssign<NonZero<$Int>> for $Int {
             /// Same as `self /= other.get()`, but because `other` is a `NonZero<_>`,
             /// there's never a runtime check for division-by-zero.
             ///
@@ -1512,7 +1512,7 @@ fn div_assign(&mut self, other: NonZero<$Int>) {
 
         #[stable(feature = "nonzero_div", since = "1.51.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Rem<NonZero<$Int>> for $Int {
+        const impl Rem<NonZero<$Int>> for $Int {
             type Output = $Int;
 
             /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
@@ -1526,7 +1526,7 @@ fn rem(self, other: NonZero<$Int>) -> $Int {
 
         #[stable(feature = "nonzero_div_assign", since = "1.79.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const RemAssign<NonZero<$Int>> for $Int {
+        const impl RemAssign<NonZero<$Int>> for $Int {
             /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
             #[inline]
             fn rem_assign(&mut self, other: NonZero<$Int>) {
@@ -1567,7 +1567,7 @@ pub const fn div_ceil(self, rhs: Self) -> Self {
     (signed $Int:ty) => {
         #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Neg for NonZero<$Int> {
+        const impl Neg for NonZero<$Int> {
             type Output = Self;
 
             #[inline]
@@ -1962,8 +1962,8 @@ pub const fn cast_signed(self) -> NonZero<$Sint> {
         /// # Some(())
         /// # }
         /// ```
-        #[stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "uint_bit_width", since = "1.97.0")]
+        #[rustc_const_stable(feature = "uint_bit_width", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 9bf765f..3170143 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -237,8 +237,8 @@ pub const fn trailing_ones(self) -> u32 {
         #[doc = concat!("assert_eq!(0b1110_", stringify!($SelfT), ".bit_width(), 4);")]
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.bit_width(), ", stringify!($BITS), ");")]
         /// ```
-        #[stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "uint_bit_width", since = "1.97.0")]
+        #[rustc_const_stable(feature = "uint_bit_width", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -257,8 +257,8 @@ pub const fn bit_width(self) -> u32 {
         /// assert_eq!(n.isolate_highest_one(), 0b_01000000);
         #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_highest_one(), 0);")]
         /// ```
-        #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -277,8 +277,8 @@ pub const fn isolate_highest_one(self) -> Self {
         /// assert_eq!(n.isolate_lowest_one(), 0b_00000100);
         #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".isolate_lowest_one(), 0);")]
         /// ```
-        #[stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "isolate_most_least_significant_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -297,8 +297,8 @@ pub const fn isolate_lowest_one(self) -> Self {
         #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")]
         #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")]
         /// ```
-        #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -320,8 +320,8 @@ pub const fn highest_one(self) -> Option<u32> {
         #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")]
         #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")]
         /// ```
-        #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
-        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "int_lowest_highest_one", since = "1.97.0")]
+        #[rustc_const_stable(feature = "int_lowest_highest_one", since = "1.97.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs
index 881fe61..68c5baf 100644
--- a/library/core/src/num/wrapping.rs
+++ b/library/core/src/num/wrapping.rs
@@ -89,7 +89,7 @@ macro_rules! sh_impl_signed {
     ($t:ident, $f:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shl<$f> for Wrapping<$t> {
+        const impl Shl<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -107,7 +107,7 @@ fn shl(self, other: $f) -> Wrapping<$t> {
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShlAssign<$f> for Wrapping<$t> {
+        const impl ShlAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shl_assign(&mut self, other: $f) {
                 *self = *self << other;
@@ -119,7 +119,7 @@ fn shl_assign(&mut self, other: $f) {
 
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shr<$f> for Wrapping<$t> {
+        const impl Shr<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -137,7 +137,7 @@ fn shr(self, other: $f) -> Wrapping<$t> {
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShrAssign<$f> for Wrapping<$t> {
+        const impl ShrAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shr_assign(&mut self, other: $f) {
                 *self = *self >> other;
@@ -153,7 +153,7 @@ macro_rules! sh_impl_unsigned {
     ($t:ident, $f:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shl<$f> for Wrapping<$t> {
+        const impl Shl<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -167,7 +167,7 @@ fn shl(self, other: $f) -> Wrapping<$t> {
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShlAssign<$f> for Wrapping<$t> {
+        const impl ShlAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shl_assign(&mut self, other: $f) {
                 *self = *self << other;
@@ -179,7 +179,7 @@ fn shl_assign(&mut self, other: $f) {
 
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shr<$f> for Wrapping<$t> {
+        const impl Shr<$f> for Wrapping<$t> {
             type Output = Wrapping<$t>;
 
             #[inline]
@@ -193,7 +193,7 @@ fn shr(self, other: $f) -> Wrapping<$t> {
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShrAssign<$f> for Wrapping<$t> {
+        const impl ShrAssign<$f> for Wrapping<$t> {
             #[inline]
             fn shr_assign(&mut self, other: $f) {
                 *self = *self >> other;
diff --git a/library/core/src/offload.md b/library/core/src/offload.md
new file mode 100644
index 0000000..fb3c0b8
--- /dev/null
+++ b/library/core/src/offload.md
@@ -0,0 +1,39 @@
+This module provides support for gpu offloading. For technical details regarding the `offload_kernel`
+and how to use it, see their respective documentation.
+
+## General usage
+The `offload_kernel` macro can be applied to a function to generate the necessary code to launch a
+kernel on the target device.
+
+```rust,ignore (optional component)
+#[offload_kernel]
+fn kernel(x: *mut [f64; 256]) {
+    // SAFETY:
+    // calling our `arch` functions and dereferencing a raw pointer is unsafe
+    unsafe {
+        let n = (*x).len();
+        let i = (thread_idx_x() + block_idx_x() * block_dim_x()) as usize;
+        if i < n {
+            (*x)[i] = i as f64;
+        }
+    }
+}
+```
+
+To launch an offloaded kernel, the only current way is to use the `core::intrinsic::offload`
+intrinsic (note that intrinsics usage is discouraged outside the standard library). This
+allows you to specify grid and block dimensions and pass the required arguments to the device.
+
+```rust,ignore (optional component)
+let mut x = [0.0f64; 256];
+core::intrinsics::offload::<_, _, ()>(kernel, [256, 1, 1], [1, 1, 1], (&mut x as *mut [f64; 256],));
+```
+
+For precise information on the `offload` intrinsic, see its respective documentation.
+
+## Current limitations:
+
+- Usage is restricted to types supported by the current device-mapping implementation.
+- Generics and functions accepting dyn Trait are not supported.
+- Kernel execution is currently restricted to intrinsics usage, which is discouraged outside of the
+standard library.
diff --git a/library/core/src/offload/mod.rs b/library/core/src/offload/mod.rs
new file mode 100644
index 0000000..164bbb9
--- /dev/null
+++ b/library/core/src/offload/mod.rs
@@ -0,0 +1,5 @@
+// offload module
+#[unstable(feature = "gpu_offload", issue = "131513")]
+pub use crate::macros::builtin::offload_kernel;
+#[unstable(feature = "gpu_offload", issue = "131513")]
+pub use crate::offload;
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index e347a20..b6daa0f 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -73,7 +73,7 @@ fn not(self) -> $t { !self }
 
 #[stable(feature = "not_never", since = "1.60.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Not for ! {
+const impl Not for ! {
     type Output = !;
 
     #[inline]
@@ -480,7 +480,7 @@ macro_rules! shl_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shl<$f> for $t {
+        const impl Shl<$f> for $t {
             type Output = $t;
 
             #[inline]
@@ -603,7 +603,7 @@ macro_rules! shr_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const Shr<$f> for $t {
+        const impl Shr<$f> for $t {
             type Output = $t;
 
             #[inline]
@@ -958,7 +958,7 @@ macro_rules! shl_assign_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShlAssign<$f> for $t {
+        const impl ShlAssign<$f> for $t {
             #[inline]
             #[track_caller]
             #[rustc_inherit_overflow_checks]
@@ -1045,7 +1045,7 @@ macro_rules! shr_assign_impl {
     ($t:ty, $f:ty) => {
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-        impl const ShrAssign<$f> for $t {
+        const impl ShrAssign<$f> for $t {
             #[inline]
             #[track_caller]
             #[rustc_inherit_overflow_checks]
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index f279ef0..227c9c4 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -102,7 +102,7 @@ pub enum ControlFlow<B, C = ()> {
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<B, C> const ops::Try for ControlFlow<B, C> {
+const impl<B, C> ops::Try for ControlFlow<B, C> {
     type Output = C;
     type Residual = ControlFlow<B, convert::Infallible>;
 
@@ -124,7 +124,7 @@ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
 // Note: manually specifying the residual type instead of using the default to work around
 // https://github.com/rust-lang/rust/issues/99940
-impl<B, C> const ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> {
+const impl<B, C> ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> {
     #[inline]
     fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
         match residual {
@@ -135,7 +135,7 @@ fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
 
 #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
 #[rustc_const_unstable(feature = "const_try_residual", issue = "91285")]
-impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> {
+const impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
     type TryType = ControlFlow<B, C>;
 }
 
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index e46204c..58bf0e2 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -152,7 +152,7 @@ pub const trait Deref: PointeeSized {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Deref for &T {
+const impl<T: ?Sized> Deref for &T {
     type Target = T;
 
     #[rustc_diagnostic_item = "noop_method_deref"]
@@ -166,7 +166,7 @@ impl<T: ?Sized> !DerefMut for &T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const Deref for &mut T {
+const impl<T: ?Sized> Deref for &mut T {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -276,7 +276,7 @@ pub const trait DerefMut: [const] Deref + PointeeSized {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: ?Sized> const DerefMut for &mut T {
+const impl<T: ?Sized> DerefMut for &mut T {
     fn deref_mut(&mut self) -> &mut T {
         self
     }
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index 57b41e6..25664a5 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -255,7 +255,7 @@ mod impls {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-    impl<A: Tuple, F: ?Sized> const Fn<A> for &F
+    const impl<A: Tuple, F: ?Sized> Fn<A> for &F
     where
         F: [const] Fn<A>,
     {
@@ -266,7 +266,7 @@ extern "rust-call" fn call(&self, args: A) -> F::Output {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-    impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
+    const impl<A: Tuple, F: ?Sized> FnMut<A> for &F
     where
         F: [const] Fn<A>,
     {
@@ -277,7 +277,7 @@ extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
+    const impl<A: Tuple, F: ?Sized> FnOnce<A> for &F
     where
         F: [const] Fn<A>,
     {
@@ -290,7 +290,7 @@ extern "rust-call" fn call_once(self, args: A) -> F::Output {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-    impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
+    const impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F
     where
         F: [const] FnMut<A>,
     {
@@ -301,7 +301,7 @@ extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
+    const impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F
     where
         F: [const] FnMut<A>,
     {
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index c15c8f2..1875aca 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -1045,7 +1045,7 @@ fn intersect<R>(self, other: R) -> (Bound<T>, Bound<T>)
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T: ?Sized> const RangeBounds<T> for RangeFull {
+const impl<T: ?Sized> RangeBounds<T> for RangeFull {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -1056,7 +1056,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeFull {
+const impl<T> IntoBounds<T> for RangeFull {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Unbounded, Unbounded)
     }
@@ -1064,7 +1064,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeFrom<T> {
+const impl<T> RangeBounds<T> for RangeFrom<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -1075,7 +1075,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeFrom<T> {
+const impl<T> IntoBounds<T> for RangeFrom<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Included(self.start), Unbounded)
     }
@@ -1083,7 +1083,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeTo<T> {
+const impl<T> RangeBounds<T> for RangeTo<T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -1094,7 +1094,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeTo<T> {
+const impl<T> IntoBounds<T> for RangeTo<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Unbounded, Excluded(self.end))
     }
@@ -1102,7 +1102,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for Range<T> {
+const impl<T> RangeBounds<T> for Range<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -1113,7 +1113,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for Range<T> {
+const impl<T> IntoBounds<T> for Range<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Included(self.start), Excluded(self.end))
     }
@@ -1121,7 +1121,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeInclusive<T> {
+const impl<T> RangeBounds<T> for RangeInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -1138,7 +1138,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeInclusive<T> {
+const impl<T> IntoBounds<T> for RangeInclusive<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (
             Included(self.start),
@@ -1155,7 +1155,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeToInclusive<T> {
+const impl<T> RangeBounds<T> for RangeToInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -1166,7 +1166,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeToInclusive<T> {
+const impl<T> IntoBounds<T> for RangeToInclusive<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Unbounded, Included(self.end))
     }
@@ -1174,7 +1174,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) {
+const impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
     fn start_bound(&self) -> Bound<&T> {
         match *self {
             (Included(ref start), _) => Included(start),
@@ -1194,7 +1194,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for (Bound<T>, Bound<T>) {
+const impl<T> IntoBounds<T> for (Bound<T>, Bound<T>) {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         self
     }
@@ -1202,7 +1202,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
+const impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
     fn start_bound(&self) -> Bound<&T> {
         self.0
     }
@@ -1220,7 +1220,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeFrom<&T> {
+const impl<T> RangeBounds<T> for RangeFrom<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -1237,7 +1237,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`.
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeTo<&T> {
+const impl<T> RangeBounds<T> for RangeTo<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -1254,7 +1254,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for Range<&T> {
+const impl<T> RangeBounds<T> for Range<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -1271,7 +1271,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeInclusive<&T> {
+const impl<T> RangeBounds<T> for RangeInclusive<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -1288,7 +1288,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`.
 #[stable(feature = "collections_range", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
+const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -1326,7 +1326,7 @@ pub const trait OneSidedRange<T>: RangeBounds<T> {
 
 #[unstable(feature = "one_sided_range", issue = "69780")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const OneSidedRange<T> for RangeTo<T>
+const impl<T> OneSidedRange<T> for RangeTo<T>
 where
     Self: RangeBounds<T>,
 {
@@ -1337,7 +1337,7 @@ fn bound(self) -> (OneSidedRangeBound, T) {
 
 #[unstable(feature = "one_sided_range", issue = "69780")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const OneSidedRange<T> for RangeFrom<T>
+const impl<T> OneSidedRange<T> for RangeFrom<T>
 where
     Self: RangeBounds<T>,
 {
@@ -1348,7 +1348,7 @@ fn bound(self) -> (OneSidedRangeBound, T) {
 
 #[unstable(feature = "one_sided_range", issue = "69780")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const OneSidedRange<T> for RangeToInclusive<T>
+const impl<T> OneSidedRange<T> for RangeToInclusive<T>
 where
     Self: RangeBounds<T>,
 {
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 4209278..f7486cd 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -430,7 +430,7 @@ pub(crate) const fn wrap_mut_2<A, B, F>(
 pub(crate) enum NeverShortCircuitResidual {}
 
 #[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")]
-impl<T> const Try for NeverShortCircuit<T> {
+const impl<T> Try for NeverShortCircuit<T> {
     type Output = T;
     type Residual = NeverShortCircuitResidual;
 
@@ -445,14 +445,14 @@ fn from_output(x: T) -> Self {
     }
 }
 #[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")]
-impl<T> const FromResidual for NeverShortCircuit<T> {
+const impl<T> FromResidual for NeverShortCircuit<T> {
     #[inline]
     fn from_residual(never: NeverShortCircuitResidual) -> Self {
         match never {}
     }
 }
 #[rustc_const_unstable(feature = "const_never_short_circuit", issue = "none")]
-impl<T: [const] Destruct> const Residual<T> for NeverShortCircuitResidual {
+const impl<T: [const] Destruct> Residual<T> for NeverShortCircuitResidual {
     type TryType = NeverShortCircuit<T>;
 }
 
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 2715981..a490a26 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1960,7 +1960,7 @@ pub const fn replace(&mut self, value: T) -> Option<T> {
         mem::replace(self, Some(value))
     }
 
-    /// Zips `self` with another `Option`.
+    /// Makes a tuple of the value in `self` and the value in another `Option`.
     ///
     /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`.
     /// Otherwise, `None` is returned.
@@ -1988,7 +1988,7 @@ pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)>
         }
     }
 
-    /// Zips `self` and another `Option` with function `f`.
+    /// Combines the value in `self` with the value in another `Option`, using the function `f`.
     ///
     /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`.
     /// Otherwise, `None` is returned.
@@ -2267,7 +2267,7 @@ const fn expect_failed(msg: &str) -> ! {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl<T> const Clone for Option<T>
+const impl<T> Clone for Option<T>
 where
     // FIXME(const_hack): the T: [const] Destruct should be inferred from the Self: [const] Destruct in clone_from.
     // See https://github.com/rust-lang/rust/issues/144207
@@ -2296,11 +2296,11 @@ impl<T> crate::clone::UseCloned for Option<T> where T: crate::clone::UseCloned {
 #[doc(hidden)]
 #[unstable(feature = "trivial_clone", issue = "none")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-unsafe impl<T> const TrivialClone for Option<T> where T: [const] TrivialClone + [const] Destruct {}
+const unsafe impl<T> TrivialClone for Option<T> where T: [const] TrivialClone + [const] Destruct {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for Option<T> {
+const impl<T> Default for Option<T> {
     /// Returns [`None`][Option::None].
     ///
     /// # Examples
@@ -2317,7 +2317,7 @@ fn default() -> Option<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<T> const IntoIterator for Option<T> {
+const impl<T> IntoIterator for Option<T> {
     type Item = T;
     type IntoIter = IntoIter<T>;
 
@@ -2362,7 +2362,7 @@ fn into_iter(self) -> IterMut<'a, T> {
 
 #[stable(since = "1.12.0", feature = "option_from")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for Option<T> {
+const impl<T> From<T> for Option<T> {
     /// Moves `val` into a new [`Some`].
     ///
     /// # Examples
@@ -2379,7 +2379,7 @@ fn from(val: T) -> Option<T> {
 
 #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a, T> const From<&'a Option<T>> for Option<&'a T> {
+const impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
     /// Converts from `&Option<T>` to `Option<&T>`.
     ///
     /// # Examples
@@ -2407,7 +2407,7 @@ fn from(o: &'a Option<T>) -> Option<&'a T> {
 
 #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> {
+const impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
     /// Converts from `&mut Option<T>` to `Option<&mut T>`
     ///
     /// # Examples
@@ -2435,7 +2435,7 @@ fn from(o: &'a mut Option<T>) -> Option<&'a mut T> {
 impl<T> crate::marker::StructuralPartialEq for Option<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialEq> const PartialEq for Option<T> {
+const impl<T: [const] PartialEq> PartialEq for Option<T> {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
         // Spelling out the cases explicitly optimizes better than
@@ -2454,7 +2454,7 @@ fn eq(&self, other: &Self) -> bool {
 // not optimal.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialOrd> const PartialOrd for Option<T> {
+const impl<T: [const] PartialOrd> PartialOrd for Option<T> {
     #[inline]
     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
         match (self, other) {
@@ -2468,7 +2468,7 @@ fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Ord> const Ord for Option<T> {
+const impl<T: [const] Ord> Ord for Option<T> {
     #[inline]
     fn cmp(&self, other: &Self) -> cmp::Ordering {
         match (self, other) {
@@ -2490,7 +2490,7 @@ struct Item<A> {
 }
 
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<A> const Iterator for Item<A> {
+const impl<A> Iterator for Item<A> {
     type Item = A;
 
     #[inline]
@@ -2625,7 +2625,7 @@ pub struct IntoIter<A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-impl<A> const Iterator for IntoIter<A> {
+const impl<A> Iterator for IntoIter<A> {
     type Item = A;
 
     #[inline]
@@ -2654,7 +2654,7 @@ impl<A> FusedIterator for IntoIter<A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
-unsafe impl<A> const TrustedLen for IntoIter<A> {}
+const unsafe impl<A> TrustedLen for IntoIter<A> {}
 
 /// The iterator produced by [`Option::into_flat_iter`]. See its documentation for more.
 #[derive(Clone, Debug)]
@@ -2766,7 +2766,7 @@ fn from_iter<I: IntoIterator<Item = Option<A>>>(iter: I) -> Option<V> {
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T> const ops::Try for Option<T> {
+const impl<T> ops::Try for Option<T> {
     type Output = T;
     type Residual = Option<convert::Infallible>;
 
@@ -2788,7 +2788,7 @@ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
 // Note: manually specifying the residual type instead of using the default to work around
 // https://github.com/rust-lang/rust/issues/99940
-impl<T> const ops::FromResidual<Option<convert::Infallible>> for Option<T> {
+const impl<T> ops::FromResidual<Option<convert::Infallible>> for Option<T> {
     #[inline]
     fn from_residual(residual: Option<convert::Infallible>) -> Self {
         match residual {
@@ -2800,7 +2800,7 @@ fn from_residual(residual: Option<convert::Infallible>) -> Self {
 #[diagnostic::do_not_recommend]
 #[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T> const ops::FromResidual<ops::Yeet<()>> for Option<T> {
+const impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> {
     #[inline]
     fn from_residual(ops::Yeet(()): ops::Yeet<()>) -> Self {
         None
@@ -2809,7 +2809,7 @@ fn from_residual(ops::Yeet(()): ops::Yeet<()>) -> Self {
 
 #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T> const ops::Residual<T> for Option<convert::Infallible> {
+const impl<T> ops::Residual<T> for Option<convert::Infallible> {
     type TryType = Option<T>;
 }
 
diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs
index f7f4854..bf2e61d 100644
--- a/library/core/src/panic/unwind_safe.rs
+++ b/library/core/src/panic/unwind_safe.rs
@@ -250,7 +250,7 @@ impl<T> RefUnwindSafe for crate::sync::atomic::AtomicPtr<T> {}
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const Deref for AssertUnwindSafe<T> {
+const impl<T> Deref for AssertUnwindSafe<T> {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -260,7 +260,7 @@ fn deref(&self) -> &T {
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const DerefMut for AssertUnwindSafe<T> {
+const impl<T> DerefMut for AssertUnwindSafe<T> {
     fn deref_mut(&mut self) -> &mut T {
         &mut self.0
     }
diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs
index 2670c26..77fbea5 100644
--- a/library/core/src/pat.rs
+++ b/library/core/src/pat.rs
@@ -64,7 +64,7 @@ fn sub_one(self) -> Self {
 }
 
 #[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
-impl const RangePattern for char {
+const impl RangePattern for char {
     const MIN: Self = char::MIN;
 
     const MAX: Self = char::MAX;
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index f7224df..40f7748 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1680,7 +1680,7 @@ pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> {
 
 #[stable(feature = "pin", since = "1.33.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<Ptr: [const] Deref> const Deref for Pin<Ptr> {
+const impl<Ptr: [const] Deref> Deref for Pin<Ptr> {
     type Target = Ptr::Target;
     fn deref(&self) -> &Ptr::Target {
         Pin::get_ref(Pin::as_ref(self))
@@ -1723,7 +1723,7 @@ pub const trait PinDerefMutHelper {
 
     #[unstable(feature = "pin_derefmut_internals", issue = "none")]
     #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-    impl<Ptr: [const] super::DerefMut> const PinDerefMutHelper for PinHelper<Ptr>
+    const impl<Ptr: [const] super::DerefMut> PinDerefMutHelper for PinHelper<Ptr>
     where
         Ptr::Target: crate::marker::Unpin,
     {
@@ -1739,7 +1739,7 @@ fn deref_mut(&mut self) -> &mut Ptr::Target {
 #[stable(feature = "pin", since = "1.33.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 #[cfg(not(doc))]
-impl<Ptr> const DerefMut for Pin<Ptr>
+const impl<Ptr> DerefMut for Pin<Ptr>
 where
     Ptr: [const] Deref,
     helper::PinHelper<Ptr>: [const] helper::PinDerefMutHelper<Target = Self::Target>,
@@ -1765,7 +1765,7 @@ fn deref_mut(&mut self) -> &mut Ptr::Target {
 #[stable(feature = "pin", since = "1.33.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
 #[cfg(doc)]
-impl<Ptr> const DerefMut for Pin<Ptr>
+const impl<Ptr> DerefMut for Pin<Ptr>
 where
     Ptr: [const] DerefMut,
     <Ptr as Deref>::Target: Unpin,
diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs
index ae03809..483cf52 100644
--- a/library/core/src/pin/unsafe_pinned.rs
+++ b/library/core/src/pin/unsafe_pinned.rs
@@ -149,7 +149,7 @@ fn default() -> Self {
 
 #[unstable(feature = "unsafe_pinned", issue = "125735")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for UnsafePinned<T> {
+const impl<T> From<T> for UnsafePinned<T> {
     /// Creates a new `UnsafePinned<T>` containing the given value.
     fn from(value: T) -> Self {
         UnsafePinned::new(value)
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 8b7b08b..0a7f9b9 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -183,6 +183,7 @@ pub fn addr(self) -> usize {
     /// [`with_exposed_provenance`]: with_exposed_provenance
     #[inline(always)]
     #[stable(feature = "exposed_provenance", since = "1.84.0")]
+    #[expect(lossy_provenance_casts, reason = "this *is* the replacement")]
     pub fn expose_provenance(self) -> usize {
         self.cast::<()>() as usize
     }
@@ -1400,11 +1401,11 @@ pub const fn cast_uninit(self) -> *const MaybeUninit<T> {
     ///
     /// ```rust
     /// #![feature(ptr_cast_slice)]
+    ///
     /// // create a slice pointer when starting out with a pointer to the first element
     /// let x = [5, 6, 7];
-    /// let raw_pointer = x.as_ptr();
-    /// let slice = raw_pointer.cast_slice(3);
-    /// assert_eq!(unsafe { &*slice }[2], 7);
+    /// let raw_slice = x.as_ptr().cast_slice(3);
+    /// assert_eq!(unsafe { &*raw_slice }[2], 7);
     /// ```
     ///
     /// You must ensure that the pointer is valid and not null before dereferencing
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index ff2c18d..593011e 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -2618,21 +2618,21 @@ fn cmp(&self, other: &Self) -> Ordering {
 #[stable(feature = "fnptr_impls", since = "1.4.0")]
 impl<F: FnPtr> hash::Hash for F {
     fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
-        state.write_usize(self.addr() as _)
+        state.write_usize(self.addr().addr())
     }
 }
 
 #[stable(feature = "fnptr_impls", since = "1.4.0")]
 impl<F: FnPtr> fmt::Pointer for F {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::pointer_fmt_inner(self.addr() as _, f)
+        fmt::pointer_fmt_inner(self.addr().addr(), f)
     }
 }
 
 #[stable(feature = "fnptr_impls", since = "1.4.0")]
 impl<F: FnPtr> fmt::Debug for F {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::pointer_fmt_inner(self.addr() as _, f)
+        fmt::pointer_fmt_inner(self.addr().addr(), f)
     }
 }
 
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 98b70a7..4b68d96 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -174,6 +174,7 @@ pub fn addr(self) -> usize {
     /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut
     #[inline(always)]
     #[stable(feature = "exposed_provenance", since = "1.84.0")]
+    #[expect(lossy_provenance_casts, reason = "this *is* the replacement")]
     pub fn expose_provenance(self) -> usize {
         self.cast::<()>() as usize
     }
@@ -1675,13 +1676,13 @@ pub const fn cast_uninit(self) -> *mut MaybeUninit<T> {
     /// #![feature(ptr_cast_slice)]
     ///
     /// let x = &mut [5, 6, 7];
-    /// let slice = x.as_mut_ptr().cast_slice(3);
+    /// let raw_mut_slice = x.as_mut_ptr().cast_slice(3);
     ///
     /// unsafe {
-    ///     (*slice)[2] = 99; // assign a value at an index in the slice
+    ///     (*raw_mut_slice)[2] = 99; // assign a value at an index in the slice
     /// };
     ///
-    /// assert_eq!(unsafe { &*slice }[2], 99);
+    /// assert_eq!(unsafe { &*raw_mut_slice }[2], 99);
     /// ```
     ///
     /// You must ensure that the pointer is valid and not null before dereferencing
@@ -1701,6 +1702,7 @@ pub const fn cast_slice(self, len: usize) -> *mut [T] {
         slice_from_raw_parts_mut(self, len)
     }
 }
+
 impl<T> *mut MaybeUninit<T> {
     /// Casts from a maybe-uninitialized type to its initialized version.
     ///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index b9b42c1..86e9d01 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1444,7 +1444,7 @@ impl<T> NonNull<[T]> {
     #[inline]
     pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
         // SAFETY: `data` is a `NonNull` pointer which is necessarily non-null
-        unsafe { Self::new_unchecked(super::slice_from_raw_parts_mut(data.as_ptr(), len)) }
+        unsafe { Self::new_unchecked(data.as_ptr().cast_slice(len)) }
     }
 
     /// Returns the length of a non-null raw slice.
@@ -1743,7 +1743,7 @@ fn hash<H: hash::Hasher>(&self, state: &mut H) {
 
 #[unstable(feature = "ptr_internals", issue = "none")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized> const From<Unique<T>> for NonNull<T> {
+const impl<T: PointeeSized> From<Unique<T>> for NonNull<T> {
     #[inline]
     fn from(unique: Unique<T>) -> Self {
         unique.as_non_null_ptr()
@@ -1752,7 +1752,7 @@ fn from(unique: Unique<T>) -> Self {
 
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized> const From<&mut T> for NonNull<T> {
+const impl<T: PointeeSized> From<&mut T> for NonNull<T> {
     /// Converts a `&mut T` to a `NonNull<T>`.
     ///
     /// This conversion is safe and infallible since references cannot be null.
@@ -1764,7 +1764,7 @@ fn from(r: &mut T) -> Self {
 
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized> const From<&T> for NonNull<T> {
+const impl<T: PointeeSized> From<&T> for NonNull<T> {
     /// Converts a `&T` to a `NonNull<T>`.
     ///
     /// This conversion is safe and infallible since references cannot be null.
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index 6e55f0e..dedabf7 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -191,7 +191,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[unstable(feature = "ptr_internals", issue = "none")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized> const From<&mut T> for Unique<T> {
+const impl<T: PointeeSized> From<&mut T> for Unique<T> {
     /// Converts a `&mut T` to a `Unique<T>`.
     ///
     /// This conversion is infallible since references cannot be null.
@@ -203,7 +203,7 @@ fn from(reference: &mut T) -> Self {
 
 #[unstable(feature = "ptr_internals", issue = "none")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T: PointeeSized> const From<NonNull<T>> for Unique<T> {
+const impl<T: PointeeSized> From<NonNull<T>> for Unique<T> {
     /// Converts a `NonNull<T>` to a `Unique<T>`.
     ///
     /// This conversion is infallible since `NonNull` cannot be null.
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index ade9a35..87e6ad6 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -176,7 +176,7 @@ pub const fn is_empty(&self) -> bool
 
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for Range<T> {
+const impl<T> RangeBounds<T> for Range<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -193,7 +193,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for Range<&T> {
+const impl<T> RangeBounds<T> for Range<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -204,7 +204,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for Range<T> {
+const impl<T> IntoBounds<T> for Range<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Included(self.start), Excluded(self.end))
     }
@@ -212,7 +212,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<Range<T>> for legacy::Range<T> {
+const impl<T> From<Range<T>> for legacy::Range<T> {
     #[inline]
     fn from(value: Range<T>) -> Self {
         Self { start: value.start, end: value.end }
@@ -220,7 +220,7 @@ fn from(value: Range<T>) -> Self {
 }
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<legacy::Range<T>> for Range<T> {
+const impl<T> From<legacy::Range<T>> for Range<T> {
     #[inline]
     fn from(value: legacy::Range<T>) -> Self {
         Self { start: value.start, end: value.end }
@@ -356,7 +356,7 @@ pub fn iter(&self) -> RangeInclusiveIter<Idx> {
 
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeInclusive<T> {
+const impl<T> RangeBounds<T> for RangeInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -373,7 +373,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeInclusive<&T> {
+const impl<T> RangeBounds<T> for RangeInclusive<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -385,7 +385,7 @@ fn end_bound(&self) -> Bound<&T> {
 // #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeInclusive<T> {
+const impl<T> IntoBounds<T> for RangeInclusive<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Included(self.start), Included(self.last))
     }
@@ -393,7 +393,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
+const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
     #[inline]
     fn from(value: RangeInclusive<T>) -> Self {
         Self::new(value.start, value.last)
@@ -401,7 +401,7 @@ fn from(value: RangeInclusive<T>) -> Self {
 }
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
+const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
     #[inline]
     fn from(value: legacy::RangeInclusive<T>) -> Self {
         assert!(
@@ -512,7 +512,7 @@ pub const fn contains<U>(&self, item: &U) -> bool
 
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeFrom<T> {
+const impl<T> RangeBounds<T> for RangeFrom<T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(&self.start)
     }
@@ -529,7 +529,7 @@ fn end_bound(&self) -> Bound<&T> {
 /// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeFrom<&T> {
+const impl<T> RangeBounds<T> for RangeFrom<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Included(self.start)
     }
@@ -540,7 +540,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeFrom<T> {
+const impl<T> IntoBounds<T> for RangeFrom<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Included(self.start), Unbounded)
     }
@@ -548,7 +548,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[unstable(feature = "one_sided_range", issue = "69780")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const OneSidedRange<T> for RangeFrom<T>
+const impl<T> OneSidedRange<T> for RangeFrom<T>
 where
     Self: RangeBounds<T>,
 {
@@ -559,7 +559,7 @@ fn bound(self) -> (OneSidedRangeBound, T) {
 
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
+const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
     #[inline]
     fn from(value: RangeFrom<T>) -> Self {
         Self { start: value.start }
@@ -567,7 +567,7 @@ fn from(value: RangeFrom<T>) -> Self {
 }
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
+const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
     #[inline]
     fn from(value: legacy::RangeFrom<T>) -> Self {
         Self { start: value.start }
@@ -679,7 +679,7 @@ fn from(value: RangeToInclusive<T>) -> Self {
 
 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeToInclusive<T> {
+const impl<T> RangeBounds<T> for RangeToInclusive<T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -690,7 +690,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
+const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
     fn start_bound(&self) -> Bound<&T> {
         Unbounded
     }
@@ -701,7 +701,7 @@ fn end_bound(&self) -> Bound<&T> {
 
 #[unstable(feature = "range_into_bounds", issue = "136903")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const IntoBounds<T> for RangeToInclusive<T> {
+const impl<T> IntoBounds<T> for RangeToInclusive<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
         (Unbounded, Included(self.last))
     }
@@ -709,7 +709,7 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
 
 #[unstable(feature = "one_sided_range", issue = "69780")]
 #[rustc_const_unstable(feature = "const_range", issue = "none")]
-impl<T> const OneSidedRange<T> for RangeToInclusive<T>
+const impl<T> OneSidedRange<T> for RangeToInclusive<T>
 where
     Self: RangeBounds<T>,
 {
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index d2855d0..f0e1a1d 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -2164,7 +2164,7 @@ fn from_iter<I: IntoIterator<Item = Result<A, E>>>(iter: I) -> Result<V, E> {
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T, E> const ops::Try for Result<T, E> {
+const impl<T, E> ops::Try for Result<T, E> {
     type Output = T;
     type Residual = Result<convert::Infallible, E>;
 
@@ -2184,7 +2184,7 @@ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
 
 #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T, E, F: [const] From<E>> const ops::FromResidual<Result<convert::Infallible, E>>
+const impl<T, E, F: [const] From<E>> ops::FromResidual<Result<convert::Infallible, E>>
     for Result<T, F>
 {
     #[inline]
@@ -2198,7 +2198,7 @@ fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
 #[diagnostic::do_not_recommend]
 #[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T, E, F: [const] From<E>> const ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
+const impl<T, E, F: [const] From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
     #[inline]
     fn from_residual(ops::Yeet(e): ops::Yeet<E>) -> Self {
         Err(From::from(e))
@@ -2207,6 +2207,6 @@ fn from_residual(ops::Yeet(e): ops::Yeet<E>) -> Self {
 
 #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
-impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> {
+const impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> {
     type TryType = Result<T, E>;
 }
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 6a10fc2..10a0088 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -11,7 +11,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U> const PartialEq<[U]> for [T]
+const impl<T, U> PartialEq<[U]> for [T]
 where
     T: [const] PartialEq<U>,
 {
@@ -30,12 +30,12 @@ fn eq(&self, other: &[U]) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Eq> const Eq for [T] {}
+const impl<T: [const] Eq> Eq for [T] {}
 
 /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] Ord> const Ord for [T] {
+const impl<T: [const] Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
         SliceOrd::compare(self, other)
     }
@@ -55,7 +55,7 @@ const fn as_underlying(x: ControlFlow<bool>) -> u8 {
 /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T: [const] PartialOrd> const PartialOrd for [T] {
+const impl<T: [const] PartialOrd> PartialOrd for [T] {
     #[inline]
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
         SlicePartialOrd::partial_compare(self, other)
@@ -113,7 +113,7 @@ const trait SlicePartialEq<B> {
 
 // Generic slice equality
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A, B> const SlicePartialEq<B> for A
+const impl<A, B> SlicePartialEq<B> for A
 where
     A: [const] PartialEq<B>,
 {
@@ -143,7 +143,7 @@ impl<A, B> const SlicePartialEq<B> for A
 // When each element can be compared byte-wise, we can compare all the bytes
 // from the whole size in one call to the intrinsics.
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A, B> const SlicePartialEq<B> for A
+const impl<A, B> SlicePartialEq<B> for A
 where
     A: [const] BytewiseEq<B>,
 {
@@ -179,7 +179,7 @@ const trait SliceChain: Sized {
 type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] PartialOrd> const SlicePartialOrd for A {
+const impl<A: [const] PartialOrd> SlicePartialOrd for A {
     default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
         let elem_chain = const |a, b| match PartialOrd::partial_cmp(a, b) {
             Some(Ordering::Equal) => ControlFlow::Continue(()),
@@ -194,7 +194,7 @@ impl<A: [const] PartialOrd> const SlicePartialOrd for A {
 }
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] PartialOrd> const SliceChain for A {
+const impl<A: [const] PartialOrd> SliceChain for A {
     default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
         chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
     }
@@ -248,7 +248,7 @@ impl<A> SlicePartialOrd for A
 */
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
+const impl<A: [const] AlwaysApplicableOrd> SlicePartialOrd for A {
     fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
         Some(SliceOrd::compare(left, right))
     }
@@ -282,7 +282,7 @@ const trait SliceOrd: Sized {
 }
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] Ord> const SliceOrd for A {
+const impl<A: [const] Ord> SliceOrd for A {
     default fn compare(left: &[Self], right: &[Self]) -> Ordering {
         let elem_chain = const |a, b| match Ord::cmp(a, b) {
             Ordering::Equal => ControlFlow::Continue(()),
@@ -307,20 +307,20 @@ impl<A: [const] Ord> const SliceOrd for A {
 const unsafe trait UnsignedBytewiseOrd: [const] Ord {}
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-unsafe impl const UnsignedBytewiseOrd for bool {}
+const unsafe impl UnsignedBytewiseOrd for bool {}
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-unsafe impl const UnsignedBytewiseOrd for u8 {}
+const unsafe impl UnsignedBytewiseOrd for u8 {}
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-unsafe impl const UnsignedBytewiseOrd for NonZero<u8> {}
+const unsafe impl UnsignedBytewiseOrd for NonZero<u8> {}
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-unsafe impl const UnsignedBytewiseOrd for Option<NonZero<u8>> {}
+const unsafe impl UnsignedBytewiseOrd for Option<NonZero<u8>> {}
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-unsafe impl const UnsignedBytewiseOrd for ascii::Char {}
+const unsafe impl UnsignedBytewiseOrd for ascii::Char {}
 
 // `compare_bytes` compares a sequence of unsigned bytes lexicographically, so
 // use it if the requirements for `UnsignedBytewiseOrd` are fulfilled.
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] Ord + [const] UnsignedBytewiseOrd> const SliceOrd for A {
+const impl<A: [const] Ord + [const] UnsignedBytewiseOrd> SliceOrd for A {
     #[inline]
     fn compare(left: &[Self], right: &[Self]) -> Ordering {
         // Since the length of a slice is always less than or equal to
@@ -347,7 +347,7 @@ fn compare(left: &[Self], right: &[Self]) -> Ordering {
 // Don't generate our own chaining loops for `memcmp`-able things either.
 
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> const SliceChain for A {
+const impl<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> SliceChain for A {
     #[inline]
     fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
         match SliceOrd::compare(left, right) {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 0efe87a..56eeb63 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -8,7 +8,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I> const ops::Index<I> for [T]
+const impl<T, I> ops::Index<I> for [T]
 where
     I: [const] SliceIndex<[T]>,
 {
@@ -22,7 +22,7 @@ fn index(&self, index: I) -> &I::Output {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<T, I> const ops::IndexMut<I> for [T]
+const impl<T, I> ops::IndexMut<I> for [T]
 where
     I: [const] SliceIndex<[T]>,
 {
@@ -211,7 +211,7 @@ impl<T> Sealed for crate::index::Clamp<T> where T: Sealed {}
 /// The methods `index` and `index_mut` panic if the index is out of bounds.
 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for usize {
+const unsafe impl<T> SliceIndex<[T]> for usize {
     type Output = T;
 
     #[inline]
@@ -282,7 +282,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut T {
 /// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
 /// than there are for a general `Range<usize>` (which might be `100..3`).
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
+const unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
     type Output = [T];
 
     #[inline]
@@ -359,7 +359,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// - the end of the range is out of bounds.
 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
+const unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
     type Output = [T];
 
     #[inline]
@@ -460,7 +460,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for range::Range<usize> {
+const unsafe impl<T> SliceIndex<[T]> for range::Range<usize> {
     type Output = [T];
 
     #[inline]
@@ -499,7 +499,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> {
+const unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
     type Output = [T];
 
     #[inline]
@@ -538,7 +538,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// The methods `index` and `index_mut` panic if the start of the range is out of bounds.
 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
+const unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
     type Output = [T];
 
     #[inline]
@@ -590,7 +590,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for range::RangeFrom<usize> {
+const unsafe impl<T> SliceIndex<[T]> for range::RangeFrom<usize> {
     type Output = [T];
 
     #[inline]
@@ -628,7 +628,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 
 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
+const unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
     type Output = [T];
 
     #[inline]
@@ -667,7 +667,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// - the end of the range is out of bounds.
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
+const unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
     type Output = [T];
 
     #[inline]
@@ -725,7 +725,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for range::RangeInclusive<usize> {
+const unsafe impl<T> SliceIndex<[T]> for range::RangeInclusive<usize> {
     type Output = [T];
 
     #[inline]
@@ -764,7 +764,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
+const unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
     type Output = [T];
 
     #[inline]
@@ -803,7 +803,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 /// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl<T> const SliceIndex<[T]> for range::RangeToInclusive<usize> {
+const unsafe impl<T> SliceIndex<[T]> for range::RangeToInclusive<usize> {
     type Output = [T];
 
     #[inline]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 0f14ee1..5601716 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -5595,7 +5595,7 @@ fn spec_clone_from(&mut self, src: &[T])
 }
 
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl<T> const CloneFromSpec<T> for [T]
+const impl<T> CloneFromSpec<T> for [T]
 where
     T: [const] Clone + [const] Destruct,
 {
@@ -5617,7 +5617,7 @@ impl<T> const CloneFromSpec<T> for [T]
 }
 
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl<T> const CloneFromSpec<T> for [T]
+const impl<T> CloneFromSpec<T> for [T]
 where
     T: [const] TrivialClone + [const] Destruct,
 {
@@ -5632,7 +5632,7 @@ fn spec_clone_from(&mut self, src: &[T]) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for &[T] {
+const impl<T> Default for &[T] {
     /// Creates an empty slice.
     fn default() -> Self {
         &[]
@@ -5641,7 +5641,7 @@ fn default() -> Self {
 
 #[stable(feature = "mut_slice_default", since = "1.5.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for &mut [T] {
+const impl<T> Default for &mut [T] {
     /// Creates a mutable empty slice.
     fn default() -> Self {
         &mut []
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 5af399a..fe8ed6c 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -3155,7 +3155,7 @@ pub const fn as_str(&self) -> &str {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<[u8]> for str {
+const impl AsRef<[u8]> for str {
     #[inline]
     fn as_ref(&self) -> &[u8] {
         self.as_bytes()
@@ -3164,7 +3164,7 @@ fn as_ref(&self) -> &[u8] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for &str {
+const impl Default for &str {
     /// Creates an empty str
     #[inline]
     fn default() -> Self {
@@ -3174,7 +3174,7 @@ fn default() -> Self {
 
 #[stable(feature = "default_mut_str", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for &mut str {
+const impl Default for &mut str {
     /// Creates an empty mutable str
     #[inline]
     fn default() -> Self {
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 3b5cec2..fb0fee3 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -5,7 +5,7 @@
 use crate::intrinsics::unchecked_sub;
 use crate::slice::SliceIndex;
 use crate::ub_checks::assert_unsafe_precondition;
-use crate::{ops, ptr, range};
+use crate::{ops, range};
 
 /// Implements ordering of strings.
 ///
@@ -24,7 +24,7 @@ fn cmp(&self, other: &str) -> Ordering {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const PartialEq for str {
+const impl PartialEq for str {
     #[inline]
     fn eq(&self, other: &str) -> bool {
         self.as_bytes() == other.as_bytes()
@@ -33,7 +33,7 @@ fn eq(&self, other: &str) -> bool {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl const Eq for str {}
+const impl Eq for str {}
 
 /// Implements comparison operations on strings.
 ///
@@ -52,7 +52,7 @@ fn partial_cmp(&self, other: &str) -> Option<Ordering> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<I> const ops::Index<I> for str
+const impl<I> ops::Index<I> for str
 where
     I: [const] SliceIndex<str>,
 {
@@ -66,7 +66,7 @@ fn index(&self, index: I) -> &I::Output {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-impl<I> const ops::IndexMut<I> for str
+const impl<I> ops::IndexMut<I> for str
 where
     I: [const] SliceIndex<str>,
 {
@@ -90,7 +90,7 @@ fn index_mut(&mut self, index: I) -> &mut I::Output {
 /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::RangeFull {
+const unsafe impl SliceIndex<str> for ops::RangeFull {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -155,7 +155,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// ```
 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::Range<usize> {
+const unsafe impl SliceIndex<str> for ops::Range<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -209,7 +209,7 @@ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
         // which satisfies all the conditions for `add`.
         unsafe {
             let new_len = unchecked_sub(self.end, self.start);
-            ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
+            slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
         }
     }
     #[inline]
@@ -230,7 +230,7 @@ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
         // SAFETY: see comments for `get_unchecked`.
         unsafe {
             let new_len = unchecked_sub(self.end, self.start);
-            ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
+            slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
         }
     }
     #[inline]
@@ -260,7 +260,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 
 #[stable(feature = "new_range_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for range::Range<usize> {
+const unsafe impl SliceIndex<str> for range::Range<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -314,7 +314,7 @@ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
         // which satisfies all the conditions for `add`.
         unsafe {
             let new_len = unchecked_sub(self.end, self.start);
-            ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
+            slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
         }
     }
     #[inline]
@@ -335,7 +335,7 @@ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
         // SAFETY: see comments for `get_unchecked`.
         unsafe {
             let new_len = unchecked_sub(self.end, self.start);
-            ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
+            slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
         }
     }
     #[inline]
@@ -432,7 +432,7 @@ fn index_mut(self, slice: &mut str) -> &mut str {
 /// character (as defined by `is_char_boundary`), or if `end > len`.
 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::RangeTo<usize> {
+const unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -501,7 +501,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// a character (as defined by `is_char_boundary`), or if `begin > len`.
 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
+const unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -557,7 +557,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 
 #[stable(feature = "new_range_from_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
+const unsafe impl SliceIndex<str> for range::RangeFrom<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -629,7 +629,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
+const unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -687,7 +687,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 
 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
+const unsafe impl SliceIndex<str> for range::RangeInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -733,7 +733,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// `is_char_boundary`, or equal to `len`), or if `end >= len`.
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
+const unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
@@ -779,7 +779,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
 /// `is_char_boundary`, or equal to `len`), or if `last >= len`.
 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
 #[rustc_const_unstable(feature = "const_index", issue = "143775")]
-unsafe impl const SliceIndex<str> for range::RangeToInclusive<usize> {
+const unsafe impl SliceIndex<str> for range::RangeToInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 8a9a0b5..4f2faa7 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2504,7 +2504,7 @@ pub const fn as_ptr(&self) -> *mut *mut T {
 #[cfg(target_has_atomic_load_store = "8")]
 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const From<bool> for AtomicBool {
+const impl From<bool> for AtomicBool {
     /// Converts a `bool` into an `AtomicBool`.
     ///
     /// # Examples
@@ -2523,7 +2523,7 @@ fn from(b: bool) -> Self {
 #[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "atomic_from", since = "1.23.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<*mut T> for AtomicPtr<T> {
+const impl<T> From<*mut T> for AtomicPtr<T> {
     /// Converts a `*mut T` into an `AtomicPtr<T>`.
     #[inline]
     fn from(p: *mut T) -> Self {
diff --git a/library/core/src/sync/sync_view.rs b/library/core/src/sync/sync_view.rs
index 46ad411..3b02c4c 100644
--- a/library/core/src/sync/sync_view.rs
+++ b/library/core/src/sync/sync_view.rs
@@ -97,7 +97,7 @@ unsafe impl<T: ?Sized> Sync for SyncView<T> {}
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for SyncView<T>
+const impl<T> Default for SyncView<T>
 where
     T: [const] Default,
 {
@@ -197,7 +197,7 @@ pub const fn as_pin(self: Pin<&Self>) -> Pin<&T> {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for SyncView<T> {
+const impl<T> From<T> for SyncView<T> {
     #[inline]
     fn from(t: T) -> Self {
         Self::new(t)
@@ -206,7 +206,7 @@ fn from(t: T) -> Self {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-impl<F, Args> const FnOnce<Args> for SyncView<F>
+const impl<F, Args> FnOnce<Args> for SyncView<F>
 where
     F: [const] FnOnce<Args>,
     Args: Tuple,
@@ -220,7 +220,7 @@ extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-impl<F, Args> const FnMut<Args> for SyncView<F>
+const impl<F, Args> FnMut<Args> for SyncView<F>
 where
     F: [const] FnMut<Args>,
     Args: Tuple,
@@ -232,7 +232,7 @@ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")]
-impl<F, Args> const Fn<Args> for SyncView<F>
+const impl<F, Args> Fn<Args> for SyncView<F>
 where
     F: Sync + [const] Fn<Args>,
     Args: Tuple,
@@ -313,7 +313,7 @@ fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Ret
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const AsRef<T> for SyncView<T>
+const impl<T> AsRef<T> for SyncView<T>
 where
     T: Sync + ?Sized,
 {
@@ -326,7 +326,7 @@ fn as_ref(&self) -> &T {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const AsMut<T> for SyncView<T>
+const impl<T> AsMut<T> for SyncView<T>
 where
     T: ?Sized,
 {
@@ -339,7 +339,7 @@ fn as_mut(&mut self) -> &mut T {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-impl<T> const Clone for SyncView<T>
+const impl<T> Clone for SyncView<T>
 where
     T: Sync + [const] Clone,
 {
@@ -352,14 +352,14 @@ fn clone(&self) -> Self {
 #[doc(hidden)]
 #[unstable(feature = "trivial_clone", issue = "none")]
 #[rustc_const_unstable(feature = "const_clone", issue = "142757")]
-unsafe impl<T> const TrivialClone for SyncView<T> where T: Sync + [const] TrivialClone {}
+const unsafe impl<T> TrivialClone for SyncView<T> where T: Sync + [const] TrivialClone {}
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 impl<T> Copy for SyncView<T> where T: Sync + Copy {}
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U> const PartialEq<SyncView<U>> for SyncView<T>
+const impl<T, U> PartialEq<SyncView<U>> for SyncView<T>
 where
     T: Sync + [const] PartialEq<U> + ?Sized,
     U: Sync + ?Sized,
@@ -375,7 +375,7 @@ impl<T> StructuralPartialEq for SyncView<T> where T: Sync + StructuralPartialEq
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const Eq for SyncView<T> where T: Sync + [const] Eq + ?Sized {}
+const impl<T> Eq for SyncView<T> where T: Sync + [const] Eq + ?Sized {}
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 impl<T> Hash for SyncView<T>
@@ -390,7 +390,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T, U> const PartialOrd<SyncView<U>> for SyncView<T>
+const impl<T, U> PartialOrd<SyncView<U>> for SyncView<T>
 where
     T: Sync + [const] PartialOrd<U> + ?Sized,
     U: Sync + ?Sized,
@@ -403,7 +403,7 @@ fn partial_cmp(&self, other: &SyncView<U>) -> Option<Ordering> {
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-impl<T> const Ord for SyncView<T>
+const impl<T> Ord for SyncView<T>
 where
     T: Sync + [const] Ord + ?Sized,
 {
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 380abac..87f8830 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -216,7 +216,7 @@ pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
 
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl<T> const From<T> for Poll<T> {
+const impl<T> From<T> for Poll<T> {
     /// Moves the value into a [`Poll::Ready`] to make a `Poll<T>`.
     ///
     /// # Example
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index c22a9da..14f0980 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -946,7 +946,7 @@ fn clone_from(&mut self, source: &Self) {
 
 #[unstable(feature = "local_waker", issue = "118959")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<LocalWaker> for Waker {
+const impl AsRef<LocalWaker> for Waker {
     fn as_ref(&self) -> &LocalWaker {
         // SAFETY: LocalWaker is just Waker without thread safety
         unsafe { transmute(self) }
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 9073131..682a61a 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1249,7 +1249,7 @@ pub const fn div_duration_ceil(self, rhs: Duration) -> u128 {
 
 #[stable(feature = "duration", since = "1.3.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Add for Duration {
+const impl Add for Duration {
     type Output = Duration;
 
     #[inline]
@@ -1260,7 +1260,7 @@ fn add(self, rhs: Duration) -> Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const AddAssign for Duration {
+const impl AddAssign for Duration {
     #[inline]
     fn add_assign(&mut self, rhs: Duration) {
         *self = *self + rhs;
@@ -1269,7 +1269,7 @@ fn add_assign(&mut self, rhs: Duration) {
 
 #[stable(feature = "duration", since = "1.3.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Sub for Duration {
+const impl Sub for Duration {
     type Output = Duration;
 
     #[inline]
@@ -1280,7 +1280,7 @@ fn sub(self, rhs: Duration) -> Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const SubAssign for Duration {
+const impl SubAssign for Duration {
     #[inline]
     fn sub_assign(&mut self, rhs: Duration) {
         *self = *self - rhs;
@@ -1289,7 +1289,7 @@ fn sub_assign(&mut self, rhs: Duration) {
 
 #[stable(feature = "duration", since = "1.3.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Mul<u32> for Duration {
+const impl Mul<u32> for Duration {
     type Output = Duration;
 
     #[inline]
@@ -1300,7 +1300,7 @@ fn mul(self, rhs: u32) -> Duration {
 
 #[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Mul<Duration> for u32 {
+const impl Mul<Duration> for u32 {
     type Output = Duration;
 
     #[inline]
@@ -1311,7 +1311,7 @@ fn mul(self, rhs: Duration) -> Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const MulAssign<u32> for Duration {
+const impl MulAssign<u32> for Duration {
     #[inline]
     fn mul_assign(&mut self, rhs: u32) {
         *self = *self * rhs;
@@ -1320,7 +1320,7 @@ fn mul_assign(&mut self, rhs: u32) {
 
 #[stable(feature = "duration", since = "1.3.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Div<u32> for Duration {
+const impl Div<u32> for Duration {
     type Output = Duration;
 
     #[inline]
@@ -1332,7 +1332,7 @@ fn div(self, rhs: u32) -> Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const DivAssign<u32> for Duration {
+const impl DivAssign<u32> for Duration {
     #[inline]
     #[track_caller]
     fn div_assign(&mut self, rhs: u32) {
diff --git a/library/coretests/tests/array.rs b/library/coretests/tests/array.rs
index 20c7a39..5b35d05 100644
--- a/library/coretests/tests/array.rs
+++ b/library/coretests/tests/array.rs
@@ -798,7 +798,7 @@ const fn extra_const_array_ops() {
         { std::array::from_fn(const |i| i + 4).map(const |x| x * 2).map(const |x| x as _) };
     let y = 4;
     struct Z(u16);
-    impl const Drop for Z {
+    const impl Drop for Z {
         fn drop(&mut self) {}
     }
     let w = Z(2);
diff --git a/library/coretests/tests/char.rs b/library/coretests/tests/char.rs
index 877017f..4337200 100644
--- a/library/coretests/tests/char.rs
+++ b/library/coretests/tests/char.rs
@@ -318,7 +318,7 @@ fn check(input: char, expect: &[u8]) {
         let mut buf = [0; char::MAX_LEN_UTF8];
         let ptr = buf.as_ptr();
         let s = input.encode_utf8(&mut buf);
-        assert_eq!(s.as_ptr() as usize, ptr as usize);
+        assert_eq!(s.as_ptr(), ptr);
         assert!(str::from_utf8(s.as_bytes()).is_ok());
         assert_eq!(s.as_bytes(), expect);
     }
@@ -335,7 +335,7 @@ fn check(input: char, expect: &[u16]) {
         let mut buf = [0; 2];
         let ptr = buf.as_mut_ptr();
         let b = input.encode_utf16(&mut buf);
-        assert_eq!(b.as_mut_ptr() as usize, ptr as usize);
+        assert_eq!(b.as_mut_ptr(), ptr);
         assert_eq!(b, expect);
     }
 
diff --git a/library/coretests/tests/cmp.rs b/library/coretests/tests/cmp.rs
index bb350b1..e6af357 100644
--- a/library/coretests/tests/cmp.rs
+++ b/library/coretests/tests/cmp.rs
@@ -254,13 +254,13 @@ mod const_cmp {
 
     struct S(i32);
 
-    impl const PartialEq for S {
+    const impl PartialEq for S {
         fn eq(&self, other: &Self) -> bool {
             self.0 == other.0
         }
     }
 
-    impl const PartialOrd for S {
+    const impl PartialOrd for S {
         fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
             let ret = match (self.0, other.0) {
                 (a, b) if a > b => Ordering::Greater,
diff --git a/library/coretests/tests/hint.rs b/library/coretests/tests/hint.rs
index d157308..8eeb86b 100644
--- a/library/coretests/tests/hint.rs
+++ b/library/coretests/tests/hint.rs
@@ -3,7 +3,7 @@ fn select_unpredictable_drop() {
     use core::cell::Cell;
 
     struct X<'a>(&'a Cell<bool>);
-    impl const Drop for X<'_> {
+    const impl Drop for X<'_> {
         fn drop(&mut self) {
             self.0.set(true);
         }
diff --git a/library/coretests/tests/io/io_slice.rs b/library/coretests/tests/io/io_slice.rs
new file mode 100644
index 0000000..4639ef2
--- /dev/null
+++ b/library/coretests/tests/io/io_slice.rs
@@ -0,0 +1,100 @@
+use core::io::{IoSlice, IoSliceMut};
+use core::ops::Deref;
+
+#[test]
+fn io_slice_mut_advance_slices() {
+    let mut buf1 = [1; 8];
+    let mut buf2 = [2; 16];
+    let mut buf3 = [3; 8];
+    let mut bufs = &mut [
+        IoSliceMut::new(&mut buf1),
+        IoSliceMut::new(&mut buf2),
+        IoSliceMut::new(&mut buf3),
+    ][..];
+
+    // Only in a single buffer..
+    IoSliceMut::advance_slices(&mut bufs, 1);
+    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+    // Removing a buffer, leaving others as is.
+    IoSliceMut::advance_slices(&mut bufs, 7);
+    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+    // Removing a buffer and removing from the next buffer.
+    IoSliceMut::advance_slices(&mut bufs, 18);
+    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+}
+
+#[test]
+#[should_panic]
+fn io_slice_mut_advance_slices_empty_slice() {
+    let mut empty_bufs = &mut [][..];
+    IoSliceMut::advance_slices(&mut empty_bufs, 1);
+}
+
+#[test]
+#[should_panic]
+fn io_slice_mut_advance_slices_beyond_total_length() {
+    let mut buf1 = [1; 8];
+    let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
+
+    IoSliceMut::advance_slices(&mut bufs, 9);
+    assert!(bufs.is_empty());
+}
+
+#[test]
+fn io_slice_advance_slices() {
+    let buf1 = [1; 8];
+    let buf2 = [2; 16];
+    let buf3 = [3; 8];
+    let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
+
+    // Only in a single buffer..
+    IoSlice::advance_slices(&mut bufs, 1);
+    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+    // Removing a buffer, leaving others as is.
+    IoSlice::advance_slices(&mut bufs, 7);
+    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+    // Removing a buffer and removing from the next buffer.
+    IoSlice::advance_slices(&mut bufs, 18);
+    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+}
+
+#[test]
+#[should_panic]
+fn io_slice_advance_slices_empty_slice() {
+    let mut empty_bufs = &mut [][..];
+    IoSlice::advance_slices(&mut empty_bufs, 1);
+}
+
+#[test]
+#[should_panic]
+fn io_slice_advance_slices_beyond_total_length() {
+    let buf1 = [1; 8];
+    let mut bufs = &mut [IoSlice::new(&buf1)][..];
+
+    IoSlice::advance_slices(&mut bufs, 9);
+    assert!(bufs.is_empty());
+}
+
+#[test]
+fn io_slice_as_slice() {
+    let buf = [1; 8];
+    let slice = IoSlice::new(&buf).as_slice();
+    assert_eq!(slice, buf);
+}
+
+#[test]
+fn io_slice_into_slice() {
+    let mut buf = [1; 8];
+    let slice = IoSliceMut::new(&mut buf).into_slice();
+    assert_eq!(slice, [1; 8]);
+}
diff --git a/library/coretests/tests/io/mod.rs b/library/coretests/tests/io/mod.rs
index a24893a..7683131 100644
--- a/library/coretests/tests/io/mod.rs
+++ b/library/coretests/tests/io/mod.rs
@@ -1 +1,2 @@
 mod borrowed_buf;
+mod io_slice;
diff --git a/library/coretests/tests/iter/adapters/map_windows.rs b/library/coretests/tests/iter/adapters/map_windows.rs
index 994ec08..fa84f9d 100644
--- a/library/coretests/tests/iter/adapters/map_windows.rs
+++ b/library/coretests/tests/iter/adapters/map_windows.rs
@@ -5,7 +5,7 @@
 mod drop_checks {
     //! These tests mainly make sure the elements are correctly dropped.
 
-    use std::sync::atomic::Ordering::SeqCst;
+    use std::sync::atomic::Ordering::{Relaxed, SeqCst};
     use std::sync::atomic::{AtomicBool, AtomicUsize};
 
     #[derive(Debug)]
@@ -143,6 +143,51 @@ fn len_equals_n() {
         check::<5>(5, 1);
         check::<5>(5, 4);
     }
+
+    /// Regression test for #156501
+    #[test]
+    fn panicking_clone() {
+        static CLONE_COUNTER: AtomicUsize = AtomicUsize::new(0);
+        static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
+
+        struct PanickingClone(u8);
+
+        impl Clone for PanickingClone {
+            fn clone(&self) -> Self {
+                if CLONE_COUNTER.fetch_add(1, Relaxed) == 3 {
+                    panic!(
+                        "âšž(· <:::> ·)⚟ aaaaaah its the turbofish monster!!! its gonna eat us all!!!1!"
+                    );
+                }
+
+                Self(self.0)
+            }
+        }
+
+        impl Drop for PanickingClone {
+            fn drop(&mut self) {
+                assert_eq!(self.0, 42);
+
+                DROP_COUNTER.fetch_add(1, Relaxed);
+            }
+        }
+
+        let array = [const { PanickingClone(42) }; 17];
+        let mut iter = array.into_iter().map_windows::<_, (), 17>(|_| ());
+
+        // initialize the buffer
+        iter.next();
+
+        let result = std::panic::catch_unwind(|| {
+            // now do the clones and panic.
+            // this should't try to drop uninitialized memory
+            let _ = iter.clone();
+        });
+
+        assert!(result.is_err());
+
+        assert_eq!(DROP_COUNTER.load(Relaxed), 3);
+    }
 }
 
 #[test]
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index d1e706b..aa6aa14 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -67,6 +67,7 @@
 #![feature(hashmap_internals)]
 #![feature(int_from_ascii)]
 #![feature(int_roundings)]
+#![feature(io_slice_as_bytes)]
 #![feature(ip)]
 #![feature(is_ascii_octdigit)]
 #![feature(iter_advance_by)]
@@ -128,6 +129,7 @@
 // tidy-alphabetical-end
 #![allow(internal_features)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 /// Version of `assert_matches` that ignores fancy runtime printing in const context and uses structural equality.
diff --git a/library/coretests/tests/manually_drop.rs b/library/coretests/tests/manually_drop.rs
index 1638c82..db0cb9c 100644
--- a/library/coretests/tests/manually_drop.rs
+++ b/library/coretests/tests/manually_drop.rs
@@ -40,7 +40,7 @@ fn const_drop_in_place() {
         struct Test<'a>(Dropped<'a>);
 
         struct Dropped<'a>(&'a Cell<usize>);
-        impl const Drop for Dropped<'_> {
+        const impl Drop for Dropped<'_> {
             fn drop(&mut self) {
                 self.0.set(self.0.get() + 1);
             }
diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs
index 93f9454..9dbaf66 100644
--- a/library/coretests/tests/ptr.rs
+++ b/library/coretests/tests/ptr.rs
@@ -384,7 +384,7 @@ fn align_offset_stride_one() {
 #[test]
 fn align_offset_various_strides() {
     unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
-        let numptr = ptr as usize;
+        let numptr = ptr.addr();
         let mut expected = usize::MAX;
         // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
         for el in 0..align {
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
index 2bb62f3..a4db730 100644
--- a/library/coretests/tests/slice.rs
+++ b/library/coretests/tests/slice.rs
@@ -1886,7 +1886,7 @@ fn test_align_to_empty_mid() {
     type Chunk = u32;
     for offset in 0..4 {
         let (_, mid, _) = unsafe { bytes[offset..offset + 1].align_to::<Chunk>() };
-        assert_eq!(mid.as_ptr() as usize % align_of::<Chunk>(), 0);
+        assert_eq!(mid.as_ptr().addr() % align_of::<Chunk>(), 0);
     }
 }
 
diff --git a/library/coretests/tests/waker.rs b/library/coretests/tests/waker.rs
index 4889b89..be8b07b 100644
--- a/library/coretests/tests/waker.rs
+++ b/library/coretests/tests/waker.rs
@@ -5,16 +5,16 @@
 fn test_waker_getters() {
     let raw_waker = RawWaker::new(ptr::without_provenance_mut(42usize), &WAKER_VTABLE);
     let waker = unsafe { Waker::from_raw(raw_waker) };
-    assert_eq!(waker.data() as usize, 42);
+    assert_eq!(waker.data().addr(), 42);
     assert!(ptr::eq(waker.vtable(), &WAKER_VTABLE));
 
     let waker2 = waker.clone();
-    assert_eq!(waker2.data() as usize, 43);
+    assert_eq!(waker2.data().addr(), 43);
     assert!(ptr::eq(waker2.vtable(), &WAKER_VTABLE));
 }
 
 static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
-    |data| RawWaker::new(ptr::without_provenance_mut(data as usize + 1), &WAKER_VTABLE),
+    |data| RawWaker::new(ptr::without_provenance_mut(data.addr() + 1), &WAKER_VTABLE),
     |_| {},
     |_| {},
     |_| {},
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 696cd4e..3d8ad71 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -2,19 +2,9 @@
 
 use std::cell::RefCell;
 use std::marker::PhantomData;
-use std::sync::atomic::AtomicU32;
 
 use super::*;
 
-#[repr(C)]
-pub(super) struct HandleCounters {
-    pub(super) token_stream: AtomicU32,
-    pub(super) span: AtomicU32,
-}
-
-static COUNTERS: HandleCounters =
-    HandleCounters { token_stream: AtomicU32::new(1), span: AtomicU32::new(1) };
-
 pub(crate) struct TokenStream {
     handle: handle::Handle,
 }
@@ -47,6 +37,18 @@ fn decode(r: &mut &[u8], s: &mut S) -> Self {
     }
 }
 
+impl Encode<()> for crate::TokenStream {
+    fn encode(self, w: &mut Buffer, s: &mut ()) {
+        self.0.encode(w, s)
+    }
+}
+
+impl Decode<'_, '_, ()> for crate::TokenStream {
+    fn decode(r: &mut &[u8], s: &mut ()) -> Self {
+        crate::TokenStream(Some(Decode::decode(r, s)))
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub(crate) struct Span {
     handle: handle::Handle,
@@ -209,8 +211,6 @@ pub(crate) fn is_available() -> bool {
 /// and forcing the use of APIs that take/return `S::TokenStream`, server-side.
 #[repr(C)]
 pub struct Client<I, O> {
-    pub(super) handle_counters: &'static HandleCounters,
-
     pub(super) run: extern "C" fn(BridgeConfig<'_>) -> Buffer,
 
     pub(super) _marker: PhantomData<fn(I) -> O>,
@@ -243,14 +243,13 @@ fn maybe_install_panic_hook(force_show_panics: bool) {
 
 /// Client-side helper for handling client panics, entering the bridge,
 /// deserializing input and serializing output.
-// FIXME(eddyb) maybe replace `Bridge::enter` with this?
-fn run_client<A: for<'a, 's> Decode<'a, 's, ()>, R: Encode<()>>(
+fn run_client<A: for<'a, 's> Decode<'a, 's, ()>>(
     config: BridgeConfig<'_>,
-    f: impl FnOnce(A) -> R,
+    f: impl FnOnce(A) -> crate::TokenStream,
 ) -> Buffer {
     let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config;
 
-    panic::catch_unwind(panic::AssertUnwindSafe(|| {
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
         maybe_install_panic_hook(force_show_panics);
 
         // Make sure the symbol store is empty before decoding inputs.
@@ -267,23 +266,12 @@ fn run_client<A: for<'a, 's> Decode<'a, 's, ()>, R: Encode<()>>(
         // Take the `cached_buffer` back out, for the output value.
         buf = RefCell::into_inner(state).cached_buffer;
 
-        // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
-        // from encoding a panic (`Err(e: PanicMessage)`) to avoid
-        // having handles outside the `bridge.enter(|| ...)` scope, and
-        // to catch panics that could happen while encoding the success.
-        //
-        // Note that panics should be impossible beyond this point, but
-        // this is defensively trying to avoid any accidental panicking
-        // reaching the `extern "C"` (which should `abort` but might not
-        // at the moment, so this is also potentially preventing UB).
-        buf.clear();
-        Ok::<_, ()>(output).encode(&mut buf, &mut ());
-    }))
-    .map_err(PanicMessage::from)
-    .unwrap_or_else(|e| {
-        buf.clear();
-        Err::<(), _>(e).encode(&mut buf, &mut ());
-    });
+        output
+    }));
+
+    // Serialize response of type `Result<R, PanicMessage>`.
+    buf.clear();
+    res.map_err(PanicMessage::from).encode(&mut buf, &mut ());
 
     // Now that a response has been serialized, invalidate all symbols
     // registered with the interner.
@@ -294,9 +282,8 @@ fn run_client<A: for<'a, 's> Decode<'a, 's, ()>, R: Encode<()>>(
 impl Client<crate::TokenStream, crate::TokenStream> {
     pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self {
         Client {
-            handle_counters: &COUNTERS,
             run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
-                run_client(bridge, |input| f(crate::TokenStream(Some(input))).0)
+                run_client(bridge, |input| f(input))
             }),
             _marker: PhantomData,
         }
@@ -308,11 +295,8 @@ pub const fn expand2(
         f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
     ) -> Self {
         Client {
-            handle_counters: &COUNTERS,
             run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
-                run_client(bridge, |(input, input2)| {
-                    f(crate::TokenStream(Some(input)), crate::TokenStream(Some(input2))).0
-                })
+                run_client(bridge, |(input, input2)| f(input, input2))
             }),
             _marker: PhantomData,
         }
diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs
index 2ada1820..8804cf8 100644
--- a/library/proc_macro/src/bridge/rpc.rs
+++ b/library/proc_macro/src/bridge/rpc.rs
@@ -15,20 +15,30 @@ pub(super) trait Decode<'a, 's, S>: Sized {
 }
 
 macro_rules! rpc_encode_decode {
-    (le $ty:ty) => {
+    (le $ty:ident $size:literal) => {
         impl<S> Encode<S> for $ty {
             fn encode(self, w: &mut Buffer, _: &mut S) {
-                w.extend_from_array(&self.to_le_bytes());
+                const N: usize = size_of::<$ty>();
+
+                // We can pad with zeros without changing the value because of
+                // little endian encoding.
+                let mut bytes = [0; $size];
+                bytes[..N].copy_from_slice(&self.to_le_bytes());
+
+                w.extend_from_array(&bytes);
             }
         }
 
         impl<S> Decode<'_, '_, S> for $ty {
             fn decode(r: &mut &[u8], _: &mut S) -> Self {
                 const N: usize = size_of::<$ty>();
+                const {
+                    assert!(N <= $size);
+                }
 
                 let mut bytes = [0; N];
                 bytes.copy_from_slice(&r[..N]);
-                *r = &r[N..];
+                *r = &r[$size..];
 
                 Self::from_le_bytes(bytes)
             }
@@ -108,8 +118,8 @@ fn decode(r: &mut &[u8], _: &mut S) -> Self {
     }
 }
 
-rpc_encode_decode!(le u32);
-rpc_encode_decode!(le usize);
+rpc_encode_decode!(le u32 4);
+rpc_encode_decode!(le usize 8);
 
 impl<S> Encode<S> for bool {
     fn encode(self, w: &mut Buffer, s: &mut S) {
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 1151798..6a739da 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -1,6 +1,7 @@
 //! Server-side traits.
 
 use std::cell::Cell;
+use std::sync::atomic::AtomicU32;
 use std::sync::mpsc;
 
 use super::*;
@@ -11,10 +12,13 @@ pub(super) struct HandleStore<S: Server> {
 }
 
 impl<S: Server> HandleStore<S> {
-    fn new(handle_counters: &'static client::HandleCounters) -> Self {
+    fn new() -> Self {
+        static TOKEN_STREAM: AtomicU32 = AtomicU32::new(1);
+        static SPAN: AtomicU32 = AtomicU32::new(1);
+
         HandleStore {
-            token_stream: handle::OwnedStore::new(&handle_counters.token_stream),
-            span: handle::InternedStore::new(&handle_counters.span),
+            token_stream: handle::OwnedStore::new(&TOKEN_STREAM),
+            span: handle::InternedStore::new(&SPAN),
         }
     }
 }
@@ -246,13 +250,12 @@ fn run_server<
     O: for<'a, 's> Decode<'a, 's, HandleStore<S>>,
 >(
     strategy: &impl ExecutionStrategy,
-    handle_counters: &'static client::HandleCounters,
     server: S,
     input: I,
     run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
     force_show_panics: bool,
 ) -> Result<O, PanicMessage> {
-    let mut dispatcher = Dispatcher { handle_store: HandleStore::new(handle_counters), server };
+    let mut dispatcher = Dispatcher { handle_store: HandleStore::new(), server };
 
     let globals = dispatcher.server.globals();
 
@@ -276,16 +279,9 @@ pub fn run<S>(
     where
         S: Server,
     {
-        let client::Client { handle_counters, run, _marker } = *self;
-        run_server(
-            strategy,
-            handle_counters,
-            server,
-            <MarkedTokenStream<S>>::mark(input),
-            run,
-            force_show_panics,
-        )
-        .map(|s| <Option<MarkedTokenStream<S>>>::unmark(s).unwrap_or_default())
+        let client::Client { run, _marker } = *self;
+        run_server(strategy, server, <MarkedTokenStream<S>>::mark(input), run, force_show_panics)
+            .map(|s| <Option<MarkedTokenStream<S>>>::unmark(s).unwrap_or_default())
     }
 }
 
@@ -301,10 +297,9 @@ pub fn run<S>(
     where
         S: Server,
     {
-        let client::Client { handle_counters, run, _marker } = *self;
+        let client::Client { run, _marker } = *self;
         run_server(
             strategy,
-            handle_counters,
             server,
             (<MarkedTokenStream<S>>::mark(input), <MarkedTokenStream<S>>::mark(input2)),
             run,
diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs
index a8265a3..d268090 100644
--- a/library/rtstartup/rsbegin.rs
+++ b/library/rtstartup/rsbegin.rs
@@ -39,8 +39,7 @@ trait Copy {}
 
 impl<T: PointeeSized> Copy for *mut T {}
 
-#[cfg_attr(not(bootstrap), lang = "drop_glue")]
-#[cfg_attr(bootstrap, lang = "drop_in_place")]
+#[lang = "drop_glue"]
 #[inline]
 pub unsafe fn drop_glue<T: PointeeSized>(_to_drop: &mut T) {}
 
diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs
index 2e69559..8121135 100644
--- a/library/rtstartup/rsend.rs
+++ b/library/rtstartup/rsend.rs
@@ -27,8 +27,7 @@ trait Copy {}
 
 impl<T: PointeeSized> Copy for *mut T {}
 
-#[cfg_attr(not(bootstrap), lang = "drop_glue")]
-#[cfg_attr(bootstrap, lang = "drop_in_place")]
+#[lang = "drop_glue"]
 #[inline]
 pub unsafe fn drop_glue<T: PointeeSized>(_to_drop: &mut T) {}
 
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index ed0322e..7a576e0 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -142,7 +142,7 @@ impl System {
     #[inline]
     fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
         match layout.size() {
-            0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
+            0 => Ok(layout.dangling_ptr().cast_slice(0)),
             // SAFETY: `layout` is non-zero in size,
             size => unsafe {
                 let raw_ptr = if zeroed {
@@ -151,7 +151,7 @@ fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, Allo
                     GlobalAlloc::alloc(self, layout)
                 };
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
-                Ok(NonNull::slice_from_raw_parts(ptr, size))
+                Ok(ptr.cast_slice(size))
             },
         }
     }
@@ -187,7 +187,7 @@ unsafe fn grow_impl(
                 if zeroed {
                     raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
                 }
-                Ok(NonNull::slice_from_raw_parts(ptr, new_size))
+                Ok(ptr.cast_slice(new_size))
             },
 
             // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
@@ -266,7 +266,7 @@ unsafe fn shrink(
             // SAFETY: conditions must be upheld by the caller
             0 => unsafe {
                 Allocator::deallocate(self, ptr, old_layout);
-                Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
+                Ok(new_layout.dangling_ptr().cast_slice(0))
             },
 
             // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
@@ -276,7 +276,7 @@ unsafe fn shrink(
 
                 let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
-                Ok(NonNull::slice_from_raw_parts(ptr, new_size))
+                Ok(ptr.cast_slice(new_size))
             },
 
             // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index a7a9b79..887efd1 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1486,7 +1486,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<K, V, S> const Default for HashMap<K, V, S>
+const impl<K, V, S> Default for HashMap<K, V, S>
 where
     S: [const] Default,
 {
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index fadd626..b0a8e8f 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -1276,7 +1276,7 @@ fn extend_reserve(&mut self, additional: usize) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T, S> const Default for HashSet<T, S>
+const impl<T, S> Default for HashSet<T, S>
 where
     S: [const] Default,
 {
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 150ce9c..a4a5e85 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -220,14 +220,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
-    _var(key.as_ref())
-}
-
-fn _var(key: &OsStr) -> Result<String, VarError> {
-    match var_os(key) {
-        Some(s) => s.into_string().map_err(VarError::NotUnicode),
-        None => Err(VarError::NotPresent),
+    fn inner(key: &OsStr) -> Result<String, VarError> {
+        env_imp::getenv(key)
+            .ok_or(VarError::NotPresent)?
+            .into_string()
+            .map_err(VarError::NotUnicode)
     }
+    inner(key.as_ref())
 }
 
 /// Fetches the environment variable `key` from the current process, returning
@@ -257,11 +256,7 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 #[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
-    _var_os(key.as_ref())
-}
-
-fn _var_os(key: &OsStr) -> Option<OsString> {
-    env_imp::getenv(key)
+    env_imp::getenv(key.as_ref())
 }
 
 /// The error type for operations interacting with environment variables.
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index be606ae..4e74479 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -1758,7 +1758,7 @@ fn clone_into(&self, target: &mut OsString) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<OsStr> for OsStr {
+const impl AsRef<OsStr> for OsStr {
     #[inline]
     fn as_ref(&self) -> &OsStr {
         self
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 20e2841..3f0db7a 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1598,6 +1598,25 @@ pub fn open_file<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
             .open_file(path.as_ref(), &OpenOptions::new().read(true).0)
             .map(|f| File { inner: f })
     }
+
+    /// Queries metadata about the underlying directory.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(dirfd)]
+    /// use std::fs::Dir;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let dir = Dir::open("foo")?;
+    ///     let metadata = dir.metadata()?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "dirfd", issue = "120426")]
+    pub fn metadata(&self) -> io::Result<Metadata> {
+        self.inner.metadata().map(Metadata)
+    }
 }
 
 impl AsInner<fs_imp::Dir> for Dir {
@@ -2147,6 +2166,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+impl IntoInner<fs_imp::FileAttr> for Metadata {
+    fn into_inner(self) -> fs_imp::FileAttr {
+        self.0
+    }
+}
+
 impl AsInner<fs_imp::FileAttr> for Metadata {
     #[inline]
     fn as_inner(&self) -> &fs_imp::FileAttr {
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 39015ef..62afcfe 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -2363,6 +2363,9 @@ fn test_fs_set_times_follows_symlink() {
     use crate::os::windows::fs::FileTimesExt;
 
     let tmp = tmpdir();
+    if !got_symlink_permission(&tmp) {
+        return;
+    }
 
     // Create a target file
     let target = tmp.join("target");
@@ -2461,6 +2464,9 @@ fn test_fs_set_times_nofollow() {
     use crate::os::windows::fs::FileTimesExt;
 
     let tmp = tmpdir();
+    if !got_symlink_permission(&tmp) {
+        return;
+    }
 
     // Create a target file and a symlink to it
     let target = tmp.join("target");
@@ -2545,3 +2551,11 @@ fn test_dir_read_file() {
     let buf = check!(io::read_to_string(f));
     assert_eq!("bar", &buf);
 }
+
+#[test]
+fn test_dir_metadata() {
+    let tmpdir = tmpdir();
+    let dir = check!(Dir::open(tmpdir.path()));
+    let metadata = check!(dir.metadata());
+    assert!(metadata.is_dir());
+}
diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs
index 3c1b21e..b9c21ab 100644
--- a/library/std/src/hash/random.rs
+++ b/library/std/src/hash/random.rs
@@ -110,7 +110,7 @@ pub const fn new() -> DefaultHasher {
 
 #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl const Default for DefaultHasher {
+const impl Default for DefaultHasher {
     /// Creates a new `DefaultHasher` using [`new`].
     /// See its documentation for more.
     ///
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 43a6a18..9109257 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -301,6 +301,8 @@
 pub use core::io::{BorrowedBuf, BorrowedCursor};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::io::{Chain, Empty, Repeat, Sink, Take, empty, repeat, sink};
+#[stable(feature = "iovec", since = "1.36.0")]
+pub use core::io::{IoSlice, IoSliceMut};
 use core::slice::memchr;
 
 #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
@@ -331,9 +333,8 @@
     error::{Error, ErrorKind, Result},
     stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout},
 };
-use crate::mem::{MaybeUninit, take};
-use crate::ops::{Deref, DerefMut};
-use crate::{cmp, fmt, slice, str, sys};
+use crate::mem::MaybeUninit;
+use crate::{cmp, fmt, slice, str};
 
 mod buffered;
 pub(crate) mod copy;
@@ -1332,323 +1333,6 @@ pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
     Ok(buf)
 }
 
-/// A buffer type used with `Read::read_vectored`.
-///
-/// It is semantically a wrapper around a `&mut [u8]`, but is guaranteed to be
-/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
-/// Windows.
-#[stable(feature = "iovec", since = "1.36.0")]
-#[repr(transparent)]
-pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>);
-
-#[stable(feature = "iovec_send_sync", since = "1.44.0")]
-unsafe impl<'a> Send for IoSliceMut<'a> {}
-
-#[stable(feature = "iovec_send_sync", since = "1.44.0")]
-unsafe impl<'a> Sync for IoSliceMut<'a> {}
-
-#[stable(feature = "iovec", since = "1.36.0")]
-impl<'a> fmt::Debug for IoSliceMut<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.0.as_slice(), fmt)
-    }
-}
-
-impl<'a> IoSliceMut<'a> {
-    /// Creates a new `IoSliceMut` wrapping a byte slice.
-    ///
-    /// # Panics
-    ///
-    /// Panics on Windows if the slice is larger than 4GB.
-    #[stable(feature = "iovec", since = "1.36.0")]
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut(sys::io::IoSliceMut::new(buf))
-    }
-
-    /// Advance the internal cursor of the slice.
-    ///
-    /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
-    /// multiple buffers.
-    ///
-    /// # Panics
-    ///
-    /// Panics when trying to advance beyond the end of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::io::IoSliceMut;
-    /// use std::ops::Deref;
-    ///
-    /// let mut data = [1; 8];
-    /// let mut buf = IoSliceMut::new(&mut data);
-    ///
-    /// // Mark 3 bytes as read.
-    /// buf.advance(3);
-    /// assert_eq!(buf.deref(), [1; 5].as_ref());
-    /// ```
-    #[stable(feature = "io_slice_advance", since = "1.81.0")]
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0.advance(n)
-    }
-
-    /// Advance a slice of slices.
-    ///
-    /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over.
-    /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified
-    /// to start at that cursor.
-    ///
-    /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes,
-    /// the result will only include the second `IoSliceMut`, advanced by 2 bytes.
-    ///
-    /// # Panics
-    ///
-    /// Panics when trying to advance beyond the end of the slices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::io::IoSliceMut;
-    /// use std::ops::Deref;
-    ///
-    /// let mut buf1 = [1; 8];
-    /// let mut buf2 = [2; 16];
-    /// let mut buf3 = [3; 8];
-    /// let mut bufs = &mut [
-    ///     IoSliceMut::new(&mut buf1),
-    ///     IoSliceMut::new(&mut buf2),
-    ///     IoSliceMut::new(&mut buf3),
-    /// ][..];
-    ///
-    /// // Mark 10 bytes as read.
-    /// IoSliceMut::advance_slices(&mut bufs, 10);
-    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
-    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-    /// ```
-    #[stable(feature = "io_slice_advance", since = "1.81.0")]
-    #[inline]
-    pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
-        // Number of buffers to remove.
-        let mut remove = 0;
-        // Remaining length before reaching n.
-        let mut left = n;
-        for buf in bufs.iter() {
-            if let Some(remainder) = left.checked_sub(buf.len()) {
-                left = remainder;
-                remove += 1;
-            } else {
-                break;
-            }
-        }
-
-        *bufs = &mut take(bufs)[remove..];
-        if bufs.is_empty() {
-            assert!(left == 0, "advancing io slices beyond their length");
-        } else {
-            bufs[0].advance(left);
-        }
-    }
-
-    /// Get the underlying bytes as a mutable slice with the original lifetime.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(io_slice_as_bytes)]
-    /// use std::io::IoSliceMut;
-    ///
-    /// let mut data = *b"abcdef";
-    /// let io_slice = IoSliceMut::new(&mut data);
-    /// io_slice.into_slice()[0] = b'A';
-    ///
-    /// assert_eq!(&data, b"Abcdef");
-    /// ```
-    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
-    pub const fn into_slice(self) -> &'a mut [u8] {
-        self.0.into_slice()
-    }
-}
-
-#[stable(feature = "iovec", since = "1.36.0")]
-impl<'a> Deref for IoSliceMut<'a> {
-    type Target = [u8];
-
-    #[inline]
-    fn deref(&self) -> &[u8] {
-        self.0.as_slice()
-    }
-}
-
-#[stable(feature = "iovec", since = "1.36.0")]
-impl<'a> DerefMut for IoSliceMut<'a> {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut [u8] {
-        self.0.as_mut_slice()
-    }
-}
-
-/// A buffer type used with `Write::write_vectored`.
-///
-/// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be
-/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
-/// Windows.
-#[stable(feature = "iovec", since = "1.36.0")]
-#[derive(Copy, Clone)]
-#[repr(transparent)]
-pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
-
-#[stable(feature = "iovec_send_sync", since = "1.44.0")]
-unsafe impl<'a> Send for IoSlice<'a> {}
-
-#[stable(feature = "iovec_send_sync", since = "1.44.0")]
-unsafe impl<'a> Sync for IoSlice<'a> {}
-
-#[stable(feature = "iovec", since = "1.36.0")]
-impl<'a> fmt::Debug for IoSlice<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.0.as_slice(), fmt)
-    }
-}
-
-impl<'a> IoSlice<'a> {
-    /// Creates a new `IoSlice` wrapping a byte slice.
-    ///
-    /// # Panics
-    ///
-    /// Panics on Windows if the slice is larger than 4GB.
-    #[stable(feature = "iovec", since = "1.36.0")]
-    #[must_use]
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice(sys::io::IoSlice::new(buf))
-    }
-
-    /// Advance the internal cursor of the slice.
-    ///
-    /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
-    /// buffers.
-    ///
-    /// # Panics
-    ///
-    /// Panics when trying to advance beyond the end of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::io::IoSlice;
-    /// use std::ops::Deref;
-    ///
-    /// let data = [1; 8];
-    /// let mut buf = IoSlice::new(&data);
-    ///
-    /// // Mark 3 bytes as read.
-    /// buf.advance(3);
-    /// assert_eq!(buf.deref(), [1; 5].as_ref());
-    /// ```
-    #[stable(feature = "io_slice_advance", since = "1.81.0")]
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0.advance(n)
-    }
-
-    /// Advance a slice of slices.
-    ///
-    /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over.
-    /// If the cursor ends up in the middle of an `IoSlice`, it is modified
-    /// to start at that cursor.
-    ///
-    /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes,
-    /// the result will only include the second `IoSlice`, advanced by 2 bytes.
-    ///
-    /// # Panics
-    ///
-    /// Panics when trying to advance beyond the end of the slices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::io::IoSlice;
-    /// use std::ops::Deref;
-    ///
-    /// let buf1 = [1; 8];
-    /// let buf2 = [2; 16];
-    /// let buf3 = [3; 8];
-    /// let mut bufs = &mut [
-    ///     IoSlice::new(&buf1),
-    ///     IoSlice::new(&buf2),
-    ///     IoSlice::new(&buf3),
-    /// ][..];
-    ///
-    /// // Mark 10 bytes as written.
-    /// IoSlice::advance_slices(&mut bufs, 10);
-    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
-    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-    #[stable(feature = "io_slice_advance", since = "1.81.0")]
-    #[inline]
-    pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
-        // Number of buffers to remove.
-        let mut remove = 0;
-        // Remaining length before reaching n. This prevents overflow
-        // that could happen if the length of slices in `bufs` were instead
-        // accumulated. Those slice may be aliased and, if they are large
-        // enough, their added length may overflow a `usize`.
-        let mut left = n;
-        for buf in bufs.iter() {
-            if let Some(remainder) = left.checked_sub(buf.len()) {
-                left = remainder;
-                remove += 1;
-            } else {
-                break;
-            }
-        }
-
-        *bufs = &mut take(bufs)[remove..];
-        if bufs.is_empty() {
-            assert!(left == 0, "advancing io slices beyond their length");
-        } else {
-            bufs[0].advance(left);
-        }
-    }
-
-    /// Get the underlying bytes as a slice with the original lifetime.
-    ///
-    /// This doesn't borrow from `self`, so is less restrictive than calling
-    /// `.deref()`, which does.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(io_slice_as_bytes)]
-    /// use std::io::IoSlice;
-    ///
-    /// let data = b"abcdef";
-    ///
-    /// let mut io_slice = IoSlice::new(data);
-    /// let tail = &io_slice.as_slice()[3..];
-    ///
-    /// // This works because `tail` doesn't borrow `io_slice`
-    /// io_slice = IoSlice::new(tail);
-    ///
-    /// assert_eq!(io_slice.as_slice(), b"def");
-    /// ```
-    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
-    pub const fn as_slice(self) -> &'a [u8] {
-        self.0.as_slice()
-    }
-}
-
-#[stable(feature = "iovec", since = "1.36.0")]
-impl<'a> Deref for IoSlice<'a> {
-    type Target = [u8];
-
-    #[inline]
-    fn deref(&self) -> &[u8] {
-        self.0.as_slice()
-    }
-}
-
 /// A trait for objects which are byte-oriented sinks.
 ///
 /// Implementors of the `Write` trait are sometimes called 'writers'.
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 12cbb1d..56d3bd6 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -1,10 +1,7 @@
 use super::{BorrowedBuf, Cursor, SeekFrom, repeat};
 use crate::cmp::{self, min};
-use crate::io::{
-    self, BufRead, BufReader, DEFAULT_BUF_SIZE, IoSlice, IoSliceMut, Read, Seek, Write,
-};
+use crate::io::{self, BufRead, BufReader, DEFAULT_BUF_SIZE, IoSlice, Read, Seek, Write};
 use crate::mem::MaybeUninit;
-use crate::ops::Deref;
 
 #[test]
 fn read_until() {
@@ -565,104 +562,6 @@ fn test_read_to_end_capacity() -> io::Result<()> {
     Ok(())
 }
 
-#[test]
-fn io_slice_mut_advance_slices() {
-    let mut buf1 = [1; 8];
-    let mut buf2 = [2; 16];
-    let mut buf3 = [3; 8];
-    let mut bufs = &mut [
-        IoSliceMut::new(&mut buf1),
-        IoSliceMut::new(&mut buf2),
-        IoSliceMut::new(&mut buf3),
-    ][..];
-
-    // Only in a single buffer..
-    IoSliceMut::advance_slices(&mut bufs, 1);
-    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
-    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
-    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
-
-    // Removing a buffer, leaving others as is.
-    IoSliceMut::advance_slices(&mut bufs, 7);
-    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
-    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-
-    // Removing a buffer and removing from the next buffer.
-    IoSliceMut::advance_slices(&mut bufs, 18);
-    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
-}
-
-#[test]
-#[should_panic]
-fn io_slice_mut_advance_slices_empty_slice() {
-    let mut empty_bufs = &mut [][..];
-    IoSliceMut::advance_slices(&mut empty_bufs, 1);
-}
-
-#[test]
-#[should_panic]
-fn io_slice_mut_advance_slices_beyond_total_length() {
-    let mut buf1 = [1; 8];
-    let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
-
-    IoSliceMut::advance_slices(&mut bufs, 9);
-    assert!(bufs.is_empty());
-}
-
-#[test]
-fn io_slice_advance_slices() {
-    let buf1 = [1; 8];
-    let buf2 = [2; 16];
-    let buf3 = [3; 8];
-    let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
-
-    // Only in a single buffer..
-    IoSlice::advance_slices(&mut bufs, 1);
-    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
-    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
-    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
-
-    // Removing a buffer, leaving others as is.
-    IoSlice::advance_slices(&mut bufs, 7);
-    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
-    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-
-    // Removing a buffer and removing from the next buffer.
-    IoSlice::advance_slices(&mut bufs, 18);
-    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
-}
-
-#[test]
-#[should_panic]
-fn io_slice_advance_slices_empty_slice() {
-    let mut empty_bufs = &mut [][..];
-    IoSlice::advance_slices(&mut empty_bufs, 1);
-}
-
-#[test]
-#[should_panic]
-fn io_slice_advance_slices_beyond_total_length() {
-    let buf1 = [1; 8];
-    let mut bufs = &mut [IoSlice::new(&buf1)][..];
-
-    IoSlice::advance_slices(&mut bufs, 9);
-    assert!(bufs.is_empty());
-}
-
-#[test]
-fn io_slice_as_slice() {
-    let buf = [1; 8];
-    let slice = IoSlice::new(&buf).as_slice();
-    assert_eq!(slice, buf);
-}
-
-#[test]
-fn io_slice_into_slice() {
-    let mut buf = [1; 8];
-    let slice = IoSliceMut::new(&mut buf).into_slice();
-    assert_eq!(slice, [1; 8]);
-}
-
 /// Creates a new writer that reads from at most `n_bufs` and reads
 /// `per_call` bytes (in total) per call to write.
 fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index cb0f8ed..addbb40 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -246,6 +246,7 @@
 #![allow(unused_lifetimes)]
 #![allow(internal_features)]
 #![deny(fuzzy_provenance_casts)]
+#![deny(lossy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![allow(rustdoc::redundant_explicit_links)]
 #![warn(rustdoc::unescaped_backticks)]
@@ -289,6 +290,7 @@
 #![feature(f16)]
 #![feature(f128)]
 #![feature(ffi_const)]
+#![feature(gpu_offload)]
 #![feature(intra_doc_pointers)]
 #![feature(lang_items)]
 #![feature(link_cfg)]
@@ -353,6 +355,7 @@
 #![feature(io_error_inprogress)]
 #![feature(io_error_more)]
 #![feature(io_error_uncategorized)]
+#![feature(io_slice_as_bytes)]
 #![feature(ip)]
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
@@ -365,6 +368,7 @@
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
 #![feature(ptr_as_uninit)]
+#![feature(ptr_cast_slice)]
 #![feature(ptr_mask)]
 #![feature(random)]
 #![feature(raw_os_error_ty)]
@@ -661,6 +665,12 @@ pub mod autodiff {
     pub use core::autodiff::{autodiff_forward, autodiff_reverse};
 }
 
+#[unstable(feature = "gpu_offload", issue = "131513")]
+#[doc = include_str!("../../core/src/offload.md")]
+pub mod offload {
+    pub use core::offload::{offload, offload_kernel};
+}
+
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub mod task {
     //! Types and Traits for working with asynchronous tasks.
@@ -714,7 +724,13 @@ pub mod arch {
 mod panicking;
 
 #[path = "../../backtrace/src/lib.rs"]
-#[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)]
+#[allow(
+    dead_code,
+    unused_attributes,
+    fuzzy_provenance_casts,
+    lossy_provenance_casts,
+    unsafe_op_in_unsafe_fn
+)]
 mod backtrace_rs;
 
 #[stable(feature = "cfg_select", since = "1.95.0")]
diff --git a/library/std/src/net/test.rs b/library/std/src/net/test.rs
index 68cbf7b..5002bb5 100644
--- a/library/std/src/net/test.rs
+++ b/library/std/src/net/test.rs
@@ -4,9 +4,6 @@
 use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 use crate::sync::atomic::{AtomicUsize, Ordering};
 
-static PORT: AtomicUsize = AtomicUsize::new(0);
-const BASE_PORT: u16 = 19600;
-
 /// A localhost address whose port will be picked automatically by the OS.
 pub const LOCALHOST_IP4: SocketAddr =
     SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
@@ -14,16 +11,6 @@
 pub const LOCALHOST_IP6: SocketAddr =
     SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0));
 
-pub fn next_test_ip4() -> SocketAddr {
-    let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + BASE_PORT;
-    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port))
-}
-
-pub fn next_test_ip6() -> SocketAddr {
-    let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + BASE_PORT;
-    SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0))
-}
-
 pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
     SocketAddr::V4(SocketAddrV4::new(a, p))
 }
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index 0638b36..ede0240 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -1,15 +1,10 @@
 use crate::io::ErrorKind;
-use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
+use crate::net::test::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid};
 use crate::net::*;
 use crate::sync::mpsc::channel;
 use crate::thread;
 use crate::time::{Duration, Instant};
 
-fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
-    f(next_test_ip4(), next_test_ip4());
-    f(next_test_ip6(), next_test_ip6());
-}
-
 macro_rules! t {
     ($e:expr) => {
         match $e {
@@ -19,6 +14,11 @@ macro_rules! t {
     };
 }
 
+fn each_ip(f: &mut dyn FnMut(UdpSocket, UdpSocket)) {
+    f(t!(UdpSocket::bind(LOCALHOST_IP4)), t!(UdpSocket::bind(LOCALHOST_IP4)));
+    f(t!(UdpSocket::bind(LOCALHOST_IP6)), t!(UdpSocket::bind(LOCALHOST_IP6)));
+}
+
 #[test]
 fn bind_error() {
     match UdpSocket::bind("1.1.1.1:9999") {
@@ -30,18 +30,19 @@ fn bind_error() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // no threads
 fn socket_smoke_test_ip4() {
-    each_ip(&mut |server_ip, client_ip| {
+    each_ip(&mut |server, client| {
+        let server_ip = t!(server.local_addr());
+        let client_ip = t!(client.local_addr());
+
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
 
         let _t = thread::spawn(move || {
-            let client = t!(UdpSocket::bind(&client_ip));
             rx1.recv().unwrap();
             t!(client.send_to(&[99], &server_ip));
             tx2.send(()).unwrap();
         });
 
-        let server = t!(UdpSocket::bind(&server_ip));
         tx1.send(()).unwrap();
         let mut buf = [0];
         let (nread, src) = t!(server.recv_from(&mut buf));
@@ -53,29 +54,28 @@ fn socket_smoke_test_ip4() {
 }
 
 #[test]
-fn socket_name() {
-    each_ip(&mut |addr, _| {
-        let server = t!(UdpSocket::bind(&addr));
-        assert_eq!(addr, t!(server.local_addr()));
-    })
-}
+fn socket_and_peer_name() {
+    each_ip(&mut |sock1, sock2| {
+        let addr1 = t!(sock1.local_addr());
+        let addr2 = t!(sock2.local_addr());
 
-#[test]
-fn socket_peer() {
-    each_ip(&mut |addr1, addr2| {
-        let server = t!(UdpSocket::bind(&addr1));
-        assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
-        t!(server.connect(&addr2));
-        assert_eq!(addr2, t!(server.peer_addr()));
+        assert_eq!(sock1.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
+        assert!(addr1.ip() == LOCALHOST_IP4.ip() || addr1.ip() == LOCALHOST_IP6.ip());
+
+        t!(sock1.connect(addr2));
+        t!(sock2.connect(addr1));
+
+        assert_eq!(addr2, t!(sock1.peer_addr()));
+        assert_eq!(addr1, t!(sock2.peer_addr()));
     })
 }
 
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // no threads
 fn udp_clone_smoke() {
-    each_ip(&mut |addr1, addr2| {
-        let sock1 = t!(UdpSocket::bind(&addr1));
-        let sock2 = t!(UdpSocket::bind(&addr2));
+    each_ip(&mut |sock1, sock2| {
+        let addr1 = t!(sock1.local_addr());
+        let addr2 = t!(sock2.local_addr());
 
         let _t = thread::spawn(move || {
             let mut buf = [0, 0];
@@ -107,9 +107,9 @@ fn udp_clone_smoke() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // no threads
 fn udp_clone_two_read() {
-    each_ip(&mut |addr1, addr2| {
-        let sock1 = t!(UdpSocket::bind(&addr1));
-        let sock2 = t!(UdpSocket::bind(&addr2));
+    each_ip(&mut |sock1, sock2| {
+        let addr1 = t!(sock1.local_addr());
+
         let (tx1, rx) = channel();
         let tx2 = tx1.clone();
 
@@ -140,9 +140,8 @@ fn udp_clone_two_read() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // no threads
 fn udp_clone_two_write() {
-    each_ip(&mut |addr1, addr2| {
-        let sock1 = t!(UdpSocket::bind(&addr1));
-        let sock2 = t!(UdpSocket::bind(&addr2));
+    each_ip(&mut |sock1, sock2| {
+        let addr2 = t!(sock2.local_addr());
 
         let (tx, rx) = channel();
         let (serv_tx, serv_rx) = channel();
@@ -177,9 +176,9 @@ fn udp_clone_two_write() {
 #[test]
 fn debug() {
     let name = if cfg!(windows) { "socket" } else { "fd" };
-    let socket_addr = next_test_ip4();
 
-    let udpsock = t!(UdpSocket::bind(&socket_addr));
+    let udpsock = t!(UdpSocket::bind(LOCALHOST_IP4));
+    let socket_addr = t!(udpsock.local_addr());
     let udpsock_inner = udpsock.0.socket().as_raw();
     let compare = format!("UdpSocket {{ addr: {socket_addr:?}, {name}: {udpsock_inner:?} }}");
     assert_eq!(format!("{udpsock:?}"), compare);
@@ -195,9 +194,7 @@ fn debug() {
 #[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
 #[test]
 fn timeouts() {
-    let addr = next_test_ip4();
-
-    let stream = t!(UdpSocket::bind(&addr));
+    let stream = t!(UdpSocket::bind(LOCALHOST_IP4));
     let dur = Duration::new(15410, 0);
 
     assert_eq!(None, t!(stream.read_timeout()));
@@ -220,9 +217,7 @@ fn timeouts() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
 fn test_read_timeout() {
-    let addr = next_test_ip4();
-
-    let stream = t!(UdpSocket::bind(&addr));
+    let stream = t!(UdpSocket::bind(LOCALHOST_IP4));
     t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
 
     let mut buf = [0; 10];
@@ -245,9 +240,8 @@ fn test_read_timeout() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
 fn test_read_with_timeout() {
-    let addr = next_test_ip4();
-
-    let stream = t!(UdpSocket::bind(&addr));
+    let stream = t!(UdpSocket::bind(LOCALHOST_IP4));
+    let addr = t!(stream.local_addr());
     t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
 
     t!(stream.send_to(b"hello world", &addr));
@@ -275,9 +269,7 @@ fn test_read_with_timeout() {
 // when passed zero Durations
 #[test]
 fn test_timeout_zero_duration() {
-    let addr = next_test_ip4();
-
-    let socket = t!(UdpSocket::bind(&addr));
+    let socket = t!(UdpSocket::bind(LOCALHOST_IP4));
 
     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
     let err = result.unwrap_err();
@@ -290,9 +282,8 @@ fn test_timeout_zero_duration() {
 
 #[test]
 fn connect_send_recv() {
-    let addr = next_test_ip4();
-
-    let socket = t!(UdpSocket::bind(&addr));
+    let socket = t!(UdpSocket::bind(LOCALHOST_IP4));
+    let addr = t!(socket.local_addr());
     t!(socket.connect(addr));
 
     t!(socket.send(b"hello world"));
@@ -305,8 +296,8 @@ fn connect_send_recv() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // peek not supported
 fn connect_send_peek_recv() {
-    each_ip(&mut |addr, _| {
-        let socket = t!(UdpSocket::bind(&addr));
+    each_ip(&mut |socket, _| {
+        let addr = t!(socket.local_addr());
         t!(socket.connect(addr));
 
         t!(socket.send(b"hello world"));
@@ -328,8 +319,8 @@ fn connect_send_peek_recv() {
 #[test]
 #[cfg_attr(target_os = "wasi", ignore)] // peek_from not supported
 fn peek_from() {
-    each_ip(&mut |addr, _| {
-        let socket = t!(UdpSocket::bind(&addr));
+    each_ip(&mut |socket, _| {
+        let addr = t!(socket.local_addr());
         t!(socket.send_to(b"hello world", &addr));
 
         for _ in 1..3 {
@@ -350,9 +341,7 @@ fn peek_from() {
 fn ttl() {
     let ttl = 100;
 
-    let addr = next_test_ip4();
-
-    let stream = t!(UdpSocket::bind(&addr));
+    let stream = t!(UdpSocket::bind(LOCALHOST_IP4));
 
     t!(stream.set_ttl(ttl));
     assert_eq!(ttl, t!(stream.ttl()));
@@ -360,8 +349,8 @@ fn ttl() {
 
 #[test]
 fn set_nonblocking() {
-    each_ip(&mut |addr, _| {
-        let socket = t!(UdpSocket::bind(&addr));
+    each_ip(&mut |socket, _| {
+        let addr = t!(socket.local_addr());
 
         t!(socket.set_nonblocking(true));
         t!(socket.set_nonblocking(false));
diff --git a/library/std/src/os/net/linux_ext/tests.rs b/library/std/src/os/net/linux_ext/tests.rs
index 0758b42..02839ee 100644
--- a/library/std/src/os/net/linux_ext/tests.rs
+++ b/library/std/src/os/net/linux_ext/tests.rs
@@ -1,6 +1,6 @@
 #[test]
 fn quickack() {
-    use crate::net::test::next_test_ip4;
+    use crate::net::test::LOCALHOST_IP4;
     use crate::net::{TcpListener, TcpStream};
     use crate::os::net::linux_ext::tcp::TcpStreamExt;
 
@@ -13,8 +13,8 @@ macro_rules! t {
         };
     }
 
-    let addr = next_test_ip4();
-    let _listener = t!(TcpListener::bind(&addr));
+    let listener = t!(TcpListener::bind(LOCALHOST_IP4));
+    let addr = t!(listener.local_addr());
 
     let stream = t!(TcpStream::connect(&("localhost", addr.port())));
 
@@ -29,7 +29,7 @@ macro_rules! t {
 #[test]
 #[cfg(target_os = "linux")]
 fn deferaccept() {
-    use crate::net::test::next_test_ip4;
+    use crate::net::test::LOCALHOST_IP4;
     use crate::net::{TcpListener, TcpStream};
     use crate::os::net::linux_ext::tcp::TcpStreamExt;
     use crate::time::Duration;
@@ -43,10 +43,11 @@ macro_rules! t {
         };
     }
 
-    let addr = next_test_ip4();
     let one = Duration::from_secs(1u64);
     let zero = Duration::from_secs(0u64);
-    let _listener = t!(TcpListener::bind(&addr));
+
+    let listener = t!(TcpListener::bind(LOCALHOST_IP4));
+    let addr = t!(listener.local_addr());
     let stream = t!(TcpStream::connect(&("localhost", addr.port())));
     stream.set_deferaccept(one).expect("set_deferaccept failed");
     assert_eq!(stream.deferaccept().unwrap(), one);
diff --git a/library/std/src/os/unix/thread.rs b/library/std/src/os/unix/thread.rs
index 32085e5..efb349b 100644
--- a/library/std/src/os/unix/thread.rs
+++ b/library/std/src/os/unix/thread.rs
@@ -31,10 +31,15 @@ pub trait JoinHandleExt {
 
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 impl<T> JoinHandleExt for JoinHandle<T> {
+    // This is an int2ptr cast on some platforms (e.g., *-musl) where RawPthread
+    // is an integer but libc::pthread_t is a pointer. Exposed provenance is the
+    // safe choice here, but `as` also works when it's int2int or ptr2ptr.
+    #[allow(lossy_provenance_casts)]
     fn as_pthread_t(&self) -> RawPthread {
         self.as_inner().id() as RawPthread
     }
 
+    #[allow(lossy_provenance_casts)] // see above for why
     fn into_pthread_t(self) -> RawPthread {
         self.into_inner().into_id() as RawPthread
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 222bf77..2d1f6a2 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2854,7 +2854,6 @@ fn _ends_with(&self, child: &Path) -> bool {
     /// # Examples
     ///
     /// ```
-    /// #![feature(path_is_empty)]
     /// use std::path::Path;
     ///
     /// let path = Path::new("");
@@ -2866,7 +2865,7 @@ fn _ends_with(&self, child: &Path) -> bool {
     /// let path = Path::new(".");
     /// assert!(!path.is_empty());
     /// ```
-    #[unstable(feature = "path_is_empty", issue = "148494")]
+    #[stable(feature = "path_is_empty", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_empty(&self) -> bool {
         self.as_os_str().is_empty()
     }
@@ -3690,7 +3689,7 @@ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<OsStr> for Path {
+const impl AsRef<OsStr> for Path {
     #[inline]
     fn as_ref(&self) -> &OsStr {
         &self.inner
@@ -3861,7 +3860,7 @@ fn cmp(&self, other: &Path) -> cmp::Ordering {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<Path> for Path {
+const impl AsRef<Path> for Path {
     #[inline]
     fn as_ref(&self) -> &Path {
         self
@@ -3870,7 +3869,7 @@ fn as_ref(&self) -> &Path {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
-impl const AsRef<Path> for OsStr {
+const impl AsRef<Path> for OsStr {
     #[inline]
     fn as_ref(&self) -> &Path {
         Path::new(self)
diff --git a/library/std/src/random.rs b/library/std/src/random.rs
index a18dcf9..8274060 100644
--- a/library/std/src/random.rs
+++ b/library/std/src/random.rs
@@ -16,6 +16,8 @@
 /// security is not a concern,  consider using an alternative random number
 /// generator (potentially seeded from this one).
 ///
+/// If you need to fill a buffer with random bytes, use `DefaultRandomSource.fill_bytes(&mut buf)`.
+///
 /// # Underlying sources
 ///
 /// Platform               | Source
@@ -54,6 +56,7 @@
 ///
 /// [`getrandom`]: https://www.man7.org/linux/man-pages/man2/getrandom.2.html
 /// [`/dev/urandom`]: https://www.man7.org/linux/man-pages/man4/random.4.html
+#[doc(alias = "getrandom", alias = "getentropy", alias = "arc4random")]
 #[derive(Default, Debug, Clone, Copy)]
 #[unstable(feature = "random", issue = "130703")]
 pub struct DefaultRandomSource;
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 2f2579e..9bb2528 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -376,7 +376,7 @@ fn deref_mut(&mut self) -> &mut T {
 
 #[stable(feature = "lazy_cell", since = "1.80.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T: Default> const Default for LazyLock<T> {
+const impl<T: Default> Default for LazyLock<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
     fn default() -> LazyLock<T> {
diff --git a/library/std/src/sync/mpmc/select.rs b/library/std/src/sync/mpmc/select.rs
index 56a83fe..ff537aa 100644
--- a/library/std/src/sync/mpmc/select.rs
+++ b/library/std/src/sync/mpmc/select.rs
@@ -22,7 +22,7 @@ impl Operation {
     /// and is alive for the entire duration of a blocking operation.
     #[inline]
     pub fn hook<T>(r: &mut T) -> Operation {
-        let val = r as *mut T as usize;
+        let val = (r as *mut T).addr();
         // Make sure that the pointer address doesn't equal the numerical representation of
         // `Selected::{Waiting, Aborted, Disconnected}`.
         assert!(val > 2);
diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs
index c743462..4f645e1 100644
--- a/library/std/src/sync/mpmc/zero.rs
+++ b/library/std/src/sync/mpmc/zero.rs
@@ -25,7 +25,7 @@ fn default() -> Self {
 
 impl fmt::Debug for ZeroToken {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&(self.0 as usize), f)
+        fmt::Debug::fmt(&self.0.addr(), f)
     }
 }
 
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index f6ea3c1..8e69e7a 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -592,7 +592,7 @@ impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
 
 #[stable(feature = "once_cell", since = "1.70.0")]
 #[rustc_const_unstable(feature = "const_default", issue = "143894")]
-impl<T> const Default for OnceLock<T> {
+const impl<T> Default for OnceLock<T> {
     /// Creates a new uninitialized cell.
     ///
     /// # Example
diff --git a/library/std/src/sys/args/sgx.rs b/library/std/src/sys/args/sgx.rs
index 6ff94f5..9403059 100644
--- a/library/std/src/sys/args/sgx.rs
+++ b/library/std/src/sys/args/sgx.rs
@@ -1,4 +1,5 @@
-#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
+// FIXME: this module systematically confuses pointers and integers
+#![allow(fuzzy_provenance_casts, lossy_provenance_casts)]
 
 use crate::ffi::OsString;
 use crate::num::NonZero;
diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs
index 09090ec..0c19fcc 100644
--- a/library/std/src/sys/env/sgx.rs
+++ b/library/std/src/sys/env/sgx.rs
@@ -1,4 +1,5 @@
-#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
+// FIXME: this module systematically confuses pointers and integers
+#![allow(fuzzy_provenance_casts, lossy_provenance_casts)]
 
 pub use super::common::Env;
 use crate::collections::HashMap;
diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs
index 4d47d39..0df91d5 100644
--- a/library/std/src/sys/fs/common.rs
+++ b/library/std/src/sys/fs/common.rs
@@ -2,7 +2,8 @@
 
 use crate::io::{self, Error, ErrorKind};
 use crate::path::{Path, PathBuf};
-use crate::sys::fs::{File, OpenOptions};
+use crate::sys::IntoInner;
+use crate::sys::fs::{File, FileAttr, OpenOptions};
 use crate::sys::helpers::ignore_notfound;
 use crate::{fmt, fs};
 
@@ -72,6 +73,10 @@ pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<Self> {
     pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
         File::open(&self.path.join(path), &opts)
     }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        self.path.metadata().map(|m| m.into_inner())
+    }
 }
 
 impl fmt::Debug for Dir {
diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs
index 094d1bf..b3b4d25 100644
--- a/library/std/src/sys/fs/unix/dir.rs
+++ b/library/std/src/sys/fs/unix/dir.rs
@@ -25,7 +25,7 @@
 use crate::path::Path;
 use crate::sys::fd::FileDesc;
 use crate::sys::fs::OpenOptions;
-use crate::sys::fs::unix::{File, debug_path_fd};
+use crate::sys::fs::unix::{File, FileAttr, debug_path_fd};
 use crate::sys::helpers::run_path_with_cstr;
 use crate::sys::{AsInner, FromInner, IntoInner, cvt_r};
 use crate::{fmt, fs, io};
@@ -41,6 +41,16 @@ pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
         run_path_with_cstr(path.as_ref(), &|path| self.open_file_c(path, &opts))
     }
 
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        // Reuse the implementation for files, which should work for all FDs.
+        let fd = self.0.as_raw_fd();
+        let f = core::mem::ManuallyDrop::new(File(
+            // SAFETY: we borrowed `self` so the FD will not be closed while this function runs.
+            unsafe { FileDesc::from_raw_fd(fd) },
+        ));
+        f.file_attr()
+    }
+
     pub fn open_with_c(path: &CStr, opts: &OpenOptions) -> io::Result<Self> {
         let flags = libc::O_CLOEXEC
             | libc::O_DIRECTORY
diff --git a/library/std/src/sys/fs/windows/dir.rs b/library/std/src/sys/fs/windows/dir.rs
index 3f61780..d8203cf 100644
--- a/library/std/src/sys/fs/windows/dir.rs
+++ b/library/std/src/sys/fs/windows/dir.rs
@@ -5,7 +5,7 @@
 use crate::path::Path;
 use crate::sys::api::{UnicodeStrRef, WinError};
 use crate::sys::fs::windows::debug_path_handle;
-use crate::sys::fs::{File, OpenOptions};
+use crate::sys::fs::{File, FileAttr, OpenOptions};
 use crate::sys::handle::Handle;
 use crate::sys::path::{WCStr, with_native_path};
 use crate::sys::{AsInner, FromInner, IntoInner, IoResult, c, to_u16s};
@@ -101,6 +101,16 @@ fn open_file_native(&self, path: &[u16], opts: &OpenOptions) -> io::Result<Handl
         };
         unsafe { nt_create_file(opts, &object_attributes, c::FILE_NON_DIRECTORY_FILE) }
     }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        // Reuse the implementation for files, which should work for all handles.
+        let handle = self.handle.as_raw_handle();
+        let f = core::mem::ManuallyDrop::new(File {
+            // SAFETY: we borrowed `self` so the handle will not be closed while this function runs.
+            handle: unsafe { Handle::from_raw_handle(handle) },
+        });
+        f.file_attr()
+    }
 }
 
 impl fmt::Debug for Dir {
diff --git a/library/std/src/sys/io/io_slice/iovec.rs b/library/std/src/sys/io/io_slice/iovec.rs
deleted file mode 100644
index d549aca..0000000
--- a/library/std/src/sys/io/io_slice/iovec.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-#[cfg(target_os = "hermit")]
-use hermit_abi::iovec;
-#[cfg(any(target_family = "unix", target_os = "trusty", target_os = "wasi"))]
-use libc::iovec;
-
-use crate::ffi::c_void;
-use crate::marker::PhantomData;
-use crate::slice;
-#[cfg(target_os = "solid_asp3")]
-use crate::sys::pal::abi::sockets::iovec;
-
-#[derive(Copy, Clone)]
-#[repr(transparent)]
-pub struct IoSlice<'a> {
-    vec: iovec,
-    _p: PhantomData<&'a [u8]>,
-}
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice {
-            vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() },
-            _p: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        if self.vec.iov_len < n {
-            panic!("advancing IoSlice beyond its length");
-        }
-
-        unsafe {
-            self.vec.iov_len -= n;
-            self.vec.iov_base = self.vec.iov_base.add(n);
-        }
-    }
-
-    #[inline]
-    pub const fn as_slice(&self) -> &'a [u8] {
-        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
-    }
-}
-
-#[repr(transparent)]
-pub struct IoSliceMut<'a> {
-    vec: iovec,
-    _p: PhantomData<&'a mut [u8]>,
-}
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut {
-            vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() },
-            _p: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        if self.vec.iov_len < n {
-            panic!("advancing IoSliceMut beyond its length");
-        }
-
-        unsafe {
-            self.vec.iov_len -= n;
-            self.vec.iov_base = self.vec.iov_base.add(n);
-        }
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
-    }
-
-    #[inline]
-    pub const fn into_slice(self) -> &'a mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
-    }
-}
diff --git a/library/std/src/sys/io/io_slice/uefi.rs b/library/std/src/sys/io/io_slice/uefi.rs
deleted file mode 100644
index 909cfbe..0000000
--- a/library/std/src/sys/io/io_slice/uefi.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-//! A buffer type used with `Write::write_vectored` for UEFI Networking APIs. Vectored writing to
-//! File is not supported as of UEFI Spec 2.11.
-
-use crate::marker::PhantomData;
-use crate::slice;
-
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub struct IoSlice<'a> {
-    len: u32,
-    data: *const u8,
-    _p: PhantomData<&'a [u8]>,
-}
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        let len = buf.len().try_into().unwrap();
-        Self { len, data: buf.as_ptr(), _p: PhantomData }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.len = u32::try_from(n)
-            .ok()
-            .and_then(|n| self.len.checked_sub(n))
-            .expect("advancing IoSlice beyond its length");
-        unsafe { self.data = self.data.add(n) };
-    }
-
-    #[inline]
-    pub const fn as_slice(&self) -> &'a [u8] {
-        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
-    }
-}
-
-#[repr(C)]
-pub struct IoSliceMut<'a> {
-    len: u32,
-    data: *mut u8,
-    _p: PhantomData<&'a mut [u8]>,
-}
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        let len = buf.len().try_into().unwrap();
-        Self { len, data: buf.as_mut_ptr(), _p: PhantomData }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.len = u32::try_from(n)
-            .ok()
-            .and_then(|n| self.len.checked_sub(n))
-            .expect("advancing IoSlice beyond its length");
-        unsafe { self.data = self.data.add(n) };
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
-    }
-
-    #[inline]
-    pub const fn into_slice(self) -> &'a mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
-    }
-}
diff --git a/library/std/src/sys/io/io_slice/unsupported.rs b/library/std/src/sys/io/io_slice/unsupported.rs
deleted file mode 100644
index 1572cac..0000000
--- a/library/std/src/sys/io/io_slice/unsupported.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use crate::mem;
-
-#[derive(Copy, Clone)]
-pub struct IoSlice<'a>(&'a [u8]);
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0 = &self.0[n..]
-    }
-
-    #[inline]
-    pub const fn as_slice(&self) -> &'a [u8] {
-        self.0
-    }
-}
-
-pub struct IoSliceMut<'a>(&'a mut [u8]);
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        let slice = mem::take(&mut self.0);
-        let (_, remaining) = slice.split_at_mut(n);
-        self.0 = remaining;
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-
-    #[inline]
-    pub const fn into_slice(self) -> &'a mut [u8] {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        self.0
-    }
-}
diff --git a/library/std/src/sys/io/io_slice/windows.rs b/library/std/src/sys/io/io_slice/windows.rs
deleted file mode 100644
index c3d8ec8..0000000
--- a/library/std/src/sys/io/io_slice/windows.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use crate::marker::PhantomData;
-use crate::slice;
-use crate::sys::c;
-
-#[derive(Copy, Clone)]
-#[repr(transparent)]
-pub struct IoSlice<'a> {
-    vec: c::WSABUF,
-    _p: PhantomData<&'a [u8]>,
-}
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        assert!(buf.len() <= u32::MAX as usize);
-        IoSlice {
-            vec: c::WSABUF { len: buf.len() as u32, buf: buf.as_ptr() as *mut u8 },
-            _p: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        if (self.vec.len as usize) < n {
-            panic!("advancing IoSlice beyond its length");
-        }
-
-        unsafe {
-            self.vec.len -= n as u32;
-            self.vec.buf = self.vec.buf.add(n);
-        }
-    }
-
-    #[inline]
-    pub const fn as_slice(&self) -> &'a [u8] {
-        unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) }
-    }
-}
-
-#[repr(transparent)]
-pub struct IoSliceMut<'a> {
-    vec: c::WSABUF,
-    _p: PhantomData<&'a mut [u8]>,
-}
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        assert!(buf.len() <= u32::MAX as usize);
-        IoSliceMut {
-            vec: c::WSABUF { len: buf.len() as u32, buf: buf.as_mut_ptr() },
-            _p: PhantomData,
-        }
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        if (self.vec.len as usize) < n {
-            panic!("advancing IoSliceMut beyond its length");
-        }
-
-        unsafe {
-            self.vec.len -= n as u32;
-            self.vec.buf = self.vec.buf.add(n);
-        }
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) }
-    }
-
-    #[inline]
-    pub const fn into_slice(self) -> &'a mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
-    }
-}
diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs
index 445bcde..0158137 100644
--- a/library/std/src/sys/io/mod.rs
+++ b/library/std/src/sys/io/mod.rs
@@ -2,27 +2,6 @@
 
 mod error;
 
-mod io_slice {
-    cfg_select! {
-        any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => {
-            mod iovec;
-            pub use iovec::*;
-        }
-        target_os = "windows" => {
-            mod windows;
-            pub use windows::*;
-        }
-        target_os = "uefi" => {
-            mod uefi;
-            pub use uefi::*;
-        }
-        _ => {
-            mod unsupported;
-            pub use unsupported::*;
-        }
-    }
-}
-
 mod is_terminal {
     cfg_select! {
         any(target_family = "unix", target_os = "wasi") => {
@@ -63,7 +42,6 @@ mod is_terminal {
 ))]
 pub use error::set_errno;
 pub use error::{decode_error_kind, errno, error_string, is_interrupted};
-pub use io_slice::{IoSlice, IoSliceMut};
 pub use is_terminal::is_terminal;
 pub use kernel_copy::{CopyState, kernel_copy};
 
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
index c269431..f4115ca 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
@@ -151,7 +151,7 @@ unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
         let elem_size = size_of::<T>();
         assert_eq!(size % elem_size, 0);
         let len = size / elem_size;
-        ptr::slice_from_raw_parts_mut(ptr as _, len)
+        ptr.cast::<T>().cast_slice(len)
     }
 }
 
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 2b284cc..7b2c8e5 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -3,7 +3,8 @@
 //! This module contains the facade (aka platform-specific) implementations of
 //! OS level functionality for Fortanix SGX.
 #![deny(unsafe_op_in_unsafe_fn)]
-#![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers
+// FIXME: this entire module systematically confuses pointers and integers
+#![allow(fuzzy_provenance_casts, lossy_provenance_casts)]
 
 use crate::io;
 use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs
index 528bc2b..e0c4fa5 100644
--- a/library/std/src/sys/process/uefi.rs
+++ b/library/std/src/sys/process/uefi.rs
@@ -27,11 +27,13 @@ pub struct Command {
     env: CommandEnv,
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Debug)]
 pub enum Stdio {
     Inherit,
     Null,
     MakePipe,
+    #[allow(dead_code)] // This variant exists only for the Debug impl
+    InheritFile(File),
 }
 
 impl Command {
@@ -120,6 +122,7 @@ fn create_pipe(
                 )
             }
             .map(Some),
+            Stdio::InheritFile(_) => Err(unsupported()?),
             Stdio::Inherit => Ok(None),
         }
     }
@@ -135,6 +138,7 @@ fn create_stdin(
                 )
             }
             .map(Some),
+            Stdio::InheritFile(_) => Err(unsupported()?),
             Stdio::Inherit => Ok(None),
             Stdio::MakePipe => unsupported(),
         }
@@ -153,7 +157,7 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>
     }
 
     // Setup Stdout
-    let stdout = command.stdout.unwrap_or(Stdio::MakePipe);
+    let stdout = command.stdout.take().unwrap_or(Stdio::MakePipe);
     let stdout = Command::create_pipe(stdout)?;
     if let Some(con) = stdout {
         cmd.stdout_init(con)
@@ -162,7 +166,7 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>
     };
 
     // Setup Stderr
-    let stderr = command.stderr.unwrap_or(Stdio::MakePipe);
+    let stderr = command.stderr.take().unwrap_or(Stdio::MakePipe);
     let stderr = Command::create_pipe(stderr)?;
     if let Some(con) = stderr {
         cmd.stderr_init(con)
@@ -171,7 +175,7 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>
     };
 
     // Setup Stdin
-    let stdin = command.stdin.unwrap_or(Stdio::Null);
+    let stdin = command.stdin.take().unwrap_or(Stdio::Null);
     let stdin = Command::create_stdin(stdin)?;
     if let Some(con) = stdin {
         cmd.stdin_init(con)
@@ -217,25 +221,19 @@ fn from(pipe: ChildPipe) -> Stdio {
 
 impl From<io::Stdout> for Stdio {
     fn from(_: io::Stdout) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+        Stdio::Inherit
     }
 }
 
 impl From<io::Stderr> for Stdio {
     fn from(_: io::Stderr) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+        Stdio::Inherit
     }
 }
 
 impl From<File> for Stdio {
-    fn from(_file: File) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+    fn from(file: File) -> Stdio {
+        Stdio::InheritFile(file)
     }
 }
 
@@ -642,7 +640,7 @@ fn drop(&mut self) {
             }
 
             if let Some((ptr, len)) = self.args {
-                let _ = unsafe { Box::from_raw(crate::ptr::slice_from_raw_parts_mut(ptr, len)) };
+                let _ = unsafe { Box::from_raw(ptr.cast_slice(len)) };
             }
         }
     }
diff --git a/library/std/src/sys/thread_local/key/tests.rs b/library/std/src/sys/thread_local/key/tests.rs
index c7d2c8e..5e5243d 100644
--- a/library/std/src/sys/thread_local/key/tests.rs
+++ b/library/std/src/sys/thread_local/key/tests.rs
@@ -18,8 +18,8 @@ fn smoke() {
         assert!(get(k2).is_null());
         set(k1, ptr::without_provenance_mut(1));
         set(k2, ptr::without_provenance_mut(2));
-        assert_eq!(get(k1) as usize, 1);
-        assert_eq!(get(k2) as usize, 2);
+        assert_eq!(get(k1).addr(), 1);
+        assert_eq!(get(k2).addr(), 2);
     }
 }
 
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 4b934c0..78b6f7c 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -152,11 +152,11 @@ fn avoid_copying_the_body<F>(spawnfn: F)
 {
     let (tx, rx) = channel();
 
-    let x: Box<_> = Box::new(1);
-    let x_in_parent = (&*x) as *const i32 as usize;
+    let x: Box<i32> = Box::new(1);
+    let x_in_parent = (&raw const *x).addr();
 
     spawnfn(Box::new(move || {
-        let x_in_child = (&*x) as *const i32 as usize;
+        let x_in_child = (&raw const *x).addr();
         tx.send(x_in_child).unwrap();
     }));
 
diff --git a/library/std_detect/src/detect/arch/loongarch.rs b/library/std_detect/src/detect/arch/loongarch.rs
index 2e021cb..b37f449 100644
--- a/library/std_detect/src/detect/arch/loongarch.rs
+++ b/library/std_detect/src/detect/arch/loongarch.rs
@@ -35,19 +35,19 @@
     /// D
     @FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] frecipe: "frecipe";
     /// Frecipe
-    @FEATURE: #[stable(feature = "stdarch_loongarch_div32", since = "CURRENT_RUSTC_VERSION")] div32: "div32";
+    @FEATURE: #[stable(feature = "stdarch_loongarch_div32", since = "1.97.0")] div32: "div32";
     /// Div32
     @FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] lsx: "lsx";
     /// LSX
     @FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] lasx: "lasx";
     /// LASX
-    @FEATURE: #[stable(feature = "stdarch_loongarch_lam_bh", since = "CURRENT_RUSTC_VERSION")] lam_bh: "lam-bh";
+    @FEATURE: #[stable(feature = "stdarch_loongarch_lam_bh", since = "1.97.0")] lam_bh: "lam-bh";
     /// LAM-BH
-    @FEATURE: #[stable(feature = "stdarch_loongarch_lamcas", since = "CURRENT_RUSTC_VERSION")] lamcas: "lamcas";
+    @FEATURE: #[stable(feature = "stdarch_loongarch_lamcas", since = "1.97.0")] lamcas: "lamcas";
     /// LAM-CAS
-    @FEATURE: #[stable(feature = "stdarch_loongarch_ld_seq_sa", since = "CURRENT_RUSTC_VERSION")] ld_seq_sa: "ld-seq-sa";
+    @FEATURE: #[stable(feature = "stdarch_loongarch_ld_seq_sa", since = "1.97.0")] ld_seq_sa: "ld-seq-sa";
     /// LD-SEQ-SA
-    @FEATURE: #[stable(feature = "stdarch_loongarch_scq", since = "CURRENT_RUSTC_VERSION")] scq: "scq";
+    @FEATURE: #[stable(feature = "stdarch_loongarch_scq", since = "1.97.0")] scq: "scq";
     /// SCQ
     @FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] lbt: "lbt";
     /// LBT
diff --git a/library/std_detect/src/detect/arch/x86.rs b/library/std_detect/src/detect/arch/x86.rs
index 4c3a71e..ede4a80 100644
--- a/library/std_detect/src/detect/arch/x86.rs
+++ b/library/std_detect/src/detect/arch/x86.rs
@@ -106,6 +106,7 @@
     /// * `"xsaves"`
     /// * `"xsavec"`
     /// * `"cmpxchg16b"`
+    /// * `"clflushopt"`
     /// * `"kl"`
     /// * `"widekl"`
     /// * `"adx"`
@@ -261,6 +262,8 @@
     /// XSAVEC (Save Processor Extended States Compacted)
     @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] cmpxchg16b: "cmpxchg16b";
     /// CMPXCH16B (16-byte compare-and-swap instruction)
+    @FEATURE: #[unstable(feature = "clflushopt_target_feature", issue = "157096")] clflushopt: "clflushopt";
+    /// CLFLUSHOPT (Cache Line Flush Optimized)
     @FEATURE: #[stable(feature = "keylocker_x86", since = "1.89.0")] kl: "kl";
     /// Intel Key Locker
     @FEATURE: #[stable(feature = "keylocker_x86", since = "1.89.0")] widekl: "widekl";
diff --git a/library/std_detect/src/detect/os/x86.rs b/library/std_detect/src/detect/os/x86.rs
index b24ef6a..2b75cd6 100644
--- a/library/std_detect/src/detect/os/x86.rs
+++ b/library/std_detect/src/detect/os/x86.rs
@@ -127,6 +127,8 @@ pub(crate) fn detect_features() -> cache::Initializer {
 
         enable(extended_features_ebx, 9, Feature::ermsb);
 
+        enable(extended_features_ebx, 23, Feature::clflushopt);
+
         enable(extended_features_eax_leaf_1, 31, Feature::movrs);
 
         // Detect if CPUID.19h available
diff --git a/library/std_detect/tests/x86-specific.rs b/library/std_detect/tests/x86-specific.rs
index 90ca322..4b02f78 100644
--- a/library/std_detect/tests/x86-specific.rs
+++ b/library/std_detect/tests/x86-specific.rs
@@ -1,6 +1,12 @@
 #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 #![allow(internal_features)]
-#![feature(stdarch_internal, x86_amx_intrinsics, xop_target_feature, movrs_target_feature)]
+#![feature(
+    stdarch_internal,
+    x86_amx_intrinsics,
+    xop_target_feature,
+    movrs_target_feature,
+    clflushopt_target_feature
+)]
 
 #[macro_use]
 extern crate std_detect;
@@ -58,6 +64,7 @@ fn dump() {
     println!("xsaves: {:?}", is_x86_feature_detected!("xsaves"));
     println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
     println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b"));
+    println!("clflushopt: {:?}", is_x86_feature_detected!("clflushopt"));
     println!("adx: {:?}", is_x86_feature_detected!("adx"));
     println!("rtm: {:?}", is_x86_feature_detected!("rtm"));
     println!("movbe: {:?}", is_x86_feature_detected!("movbe"));
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index ad256c2..5637928 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1147,7 +1147,6 @@
         else:
             deny_warnings = self.warnings == "deny"
         if deny_warnings:
-            args += ["-Zwarnings"]
             env["CARGO_BUILD_WARNINGS"] = "deny"
 
         # Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation.
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 1dbe997..b9cd0d7 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -246,8 +246,6 @@
 
             args, env = self.build_args(configure_args, args=["--warnings=warn"])
             self.assertFalse("CARGO_BUILD_WARNINGS" in env)
-            self.assertFalse("-Zwarnings" in args)
 
             args, env = self.build_args(configure_args, args=["--warnings=deny"])
             self.assertEqual("deny", env["CARGO_BUILD_WARNINGS"])
-            self.assertTrue("-Zwarnings" in args)
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index dd68964..0fccbd7 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/154485
+Last change is for: https://github.com/rust-lang/rust/pull/157205
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 68a4f92..3b497e1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1999,12 +1999,16 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             }
 
             // Copy the compiler into the correct sysroot.
-            // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`.
-            // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load.
-            // There are a few quirks of bootstrap that interact to make this reliable:
+            //
+            // FIXME(#156525): investigate if this is still needed.
+            //
+            // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're
+            // requested with `builder.ensure(Rustc)`. This fixes an issue where we'd have multiple
+            // copies of libc in the sysroot with no way to tell which to load. There are a few
+            // quirks of bootstrap that interact to make this reliable:
             // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This
-            //    avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to
-            //    fail because of duplicate metadata.
+            //    avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter
+            //    to fail because of duplicate metadata.
             // 2. The sysroot is deleted and recreated between each invocation, so running `x test
             //    ui-fulldeps && x test ui` can't cause failures.
             let mut filtered_files = Vec::new();
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index a486cbd..b0feea1 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -760,7 +760,6 @@ fn run(self, builder: &Builder<'_>) {
 
         cp_debugger_script("lldb_lookup.py");
         cp_debugger_script("lldb_providers.py");
-        cp_debugger_script("lldb_commands")
     }
 }
 
@@ -2513,6 +2512,25 @@ fn maybe_install_llvm(
         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
         if llvm_dylib_path.exists() {
             builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
+
+            if install_symlink && let Some(llvm_config_path) = &builder.llvm_config(target) {
+                let major = llvm::get_llvm_version_major(builder, llvm_config_path);
+                let versioned_name = match &builder.config.llvm_version_suffix {
+                    Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.dylib"),
+                    None => {
+                        // dev builds use `-rust-dev`, while release-channel builds include the Rust version.
+                        if builder.config.channel == "dev" {
+                            format!("libLLVM-{major}-rust-dev.dylib")
+                        } else {
+                            format!(
+                                "libLLVM-{major}-rust-{}-{}.dylib",
+                                builder.version, builder.config.channel
+                            )
+                        }
+                    }
+                };
+                t!(builder.symlink_file("libLLVM.dylib", dst_libdir.join(versioned_name)));
+            }
         }
         !builder.config.dry_run()
     } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 2329bb9..935844d 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -510,7 +510,7 @@ fn run(self, builder: &Builder<'_>) {
         let compilers = RustcPrivateCompilers::new(builder, stage, host);
         let rustfmt_build = builder.ensure(tool::Rustfmt::from_compilers(compilers));
 
-        let mut rustfmt = tool::prepare_tool_cargo(
+        let mut cargo = tool::prepare_tool_cargo(
             builder,
             rustfmt_build.build_compiler,
             Mode::ToolRustcPrivate,
@@ -521,10 +521,10 @@ fn run(self, builder: &Builder<'_>) {
             &[],
         );
 
-        rustfmt.args(["--bin", "rustfmt", "--"]);
-        rustfmt.args(builder.config.args());
+        cargo.args(["--bin", "rustfmt", "--"]);
+        cargo.args(builder.config.args());
 
-        rustfmt.into_cmd().run(builder);
+        cargo.into_cmd().run(builder);
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index c28fe4a..25b9d744 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -579,6 +579,11 @@ fn run(self, builder: &Builder<'_>) {
         let build_compiler = self.compilers.build_compiler();
         let target = self.compilers.target();
 
+        // FIXME(#156525): `compile::Sysroot::run` intentionally do not copy `rustc-dev` artifacts
+        // until they're requested with `builder.ensure(Rustc)`, relevant for `download-rustc`
+        // flows.
+        builder.ensure(compile::Rustc::new(build_compiler, target));
+
         let mut cargo = tool::prepare_tool_cargo(
             builder,
             build_compiler,
@@ -904,6 +909,54 @@ fn run(self, builder: &Builder<'_>) {
     }
 }
 
+/// Runs `library/stdarch/crates/stdarch-verify`'s tests which cross-check the
+/// `core::arch` intrinsics for x86, Arm, and MIPS against the corresponding
+/// vendor references (signatures, target features, and `assert_instr` mappings).
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct StdarchVerify;
+
+impl Step for StdarchVerify {
+    type Output = ();
+    const IS_HOST: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("library/stdarch/crates/stdarch-verify")
+    }
+
+    fn is_default_step(_builder: &Builder<'_>) -> bool {
+        true
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(StdarchVerify);
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let host = builder.config.host_target;
+        let build_compiler = builder.compiler(0, host);
+
+        let cargo = tool::prepare_tool_cargo(
+            builder,
+            build_compiler,
+            Mode::ToolBootstrap,
+            host,
+            Kind::Test,
+            "library/stdarch/crates/stdarch-verify",
+            SourceType::InTree,
+            &[],
+        );
+
+        run_cargo_test(
+            cargo,
+            &[],
+            &["stdarch-verify".to_string()],
+            Some("stdarch-verify"),
+            host,
+            builder,
+        );
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Clippy {
     compilers: RustcPrivateCompilers,
@@ -941,6 +994,11 @@ fn run(self, builder: &Builder<'_>) {
         let target_compiler = self.compilers.target_compiler();
         let build_compiler = self.compilers.build_compiler();
 
+        // FIXME(#156525): `compile::Sysroot::run` intentionally do not copy `rustc-dev` artifacts
+        // until they're requested with `builder.ensure(Rustc)`, relevant for `download-rustc`
+        // flows.
+        builder.ensure(compile::Rustc::new(build_compiler, target));
+
         let mut cargo = tool::prepare_tool_cargo(
             builder,
             build_compiler,
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index ed5c258..a75d5e4 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -224,6 +224,12 @@ pub fn prepare_tool_cargo(
     // avoid rebuilding when running tests.
     cargo.env("SYSROOT", builder.sysroot(compiler));
 
+    // Make sure we explicitly add rustc_private libs to path centrally here so that
+    // RustcPrivate tools can pick them up.
+    if mode == Mode::ToolRustcPrivate {
+        cargo.add_rustc_lib_path(builder);
+    }
+
     // if tools are using lzma we want to force the build script to build its
     // own copy
     cargo.env("LZMA_API_STATIC", "1");
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 17bee20..519f134 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -24,6 +24,7 @@ pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'sta
         ("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
         ("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
         ("library/Cargo.toml", vec![]),
+        ("library/stdarch/Cargo.toml", vec![]),
         ("src/bootstrap/Cargo.toml", vec![]),
         ("src/tools/rustbook/Cargo.toml", SUBMODULES_FOR_RUSTBOOK.into()),
         ("src/tools/rustc-perf/Cargo.toml", vec!["src/tools/rustc-perf"]),
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 8247e87..24d7a24 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -525,11 +525,6 @@ pub fn bare_cargo(
         let out_dir = self.stage_out(compiler, mode);
         cargo.env("CARGO_TARGET_DIR", &out_dir);
 
-        // Set this unconditionally. Cargo silently ignores `CARGO_BUILD_WARNINGS` when `-Z
-        // warnings` isn't present, which is hard to debug, and it's not worth the effort to keep
-        // them in sync.
-        cargo.arg("-Zwarnings");
-
         // Bootstrap makes a lot of assumptions about the artifacts produced in the target
         // directory. If users override the "build directory" using `build-dir`
         // (https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-dir), then
diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap
index 25ff1e6..60e8a21 100644
--- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap
+++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap
@@ -181,6 +181,9 @@
 [Test] test::RustcBook
     targets: [x86_64-unknown-linux-gnu]
     - Set({test::src/doc/rustc})
+[Test] test::StdarchVerify
+    targets: [x86_64-unknown-linux-gnu]
+    - Set({test::library/stdarch/crates/stdarch-verify})
 [Test] test::RustdocJSStd
     targets: [x86_64-unknown-linux-gnu]
     - Suite(test::tests/rustdoc-js-std)
diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap
index dfc3975..f97bb83 100644
--- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap
+++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap
@@ -18,3 +18,6 @@
     - Set({test::library/sysroot})
     - Set({test::library/test})
     - Set({test::library/unwind})
+[Test] test::StdarchVerify
+    targets: [x86_64-unknown-linux-gnu]
+    - Set({test::library/stdarch/crates/stdarch-verify})
diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap
index 2f1ee93..fb83986 100644
--- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap
+++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap
@@ -180,6 +180,9 @@
 [Test] test::RustcBook
     targets: [x86_64-unknown-linux-gnu]
     - Set({test::src/doc/rustc})
+[Test] test::StdarchVerify
+    targets: [x86_64-unknown-linux-gnu]
+    - Set({test::library/stdarch/crates/stdarch-verify})
 [Test] test::RustdocJSStd
     targets: [x86_64-unknown-linux-gnu]
     - Suite(test::tests/rustdoc-js-std)
diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap
index 8f5e842..3737272 100644
--- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap
+++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap
@@ -144,6 +144,9 @@
 [Test] test::RustcBook
     targets: [x86_64-unknown-linux-gnu]
     - Set({test::src/doc/rustc})
+[Test] test::StdarchVerify
+    targets: [x86_64-unknown-linux-gnu]
+    - Set({test::library/stdarch/crates/stdarch-verify})
 [Test] test::RustdocTheme
     targets: [x86_64-unknown-linux-gnu]
     - Set({test::src/tools/rustdoc-themes})
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index bc40231..2e64022 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -910,6 +910,7 @@ macro_rules! describe {
                 test::CargoMiri,
                 test::Clippy,
                 test::CompiletestTest,
+                test::StdarchVerify,
                 test::CrateRunMakeSupport,
                 test::CrateBuildHelper,
                 test::RustdocJSStd,
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile
index d0f0b46..773bd11 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile
@@ -43,5 +43,4 @@
  --set llvm.libzstd=true"
 ENV SCRIPT="python3 ../x.py \
   --stage 1 \
-  test library/coretests \
-  --set rust.codegen-backends=[\\\"gcc\\\"]"
+  test library/coretests"
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index b7a2922..6b6d560 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -517,7 +517,7 @@
   - name: dist-aarch64-apple
     env:
       SCRIPT: >-
-        ./x.py dist bootstrap
+        ./x.py dist bootstrap enzyme
         --include-default-paths
         --host=aarch64-apple-darwin
         --target=aarch64-apple-darwin
@@ -526,6 +526,7 @@
         --enable-sanitizers
         --enable-profiler
         --set rust.jemalloc
+        --set llvm.link-shared=true
         --set rust.lto=thin
         --set rust.codegen-units=1
       # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
diff --git a/src/ci/scripts/free-disk-space-linux.sh b/src/ci/scripts/free-disk-space-linux.sh
index 590e594..167abf0 100755
--- a/src/ci/scripts/free-disk-space-linux.sh
+++ b/src/ci/scripts/free-disk-space-linux.sh
@@ -277,6 +277,10 @@
     fi
 
     WAIT_DPKG_LOCK="-o DPkg::Lock::Timeout=60"
+    # This update is intended to fix any broken state of the index and make
+    # sure it is fresh. Otherwise we've had problems with missing mirror
+    # entries.
+    sudo apt-get update -qq
     sudo apt-get ${WAIT_DPKG_LOCK} -qq remove -y --fix-missing "${packages[@]}"
 
     sudo apt-get ${WAIT_DPKG_LOCK} autoremove -y \
diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md
index c7ce2de..6d406ec 100644
--- a/src/doc/rustc-dev-guide/src/offload/usage.md
+++ b/src/doc/rustc-dev-guide/src/offload/usage.md
@@ -6,73 +6,50 @@
 To follow along, copy it to a `src/lib.rs` file.
 
 ```rust
-#![feature(abi_gpu_kernel)]
-#![feature(rustc_attrs)]
-#![feature(core_intrinsics)]
+#![allow(internal_features)]
+#![feature(gpu_offload)]
+#![cfg_attr(target_os = "linux", feature(core_intrinsics))]
+#![cfg_attr(target_arch = "amdgpu", feature(stdarch_amdgpu, abi_gpu_kernel))]
+#![cfg_attr(target_arch = "nvptx64", feature(stdarch_nvptx, abi_gpu_kernel))]
 #![no_std]
 
 #[cfg(target_os = "linux")]
 extern crate libc;
-#[cfg(target_os = "linux")]
-use libc::c_char;
 
-#[cfg(target_os = "linux")]
-use core::mem;
+use core::offload::offload_kernel;
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
 
+#[cfg(target_arch = "amdgpu")]
+use core::arch::amdgpu::{workgroup_id_x as block_idx_x, workitem_id_x as thread_idx_x};
+#[cfg(target_arch = "nvptx64")]
+use core::arch::nvptx::{
+    _block_dim_x as block_dim_x, _block_idx_x as block_idx_x, _thread_idx_x as thread_idx_x,
+};
+
+#[offload_kernel]
+fn kernel(x: *mut [f64; 256]) {
+    unsafe {
+        let n = (*x).len();
+        let i = (thread_idx_x() + block_idx_x() * block_dim_x()) as usize;
+        if i < n {
+            (*x)[i] = i as f64;
+        }
+    }
+}
+
 #[cfg(target_os = "linux")]
 #[unsafe(no_mangle)]
-#[inline(never)]
 fn main() {
-    let array_c: *mut [f64; 256] =
-        unsafe { libc::calloc(256, (mem::size_of::<f64>()) as libc::size_t) as *mut [f64; 256] };
-    let output = c"The first element is zero %f\n";
-    let output2 = c"The first element is NOT zero %f\n";
-    let output3 = c"The second element is %f\n";
-    unsafe {
-        let val: *const c_char = if (*array_c)[0] < 0.1 {
-            output.as_ptr()
-        } else {
-            output2.as_ptr()
-        };
-        libc::printf(val, (*array_c)[0]);
+    let mut x = [0.0f64; 256];
+    core::intrinsics::offload::<_, _, ()>(kernel, [256, 1, 1], [1, 1, 1], (&mut x as *mut [f64; 256],));
+    for i in 0..x.len() {
+        assert_eq!(x[i], i as f64);
     }
-
-    unsafe {
-        kernel(array_c);
-    }
-    core::hint::black_box(&array_c);
-    unsafe {
-        let val: *const c_char = if (*array_c)[0] < 0.1 {
-            output.as_ptr()
-        } else {
-            output2.as_ptr()
-        };
-        libc::printf(val, (*array_c)[0]);
-        libc::printf(output3.as_ptr(), (*array_c)[1]);
-    }
-}
-
-#[inline(never)]
-unsafe fn kernel(x: *mut [f64; 256]) {
-    core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], (x,))
-}
-
-#[cfg(target_os = "linux")]
-unsafe extern "C" {
-    pub fn kernel_1(array_b: *mut [f64; 256]);
-}
-
-#[cfg(not(target_os = "linux"))]
-#[unsafe(no_mangle)]
-#[inline(never)]
-#[rustc_offload_kernel]
-pub extern "gpu-kernel" fn kernel_1(x: *mut [f64; 256]) {
-    unsafe { (*x)[0] = 21.0 };
+    unsafe { libc::printf(c"all checks passed".as_ptr()); }
 }
 ```
 
@@ -96,7 +73,7 @@
 While we integrated most offload steps into rustc by now, one binary invocation still remains for now:
 
 ```
-"clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "bare" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "target/<GPU_DIR>/release/host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o"
+"clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "main" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "target/<GPU_DIR>/release/host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o"
 ```
 
 You can try to find the paths to those files on your system.
@@ -112,9 +89,7 @@
 
 ```
 ./main
-The first element is zero 0.000000
-The first element is NOT zero 21.000000
-The second element is  0.000000
+all checks passed!
 ```
 
 To receive more information about the memory transfer, you can enable info printing with
diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md
index ec16c18..af9d134 100644
--- a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md
+++ b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md
@@ -6,7 +6,7 @@
 
 ## Target maintainers
 
-[@morr0ne](https://github.com/morr0ne)
+[@rosymati](https://github.com/rosymati)
 
 ## Requirements
 
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 9df5d7d..53fd7df0c 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -185,7 +185,9 @@
 
 ## Unit literals
 
-Never break between the opening and closing parentheses of the `()` unit literal.
+Never break between the opening and closing parentheses of the `()` unit
+literal. This applies even when the closing parenthesis would fall past the
+maximum line width.
 
 ## Tuple literals
 
@@ -384,7 +386,8 @@
 For a function call with no arguments (a nullary function call like `func()`),
 never break within the parentheses, and never put a space between the
 parentheses. Always write a nullary function call as a single-line call, never
-a multi-line call.
+a multi-line call. This applies even when the closing parenthesis would fall
+past the maximum line width.
 
 ### Single-line calls
 
diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-options.md b/src/doc/unstable-book/src/compiler-flags/codegen-options.md
index f927e5c..efde410 100644
--- a/src/doc/unstable-book/src/compiler-flags/codegen-options.md
+++ b/src/doc/unstable-book/src/compiler-flags/codegen-options.md
@@ -7,8 +7,6 @@
 ## linker-flavor
 
 In addition to the stable set of linker flavors, the following unstable values also exist:
-- `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker)
-  for Nvidia NVPTX GPGPU support.
 - `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support.
 - `llbc`: for linking in llvm bitcode. Install the preview rustup components`llvm-bitcode-linker`
   and `llvm-tools` to use as a self-contained linker by passing
diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md
similarity index 93%
rename from src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md
rename to src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md
index ee72b6a..d25cdca 100644
--- a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md
+++ b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md
@@ -1,4 +1,4 @@
-# `debug-info-for-profiling`
+# `debuginfo-for-profiling`
 
 ---
 
@@ -22,7 +22,7 @@
 Given a Rust file `main.rs`, we can produce an optimized binary as follows:
 
 ```shell
-rustc -O -Zdebug-info-for-profiling main.rs -o main
+rustc -O -Zdebuginfo-for-profiling main.rs -o main
 perf record -b ./main
 create_llvm_prof --binary=main --out=code.prof
 rustc -O -Zprofile-sample-use=code.prof main.rs -o main2
diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
index 2dd1f6f..a9bcca3 100644
--- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
+++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
@@ -4,7 +4,7 @@
 
 `-Zprofile-sample-use=code.prof` directs `rustc` to use the profile
 `code.prof` as a source for Automatic Feedback Directed Optimization (AFDO).
-See the documentation of [`-Zdebug-info-for-profiling`] for more information
+See the documentation of [`-Zdebuginfo-for-profiling`] for more information
 on using AFDO.
 
-[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html
+[`-Zdebuginfo-for-profiling`]: debuginfo_for_profiling.html
diff --git a/src/etc/lldb_batchmode/__init__.py b/src/etc/lldb_batchmode/__init__.py
new file mode 100644
index 0000000..0da71ca
--- /dev/null
+++ b/src/etc/lldb_batchmode/__init__.py
@@ -0,0 +1 @@
+from .runner import main as main
diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode/runner.py
similarity index 97%
rename from src/etc/lldb_batchmode.py
rename to src/etc/lldb_batchmode/runner.py
index 54e796b..e9b1063 100644
--- a/src/etc/lldb_batchmode.py
+++ b/src/etc/lldb_batchmode/runner.py
@@ -166,7 +166,7 @@
     def watchdog():
         while clock() < watchdog_max_time:
             time.sleep(1)
-        print("TIMEOUT: lldb_batchmode.py has been running for too long. Aborting!")
+        print("TIMEOUT: lldb_batchmode has been running for too long. Aborting!")
         thread.interrupt_main()
 
     # Start the listener and let it run as a daemon
@@ -252,7 +252,3 @@
         sys.exit(1)
     finally:
         script_file.close()
-
-
-if __name__ == "__main__":
-    main()
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands
deleted file mode 100644
index 6db81ce..0000000
--- a/src/etc/lldb_commands
+++ /dev/null
@@ -1,86 +0,0 @@
-# LLDB iterates through these in reverse order to discover summaries/synthetics that means the top
-# of the list can be "overwritten" by items lower on the list. Be careful when reordering items.
-
-# Forces test-compliant formatting to all other types
-type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
-# Std String
-type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust
-type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
-
-# Std str
-type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?str$" --category Rust
-type summary add -F lldb_lookup.StdStrSummaryProvider -e -x -h "^&(mut )?str$" --category Rust
-
-## MSVC
-type synthetic add -l lldb_lookup.MSVCStrSyntheticProvider -x "^ref(_mut)?\$<str\$>$" --category Rust
-type summary add -F lldb_lookup.StdStrSummaryProvider -e -h -x "^ref(_mut)?\$<str\$>$" --category Rust
-
-# Array/Slice
-type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?\\[.+\\]$" --category Rust
-type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
-
-## MSVC
-type synthetic add -l lldb_lookup.MSVCStdSliceSyntheticProvider -x "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
-type summary add -F lldb_lookup.StdSliceSummaryProvider -e -x -h "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
-
-# OsString
-type summary add -F lldb_lookup.StdOsStringSummaryProvider -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
-
-# Vec
-type synthetic add -l lldb_lookup.StdVecSyntheticProvider -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
-type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
-
-# VecDeque
-type synthetic add -l lldb_lookup.StdVecDequeSyntheticProvider -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
-type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
-
-# HashMap
-type synthetic add -l lldb_lookup.classify_hashmap -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
-type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
-
-# HashSet
-type synthetic add -l lldb_lookup.classify_hashset -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
-type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
-
-# Rc
-type synthetic add -l lldb_lookup.StdRcSyntheticProvider -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
-type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
-
-# Arc
-type synthetic add -l lldb_lookup.arc_synthetic -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
-type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
-
-# Cell
-type synthetic add -l lldb_lookup.StdCellSyntheticProvider -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
-
-# RefCell
-type synthetic add -l lldb_lookup.StdRefSyntheticProvider -x "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
-type summary add -F lldb_lookup.StdRefSummaryProvider -e -x -h "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
-
-# NonZero
-type summary add -F lldb_lookup.StdNonZeroNumberSummaryProvider -e -x -h "^(core::([a-z_]+::)+)NonZero(<.+>|I\d{0,3}|U\d{0,3})$" --category Rust
-
-# PathBuf
-type summary add -F lldb_lookup.StdPathBufSummaryProvider -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
-
-# Path
-type summary add -F lldb_lookup.StdPathSummaryProvider -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
-
-# Enum
-# type summary add -F lldb_lookup.ClangEncodedEnumSummaryProvider -e -h "lldb_lookup.is_sum_type_enum" --recognizer-function --category Rust
-## MSVC
-type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust
-type summary add -F lldb_lookup.MSVCEnumSummaryProvider -e -x -h "^enum2\$<.+>$" --category Rust
-
-## MSVC Variants
-type synthetic add -l lldb_lookup.synthetic_lookup -x "^enum2\$<.+>::.*$" --category Rust
-
-# Tuple
-type synthetic add -l lldb_lookup.TupleSyntheticProvider -x "^\(.*\)$" --category Rust
-type summary add -F lldb_lookup.TupleSummaryProvider -x "^\(.*\)$" --category Rust
-
-## MSVC
-type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust
-type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust
-
-type category enable Rust
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index 67194a0..cc3e841 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -1,10 +1,45 @@
 from __future__ import annotations
-from typing import List
-
+from typing import TYPE_CHECKING, List, Callable
 
 import lldb
 
-from lldb_providers import *
+from lldb_providers import (
+    LLDBFeature,
+    FEATURE_FLAGS,
+    LLDBOpaque,
+    StructSyntheticProvider,
+    StdHashMapSyntheticProvider,
+    StdOldHashMapSyntheticProvider,
+    StdRcSyntheticProvider,
+    TupleSyntheticProvider,
+    EmptySyntheticProvider,
+    ClangEncodedEnumProvider,
+    DefaultSyntheticProvider,
+    StdStringSyntheticProvider,
+    StdStringSummaryProvider,
+    StdSliceSyntheticProvider,
+    StdStrSummaryProvider,
+    MSVCStrSyntheticProvider,
+    SizeSummaryProvider,
+    MSVCStdSliceSyntheticProvider,
+    StdSliceSummaryProvider,
+    StdOsStringSummaryProvider,
+    StdVecSyntheticProvider,
+    StdVecDequeSyntheticProvider,
+    StdRcSummaryProvider,
+    StdCellSyntheticProvider,
+    StdRefSyntheticProvider,
+    StdRefSummaryProvider,
+    StdNonZeroNumberSummaryProvider,
+    StdPathBufSummaryProvider,
+    StdPathSummaryProvider,
+    MSVCEnumSyntheticProvider,
+    MSVCEnumSummaryProvider,
+    TupleSummaryProvider,
+    MSVCTupleSyntheticProvider,
+    ClangEncodedEnumSummaryProvider,
+    StructSummaryProvider,
+)
 from rust_types import (
     ENUM_DISR_FIELD_NAME,
     ENUM_LLDB_ENCODED_VARIANTS,
@@ -13,6 +48,9 @@
     is_tuple_fields,
 )
 
+if TYPE_CHECKING:
+    from lldb import SBValue
+
 ####################################################################################################
 # This file contains lookup functions that associate rust types with their synthetic/summary
 # providers.
@@ -31,6 +69,302 @@
 # (see: `classify_hashmap()` vs `classify_hashset()`).
 ####################################################################################################
 
+RUST_CATEGORY: lldb.SBTypeCategory = lldb.SBTypeCategory()
+MOD_PREFIX = f"{__name__}."
+
+DEFAULT_TYPE_OPTIONS: int = (
+    # ensure it applies through typedef chains
+    lldb.eTypeOptionCascade
+    | lldb.eTypeOptionHideEmptyAggregates
+    # helps us reason about what types can be put through the synthetic provider.
+    # this is important because of the `update` logic as well as when working with
+    # type information, since we almost always want to work on the pointee type/pointee's
+    # template args. These options allow us to know that the type we have is never a pointer-to
+    # the type we want
+    | lldb.eTypeOptionFrontEndWantsDereference
+)
+
+
+def __lldb_init_module(debugger: lldb.SBDebugger, _dict: LLDBOpaque):
+    global RUST_CATEGORY
+    RUST_CATEGORY = debugger.GetCategory("Rust")
+
+    if not RUST_CATEGORY.IsValid():
+        RUST_CATEGORY = debugger.CreateCategory("Rust")
+
+    RUST_CATEGORY.SetEnabled(True)
+
+    # BUG: This specifier is used to determine whether or not visualizers in this category shoud be
+    # used for the given executable. It defaults to `lldb.eLanguageTypeUnknown` which will be active
+    # regardless of the executable's reported language, but setting it to `rust` would be ideal
+    # so that our visualizers do not apply to, for example, C++ code when debugging across FFI
+    # boundaries.
+    # We cannot currently enable this though, as this query defers to the `TypeSystem` (in our case,
+    # `TypeSystemClang`). `TypeSystemClang::SupportsLanguage` includes Rust, which allows Rust
+    # support in LLDB, but SBTypeCategory instead checks
+    # `TypeSystemClang::GetSupportedLanguagesForTypes` which only includes various C and C++
+    # versions. I'm not sure if Rust should be added to that function or not, but in the meantime
+    # cannot directly specify that Rust is the intended language for this category.
+
+    # RUST_CATEGORY.AddLanguage(lldb.eLanguageTypeRust)
+
+    global FEATURE_FLAGS
+    # Most feature checks should be possible via simple "does this API exist at all" checks.
+    if getattr(lldb.SBType, "GetStaticFieldWithName", None) is not None:
+        FEATURE_FLAGS |= LLDBFeature.StaticFields
+    if getattr(lldb, "eFormatterMatchCallback", None) is not None:
+        FEATURE_FLAGS |= LLDBFeature.TypeRecognizers
+
+    register_providers_compatibility()
+
+
+def register_providers_compatibility():
+    """
+    Adds providers to global `RUST_CATEGORY`. Does not attempt to use type recognizers
+
+    The order that providers are added matters. Existing providers are iterated through in **reverse
+    order** when finding a match, allowing new providers to "overwrite" old providers. Be very
+    careful when modifying the order that providers are added.
+    """
+
+    global RUST_CATEGORY
+
+    if LLDBFeature.TypeRecognizers in FEATURE_FLAGS:
+        # FIXME: this can be removed once full support for type recognizers is added.
+        # This prevents a semi-unfixable regression for CodeLLDB
+        register_synth(
+            synthetic_lookup,
+            lldb.SBTypeNameSpecifier(
+                MOD_PREFIX + is_udt.__name__,
+                lldb.eFormatterMatchCallback,
+            ),
+            lldb.eTypeOptionCascade,
+        )
+
+        # enforce uniform aggregate formatting
+        register_summary(
+            StructSummaryProvider,
+            lldb.SBTypeNameSpecifier(
+                MOD_PREFIX + is_udt.__name__,
+                lldb.eFormatterMatchCallback,
+            ),
+            lldb.eTypeOptionCascade
+            | lldb.eTypeOptionHideEmptyAggregates
+            | lldb.eTypeOptionHideChildren,
+        )
+    else:
+        # Need to toss any remaining types through this so that GNU enums are caught
+        register_synth(
+            synthetic_lookup,
+            lldb.SBTypeNameSpecifier(r".*", True),
+        )
+
+    # String
+    register(
+        StdStringSyntheticProvider,
+        StdStringSummaryProvider,
+        r"^(alloc::([a-z_]+::)+)String$",
+    )
+
+    # str GNU
+    register(
+        StdSliceSyntheticProvider,
+        StdStrSummaryProvider,
+        r"^&(mut )?str$",
+    )
+
+    # str MSVC
+    register(
+        MSVCStrSyntheticProvider,
+        StdStrSummaryProvider,
+        r"^ref(_mut)?\$<str\$>$",
+    )
+
+    # slice GNU
+    register(
+        StdSliceSyntheticProvider,
+        SizeSummaryProvider,
+        r"^&(mut )?\[.+\]$",
+    )
+
+    # slice MSVC
+    register(
+        MSVCStdSliceSyntheticProvider,
+        StdSliceSummaryProvider,
+        r"^ref(_mut)?\$<slice2\$<.+> >",
+    )
+
+    # OsString
+    register_summary(
+        StdOsStringSummaryProvider,
+        lldb.SBTypeNameSpecifier(r"^(std::ffi::([a-z_]+::)+)OsString$", True),
+    )
+
+    # Vec
+    register(
+        StdVecSyntheticProvider,
+        SizeSummaryProvider,
+        r"^(alloc::([a-z_]+::)+)Vec<.+>$",
+    )
+
+    # VecDeque
+    register(
+        StdVecDequeSyntheticProvider,
+        SizeSummaryProvider,
+        r"^(alloc::([a-z_]+::)+)VecDeque<.+>$",
+    )
+
+    # HashMap
+    register(
+        classify_hashmap,
+        SizeSummaryProvider,
+        r"^(std::collections::([a-z_]+::)+)HashMap<.+>$",
+    )
+
+    # HashSet
+    register(
+        classify_hashset,
+        SizeSummaryProvider,
+        r"^(std::collections::([a-z_]+::)+)HashSet<.+>$",
+    )
+
+    # Rc
+    register(
+        StdRcSyntheticProvider,
+        StdRcSummaryProvider,
+        r"^(alloc::([a-z_]+::)+)Rc<.+>$",
+    )
+
+    # Arc
+    register(
+        arc_synthetic,
+        StdRcSummaryProvider,
+        r"^(alloc::([a-z_]+::)+)Arc<.+>$",
+    )
+
+    # Cell
+    register_synth(
+        StdCellSyntheticProvider,
+        lldb.SBTypeNameSpecifier(
+            r"^(core::([a-z_]+::)+)Cell<.+>$",
+            True,
+        ),
+    )
+
+    # RefCell
+    register(
+        StdRefSyntheticProvider,
+        StdRefSummaryProvider,
+        r"^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$",
+    )
+
+    # NonZero
+    register_summary(
+        StdNonZeroNumberSummaryProvider,
+        lldb.SBTypeNameSpecifier(
+            r"^(core::([a-z_]+::)+)NonZero(<.+>|I\d{0,3}|U\d{0,3})$",
+            True,
+        ),
+    )
+
+    # PathBuf
+    register_summary(
+        StdPathBufSummaryProvider,
+        lldb.SBTypeNameSpecifier(
+            r"^(std::([a-z_]+::)+)PathBuf$",
+            True,
+        ),
+    )
+
+    # Path
+    register_summary(
+        StdPathSummaryProvider,
+        lldb.SBTypeNameSpecifier(
+            r"^&(mut )?(std::([a-z_]+::)+)Path$",
+            True,
+        ),
+    )
+
+    # Enum MSVC
+    register(
+        MSVCEnumSyntheticProvider,
+        MSVCEnumSummaryProvider,
+        r"^enum2\$<.+>$",
+    )
+
+    # Tuple GNU
+    register(
+        TupleSyntheticProvider,
+        TupleSummaryProvider,
+        r"^\(.*\)$",
+        type_options=DEFAULT_TYPE_OPTIONS | lldb.eTypeOptionHideChildren,
+    )
+
+    # Tuple MSVC
+    register(
+        MSVCTupleSyntheticProvider,
+        TupleSummaryProvider,
+        r"^tuple\$<.+>$",
+    )
+
+
+def register(
+    synth_provider: Callable[[SBValue, LLDBOpaque], object],
+    summary_provider: Callable[[SBValue, LLDBOpaque], str],
+    match_str: str,
+    regex: bool = True,
+    type_options: int = DEFAULT_TYPE_OPTIONS,
+):
+    global RUST_CATEGORY
+    sb_name: lldb.SBTypeNameSpecifier = lldb.SBTypeNameSpecifier(match_str, regex)
+
+    register_synth(synth_provider, sb_name, type_options)
+    register_summary(summary_provider, sb_name, type_options)
+
+
+def register_synth(
+    provider: Callable[[SBValue, LLDBOpaque], object],
+    sb_name: lldb.SBTypeNameSpecifier,
+    type_options: int = DEFAULT_TYPE_OPTIONS,
+):
+    sb_synth: lldb.SBTypeSynthetic = lldb.SBTypeSynthetic.CreateWithClassName(
+        MOD_PREFIX + provider.__name__
+    )
+    sb_synth.SetOptions(type_options)
+
+    global RUST_CATEGORY
+    # returns false for failures, does not provide any info to determine what the failure was
+
+    res: bool = RUST_CATEGORY.AddTypeSynthetic(sb_name, sb_synth)
+
+    if not res:
+        print(
+            "Warning: unable to register summary: "
+            + f"{MOD_PREFIX + provider.__name__} with specifier '{sb_name.GetName()}'"
+        )
+
+
+def register_summary(
+    provider: Callable[[SBValue, LLDBOpaque], object],
+    sb_name: lldb.SBTypeNameSpecifier,
+    type_options: int = DEFAULT_TYPE_OPTIONS,
+):
+    sb_summary: lldb.SBTypeSummary = lldb.SBTypeSummary.CreateWithFunctionName(
+        MOD_PREFIX + provider.__name__
+    )
+
+    sb_summary.SetOptions(type_options)
+
+    global RUST_CATEGORY
+    # returns false for failures, does not provide any info to determine what the failure was
+    res: bool = RUST_CATEGORY.AddTypeSummary(sb_name, sb_summary)
+
+    if not res:
+        print(
+            "Warning: unable to register summary: "
+            + f"{MOD_PREFIX + provider.__name__} with specifier '{sb_name.GetName()}'"
+        )
+
 
 # BACKCOMPAT: rust 1.35
 def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
@@ -56,6 +390,15 @@
     return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
 
 
+def is_udt(type: lldb.SBType, _dict: LLDBOpaque) -> bool:
+    return (
+        type.GetBasicType() == lldb.eBasicTypeInvalid
+        and not type.IsScopedEnumerationType()
+        and not type.IsPointerType()
+        and not type.IsArrayType()
+    )
+
+
 def classify_rust_type(type: lldb.SBType, is_msvc: bool) -> RustType:
     if type.IsPointerType():
         return RustType.Indirection
@@ -133,16 +476,16 @@
             or summary.summary_data.strip()
             != "lldb_lookup.ClangEncodedEnumSummaryProvider(valobj,internal_dict)"
         ):
-            rust_category: lldb.SBTypeCategory = lldb.debugger.GetCategory("Rust")
-            rust_category.AddTypeSummary(
+            sb_summary = lldb.SBTypeSummary().CreateWithFunctionName(
+                MOD_PREFIX + ClangEncodedEnumSummaryProvider.__name__
+            )
+            sb_summary.SetOptions(DEFAULT_TYPE_OPTIONS)
+
+            RUST_CATEGORY.AddTypeSummary(
                 lldb.SBTypeNameSpecifier(valobj.GetTypeName()),
-                lldb.SBTypeSummary().CreateWithFunctionName(
-                    "lldb_lookup.ClangEncodedEnumSummaryProvider"
-                ),
+                sb_summary,
             )
 
         return ClangEncodedEnumProvider(valobj, _dict)
-    if rust_type == RustType.Indirection:
-        return IndirectionSyntheticProvider(valobj, _dict)
 
     return DefaultSyntheticProvider(valobj, _dict)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 2da6151..81841dc 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -1,6 +1,7 @@
 from __future__ import annotations
 import sys
 from typing import Generator, List, TYPE_CHECKING, Optional
+from enum import Flag, auto
 
 from lldb import (
     SBData,
@@ -53,6 +54,24 @@
 PY3 = sys.version_info[0] == 3
 
 
+class LLDBFeature(Flag):
+    """Used to track which features we rely on and whether or not we can access them. The global
+    `lldb_providers.FEATURE_FLAGS` is initialized in `lldb_lookup.__lldb_init_module` and is
+    expected not to change after that point.
+
+    This is used rather than `debugger.GetVersionString` because Apple's fork of LLDB (used for
+    xcode) uses a non-standard versioning scheme that has no relation to LLVM's.
+    """
+
+    StaticFields = auto()
+    """Added in LLDB 18. Adds functions to `SBType` the inspection of a struct's static fields."""
+    TypeRecognizers = auto()
+    """Added in LLDB 19. Callback-based type matching for synthetic/summary providers."""
+
+
+FEATURE_FLAGS: LLDBFeature = LLDBFeature(0)
+
+
 class LLDBOpaque:
     """
     An marker type for use in type hints to denote LLDB bookkeeping variables. Values marked with
@@ -70,14 +89,18 @@
     def from_int(self, name: str, value: int) -> SBValue:
         type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
         data = SBData.CreateDataFromSInt64Array(
-            self.endianness, self.pointer_size, [value]
+            self.endianness,
+            self.pointer_size,
+            [value],
         )
         return self.valobj.CreateValueFromData(name, data, type)
 
     def from_uint(self, name: str, value: int) -> SBValue:
         type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
         data = SBData.CreateDataFromUInt64Array(
-            self.endianness, self.pointer_size, [value]
+            self.endianness,
+            self.pointer_size,
+            [value],
         )
         return self.valobj.CreateValueFromData(name, data, type)
 
@@ -123,37 +146,6 @@
         return self.valobj.value
 
 
-class IndirectionSyntheticProvider:
-    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
-        self.valobj = valobj
-
-    def num_children(self) -> int:
-        return 1
-
-    def get_child_index(self, name: str) -> int:
-        if name == "$$dereference$$":
-            return 0
-        return -1
-
-    def get_child_at_index(self, index: int) -> Optional[SBValue]:
-        if index == 0:
-            value = self.valobj.Dereference()
-            if (synth := value.GetSyntheticValue()).IsValid():
-                return synth
-            else:
-                return value
-        return None
-
-    def update(self):
-        pass
-
-    def has_children(self) -> bool:
-        return True
-
-    def get_value(self):
-        return self.valobj.value
-
-
 class EmptySyntheticProvider:
     def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
         # logger = Logger.Logger()
@@ -638,6 +630,8 @@
 
 
 def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
+    if valobj.TypeIsPointerType():
+        valobj = valobj.Dereference()
     enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict)
     variant = enum_synth.variant
     name = _getVariantName(variant)
@@ -670,6 +664,10 @@
 
     def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
         self.valobj = valobj
+        # This allows the summary provider to still print something
+        # even if we can't find the variant for whatever reason
+        self.variant = valobj
+        self.value = valobj
         self.update()
 
     def update(self):
diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb
index f8f3190..91c6591 100755
--- a/src/etc/rust-lldb
+++ b/src/etc/rust-lldb
@@ -31,7 +31,6 @@
 fi
 
 script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_lookup.py\""
-commands_file="$RUSTC_SYSROOT/lib/rustlib/etc/lldb_commands"
 
 # Call LLDB with the commands added to the argument list
-exec "$lldb" --one-line-before-file "$script_import" --source-before-file "$commands_file" "$@"
+exec "$lldb" --one-line-before-file "$script_import" "$@"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 554b81b..dffdcbb 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -71,7 +71,7 @@ fn synthesize_auto_trait_impl<'tcx>(
 ) -> Option<clean::Item> {
     let tcx = cx.tcx;
     let trait_ref = ty::Binder::dummy(ty::TraitRef::new(tcx, trait_def_id, [ty]));
-    if !cx.generated_synthetics.insert((ty, trait_def_id)) {
+    if !cx.synthetic_auto_trait_impls.insert((ty, trait_def_id)) {
         debug!("already generated, aborting");
         return None;
     }
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 8dda831..6cf7c55 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -25,7 +25,7 @@ pub(crate) fn synthesize_blanket_impls(
     let mut blanket_impls = Vec::new();
     for trait_def_id in tcx.visible_traits() {
         if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id)
-            || cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id))
+            || cx.synthetic_blanket_impls.contains(&(ty.skip_binder(), trait_def_id))
         {
             continue;
         }
@@ -81,7 +81,7 @@ pub(crate) fn synthesize_blanket_impls(
             }
             debug!("found applicable impl for trait ref {trait_ref:?}");
 
-            cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));
+            cx.synthetic_blanket_impls.insert((ty.skip_binder(), trait_def_id));
 
             blanket_impls.push(clean::Item {
                 inner: Box::new(clean::ItemInner {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index cf6deeb..4284512 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -243,8 +243,8 @@ fn generate_item_with_correct_attrs(
             ) || (is_glob_import(tcx, import_id)
                 && (cx.document_hidden() || !tcx.is_doc_hidden(def_id)))
                 || macro_reexport_is_inline(tcx, import_id, def_id);
-            attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
             is_inline = is_inline || import_is_inline;
+            attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
         }
         let keep_target_cfg = is_inline || matches!(kind, ItemKind::TypeAliasItem(..));
         add_without_unwanted_attributes(&mut attrs, target_attrs, keep_target_cfg, None);
@@ -1089,7 +1089,13 @@ fn clean_fn_or_proc_macro<'tcx>(
     match macro_kind {
         Some(kind) => clean_proc_macro(item, name, kind, cx.tcx),
         None => {
-            let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id));
+            let mut func = clean_function(
+                cx,
+                sig,
+                generics,
+                ParamsSrc::Body(body_id),
+                item.owner_id.to_def_id(),
+            );
             clean_fn_decl_legacy_const_generics(&mut func, attrs);
             FunctionItem(func)
         }
@@ -1127,18 +1133,30 @@ fn clean_function<'tcx>(
     sig: &hir::FnSig<'tcx>,
     generics: &hir::Generics<'tcx>,
     params: ParamsSrc<'tcx>,
+    def_id: DefId,
 ) -> Box<Function> {
     let (generics, decl) = enter_impl_trait(cx, |cx| {
         // NOTE: Generics must be cleaned before params.
         let generics = clean_generics(generics, cx);
-        let params = match params {
-            ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id),
-            // Let's not perpetuate anon params from Rust 2015; use `_` for them.
-            ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| {
-                Some(ident.map_or(kw::Underscore, |ident| ident.name))
-            }),
+        let decl = if sig.decl.opt_delegation_sig_id().is_some() {
+            // A delegation item (`reuse path::method`) has no resolved signature in the
+            // HIR: its inputs and return type are `InferDelegation` nodes that clean to
+            // `_`, and an `async` header over that inferred return type would panic in
+            // `sugared_async_return_type`. The resolved signature only exists on the ty
+            // side, so clean that instead, exactly like an inlined item. This both fixes
+            // the rendered `-> _` / `self: _` and makes the async sugaring well-defined.
+            let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
+            clean_poly_fn_sig(cx, Some(def_id), sig)
+        } else {
+            let params = match params {
+                ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id),
+                // Let's not perpetuate anon params from Rust 2015; use `_` for them.
+                ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| {
+                    Some(ident.map_or(kw::Underscore, |ident| ident.name))
+                }),
+            };
+            clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params)
         };
-        let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params);
         (generics, decl)
     });
     Box::new(Function { decl, generics })
@@ -1270,11 +1288,18 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
                 RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body));
+                let m =
+                    clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body), local_did);
                 MethodItem(m, Defaultness::from_trait_item(trait_item.defaultness))
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => {
-                let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Idents(idents));
+                let m = clean_function(
+                    cx,
+                    sig,
+                    trait_item.generics,
+                    ParamsSrc::Idents(idents),
+                    local_did,
+                );
                 RequiredMethodItem(m, Defaultness::from_trait_item(trait_item.defaultness))
             }
             hir::TraitItemKind::Type(bounds, Some(default)) => {
@@ -1315,7 +1340,7 @@ pub(crate) fn clean_impl_item<'tcx>(
                 type_: clean_ty(ty, cx),
             })),
             hir::ImplItemKind::Fn(ref sig, body) => {
-                let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body));
+                let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body), local_did);
                 let defaultness = match impl_.impl_kind {
                     hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final,
                     hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness,
@@ -3254,7 +3279,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
     cx.with_param_env(def_id, |cx| {
         let kind = match item.kind {
             hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem(
-                clean_function(cx, &sig, generics, ParamsSrc::Idents(idents)),
+                clean_function(cx, &sig, generics, ParamsSrc::Idents(idents), def_id),
                 sig.header.safety(),
             ),
             hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 253d4dc..4367209 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -350,13 +350,13 @@ fn print_pat(pat: &Pat<'_>, wild: bool) -> impl Display {
 
 pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String {
     match n.kind() {
-        ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
-            if let Some(def) = def.as_local()
+        ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, .. }) => {
+            if let Some(def) = kind.def_id().as_local()
                 && let Some(body_id) = tcx.hir_maybe_body_owned_by(def)
             {
                 rendered_const(tcx, body_id, def)
             } else {
-                inline::print_inlined_const(tcx, def)
+                inline::print_inlined_const(tcx, kind.def_id())
             }
         }
         // array lengths are obviously usize
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 21ce508..cb64655 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -56,9 +56,18 @@ pub(crate) struct DocContext<'tcx> {
     pub(crate) current_type_aliases: DefIdMap<usize>,
     /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
     pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
-    /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
-    // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
-    pub(crate) generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>,
+
+    // FIXME: I'm pretty that the only reason we "need" these caches is because we also invoke
+    //        `synthesize_auto_trait_and_blanket_impls` on all impls(!) for primitive types
+    //        instead of calling it only once per primitive type (see also #97129).
+    //        Get rid of that jank and remove both caches!
+    //
+    /// The set of auto-trait impls generated so far; identified by `(self_ty, trait_def_id)`.
+    pub(crate) synthetic_auto_trait_impls: FxHashSet<(Ty<'tcx>, DefId)>,
+    /// The set of blanket impls generated so far; identified by `(self_ty, trait_def_id)`.
+    pub(crate) synthetic_blanket_impls: FxHashSet<(Ty<'tcx>, DefId)>,
+
+    /// All auto traits in the (visible) crate graph.
     pub(crate) auto_traits: Vec<DefId>,
     /// This same cache is used throughout rustdoc, including in [`crate::html::render`].
     pub(crate) cache: Cache,
@@ -369,7 +378,8 @@ pub(crate) fn run_global_ctxt(
         args: Default::default(),
         current_type_aliases: Default::default(),
         impl_trait_bounds: Default::default(),
-        generated_synthetics: Default::default(),
+        synthetic_auto_trait_impls: Default::default(),
+        synthetic_blanket_impls: Default::default(),
         auto_traits,
         cache: Cache::new(render_options.document_private, render_options.document_hidden),
         inlined: FxHashSet::default(),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index e6c64ef..cbb5fed 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -4,8 +4,7 @@
 //! various types in `rustdoc::clean`.
 //!
 //! These implementations all emit HTML. As an internal implementation detail,
-//! some of them support an alternate format that emits text, but that should
-//! not be used external to this module.
+//! some of them support an alternate format that emits plain text.
 
 use std::cmp::Ordering;
 use std::fmt::{self, Display, Write};
@@ -184,9 +183,9 @@ pub(crate) fn print_where_clause(
 
         let clause = if f.alternate() {
             if ending == Ending::Newline {
-                format!(" where{where_preds},")
+                format!(" where{where_preds:#},")
             } else {
-                format!(" where{where_preds}")
+                format!(" where{where_preds:#}")
             }
         } else {
             let mut br_with_padding = String::with_capacity(6 * indent + 28);
diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs
index ec8b659..4c82041 100644
--- a/src/librustdoc/html/macro_expansion.rs
+++ b/src/librustdoc/html/macro_expansion.rs
@@ -2,7 +2,7 @@
     AssocCtxt, Visitor, walk_assoc_item, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt,
     walk_ty,
 };
-use rustc_ast::{AssocItem, Crate, Expr, Item, Pat, Stmt, Ty};
+use rustc_ast::{AssocItem, Crate, Expr, ForeignItem, Item, Pat, Stmt, Ty};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::source_map::SourceMap;
 use rustc_span::{BytePos, Span};
@@ -174,4 +174,14 @@ fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) -> Self::
             walk_assoc_item(self, item, ctxt);
         }
     }
+
+    fn visit_foreign_item(&mut self, item: &'ast ForeignItem) -> Self::Result {
+        if item.span.from_expansion() {
+            self.handle_new_span(item.span, || {
+                rustc_ast_pretty::pprust::foreign_item_to_string(item)
+            });
+        } else {
+            walk_item(self, item);
+        }
+    }
 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8108316..adb53b0 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1397,13 +1397,13 @@ fn render_all_impls(
     mut w: impl Write,
     cx: &Context<'_>,
     containing_item: &clean::Item,
-    concrete: &[&Impl],
-    synthetic: &[&Impl],
-    blanket_impl: &[&Impl],
+    concrete_impls: &[&Impl],
+    auto_trait_impls: &[&Impl],
+    blanket_impls: &[&Impl],
 ) -> fmt::Result {
     let impls = {
         let mut buf = String::new();
-        render_impls(cx, &mut buf, concrete, containing_item, true)?;
+        render_impls(cx, &mut buf, concrete_impls, containing_item, true)?;
         buf
     };
     if !impls.is_empty() {
@@ -1414,23 +1414,24 @@ fn render_all_impls(
         )?;
     }
 
-    if !synthetic.is_empty() {
+    if !auto_trait_impls.is_empty() {
+        // FIXME: Change the ID to `auto-trait-implementations-list`!
         write!(
             w,
             "{}<div id=\"synthetic-implementations-list\">",
             write_impl_section_heading("Auto Trait Implementations", "synthetic-implementations",)
         )?;
-        render_impls(cx, &mut w, synthetic, containing_item, false)?;
+        render_impls(cx, &mut w, auto_trait_impls, containing_item, false)?;
         w.write_str("</div>")?;
     }
 
-    if !blanket_impl.is_empty() {
+    if !blanket_impls.is_empty() {
         write!(
             w,
             "{}<div id=\"blanket-implementations-list\">",
             write_impl_section_heading("Blanket Implementations", "blanket-implementations")
         )?;
-        render_impls(cx, &mut w, blanket_impl, containing_item, false)?;
+        render_impls(cx, &mut w, blanket_impls, containing_item, false)?;
         w.write_str("</div>")?;
     }
     Ok(())
@@ -1459,10 +1460,10 @@ fn render_assoc_items_inner(
 ) -> fmt::Result {
     info!("Documenting associated items of {:?}", containing_item.name);
     let cache = &cx.shared.cache;
-    let Some(v) = cache.impls.get(&it) else { return Ok(()) };
-    let (mut non_trait, traits): (Vec<_>, _) =
-        v.iter().partition(|i| i.inner_impl().trait_.is_none());
-    if !non_trait.is_empty() {
+    let Some(impls) = cache.impls.get(&it) else { return Ok(()) };
+    let (mut inherent_impls, trait_impls): (Vec<_>, _) =
+        impls.iter().partition(|i| i.inner_impl().trait_.is_none());
+    if !inherent_impls.is_empty() {
         let render_mode = what.render_mode();
         let class_html = what
             .class()
@@ -1485,7 +1486,7 @@ fn render_assoc_items_inner(
                 // we should not show methods from `[MaybeUninit<u8>]`.
                 // this `retain` filters out any instances where
                 // the types do not line up perfectly.
-                non_trait.retain(|impl_| {
+                inherent_impls.retain(|impl_| {
                     type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache)
                 });
                 let derived_id = cx.derive_id(&id);
@@ -1512,8 +1513,8 @@ fn render_assoc_items_inner(
                 )
             }
         };
-        let impls_buf = fmt::from_fn(|f| {
-            non_trait
+        let inherent_impls_buf = fmt::from_fn(|f| {
+            inherent_impls
                 .iter()
                 .map(|i| {
                     render_impl(
@@ -1536,10 +1537,10 @@ fn render_assoc_items_inner(
         })
         .to_string();
 
-        if !impls_buf.is_empty() {
+        if !inherent_impls_buf.is_empty() {
             write!(
                 w,
-                "{section_heading}<div id=\"{id}\"{class_html}>{impls_buf}</div>{}",
+                "{section_heading}<div id=\"{id}\"{class_html}>{inherent_impls_buf}</div>{}",
                 matches!(what, AssocItemRender::DerefFor { .. })
                     .then_some("</details>")
                     .maybe_display(),
@@ -1547,13 +1548,14 @@ fn render_assoc_items_inner(
         }
     }
 
-    if !traits.is_empty() {
-        let deref_impl = traits.iter().find(|t| {
+    if !trait_impls.is_empty() {
+        let deref_impl = trait_impls.iter().find(|t| {
             t.trait_did() == cx.tcx().lang_items().deref_trait() && !t.is_negative_trait_impl()
         });
         if let Some(impl_) = deref_impl {
-            let has_deref_mut =
-                traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
+            let has_deref_mut = trait_impls
+                .iter()
+                .any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
             render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs)?;
         }
 
@@ -1563,12 +1565,19 @@ fn render_assoc_items_inner(
             return Ok(());
         }
 
-        let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
-            traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
-        let (blanket_impl, concrete): (Vec<&Impl>, _) =
-            concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
+        let (auto_trait_impls, trait_impls): (Vec<&Impl>, Vec<&Impl>) =
+            trait_impls.into_iter().partition(|t| t.inner_impl().kind.is_auto());
+        let (blanket_impls, concrete_impls): (Vec<&Impl>, _) =
+            trait_impls.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
 
-        render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl)?;
+        render_all_impls(
+            w,
+            cx,
+            containing_item,
+            &concrete_impls,
+            &auto_trait_impls,
+            &blanket_impls,
+        )?;
     }
     Ok(())
 }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 3365138..49a8c07 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -2324,17 +2324,15 @@ fn wrap_item<W, F>(w: &mut W, f: F) -> fmt::Result
 
 #[derive(PartialEq, Eq)]
 struct ImplString {
-    rendered: String,
-    is_negative: bool,
+    // Plain text (not HTML text) because this is only used for sorting purposes, and the plain
+    // text is much shorter and thus faster to compare.
+    cmp_text: String,
 }
 
 impl ImplString {
     fn new(i: &Impl, cx: &Context<'_>) -> ImplString {
         let impl_ = i.inner_impl();
-        ImplString {
-            is_negative: impl_.is_negative_trait_impl(),
-            rendered: format!("{}", print_impl(impl_, false, cx)),
-        }
+        ImplString { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) }
     }
 }
 
@@ -2346,12 +2344,9 @@ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 
 impl Ord for ImplString {
     fn cmp(&self, other: &Self) -> Ordering {
-        // We sort negative impls first.
-        match (self.is_negative, other.is_negative) {
-            (false, true) => Ordering::Greater,
-            (true, false) => Ordering::Less,
-            _ => compare_names(&self.rendered, &other.rendered),
-        }
+        // Negative impls are naturally sorted first, because `impl !A` is less than `impl B` for
+        // any value of `B`, because `!` is less than any identifier-starting char.
+        compare_names(&self.cmp_text, &other.cmp_text)
     }
 }
 
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 26894a6..c366af8 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -14,7 +14,6 @@
 //!    or contains "invocation-specific".
 
 use std::cell::RefCell;
-use std::cmp::Ordering;
 use std::ffi::{OsStr, OsString};
 use std::fs::File;
 use std::io::{self, Write as _};
@@ -730,8 +729,10 @@ fn get(
                         None
                     } else {
                         let impl_ = imp.inner_impl();
+                        let print = print_impl(impl_, false, cx);
                         Some(Implementor {
-                            text: print_impl(impl_, false, cx).to_string(),
+                            text: format!("{}", print),
+                            cmp_text: format!("{:#}", print),
                             synthetic: imp.inner_impl().kind.is_auto(),
                             types: collect_paths_for_type(&imp.inner_impl().for_, cache),
                             is_negative: impl_.is_negative_trait_impl(),
@@ -754,14 +755,9 @@ fn get(
             path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1]));
 
             let mut implementors = implementors.collect::<Vec<_>>();
-            implementors.sort_unstable_by(|a, b| {
-                // We sort negative impls first.
-                match (a.is_negative, b.is_negative) {
-                    (false, true) => Ordering::Greater,
-                    (true, false) => Ordering::Less,
-                    _ => compare_names(&a.text, &b.text),
-                }
-            });
+            // Negative impls are naturally sorted first, because `impl !A` is less than `impl B`
+            // for any value of `B`, because `!` is less than any identifier-starting char.
+            implementors.sort_unstable_by(|a, b| compare_names(&a.cmp_text, &b.cmp_text));
 
             let part = OrderedJson::array_unsorted(
                 implementors
@@ -777,7 +773,11 @@ fn get(
 }
 
 struct Implementor {
+    // HTML text used in generated output.
     text: String,
+    // Plain text used just for sorting output. This is a performance win, because this plain text
+    // is much shorter than the HTML output and sorting is hot.
+    cmp_text: String,
     synthetic: bool,
     types: Vec<String>,
     is_negative: bool,
diff --git a/src/stage0 b/src/stage0
index 4261ef4..0c1f8dd 100644
--- a/src/stage0
+++ b/src/stage0
@@ -13,574 +13,574 @@
 # All changes below this comment will be overridden the next time the
 # tool is executed.
 
-compiler_channel_manifest_hash=6887616f401b27dd030fbcbfc4b009cbfb9ee3e9faa6b0c92d516211718c689d
-compiler_git_commit_hash=ef0fb8a2563200e322fa4419f09f65a63742038c
-compiler_date=2026-04-14
+compiler_channel_manifest_hash=e0c64bdcc0840d6f5fcfad29b2782e4e06ec600cd1104f81d8b7cfd82299179e
+compiler_git_commit_hash=0417c25868d6dfbd1c291dfeae950504faa6f790
+compiler_date=2026-05-31
 compiler_version=beta
-rustfmt_channel_manifest_hash=3668522db987dc630cd478b113f7d3c0963a1a7ee9fdd645841c10889a38af8f
-rustfmt_git_commit_hash=17584a181979f04f2aaad867332c22db1caa511a
-rustfmt_date=2026-04-14
+rustfmt_channel_manifest_hash=d4101af9bbf8d0ee88fbf1f82794fa0269b185bcb4cbfe0ea8cacc542cb0abc4
+rustfmt_git_commit_hash=f8a08b688cbe60acc386ed1fbd1b7cbaaf5576b1
+rustfmt_date=2026-05-31
 rustfmt_version=nightly
 
-dist/2026-04-14/rustc-beta-aarch64-apple-darwin.tar.gz=35f25ddeafd7e641a8ffe09e5a84a132d4fd6bb471e09ba21a63b38f570bc715
-dist/2026-04-14/rustc-beta-aarch64-apple-darwin.tar.xz=473e64fbc9a2deac6f46b31edf71fc603cefacca8717be50c24d43a3f83f08f4
-dist/2026-04-14/rustc-beta-aarch64-pc-windows-gnullvm.tar.gz=07e340e93aef14aa31589d9b943f378a7f14161ba0aa22166f0088b23815a9a2
-dist/2026-04-14/rustc-beta-aarch64-pc-windows-gnullvm.tar.xz=c02bc76f45b04abcfbd8b1e3dadceda3449ece891687c269b76d4454d7842081
-dist/2026-04-14/rustc-beta-aarch64-pc-windows-msvc.tar.gz=4e7825713c1669ecabc919008038f6ccc43058cb28f868f934cfd05d4b1933ea
-dist/2026-04-14/rustc-beta-aarch64-pc-windows-msvc.tar.xz=8ab15aafba975b1bf9d23351bd79c166eb8373381095d62a711ae5b1e47f293e
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=be0ec6c0b1902dd46dc58ce4f8f87ac2c5e2d099413b0b591276f6faa340da4e
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=2b08bdbce7d9cd7278abf4842152f3957a1beff5d2c43814d0c6ac8f12825c55
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-musl.tar.gz=377a556df12cfd34bae6eeb7f86f9e698240172397c54faf0217a682a3149d95
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-musl.tar.xz=d9794218a33e6d4ca77c15b60484c889078f82652a5ee7a9077aac897419c978
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-ohos.tar.gz=556e659a00cfab1fcc383b220588c58409ab7173350d0fab723f355f38d8cdb9
-dist/2026-04-14/rustc-beta-aarch64-unknown-linux-ohos.tar.xz=25b78160b0beedc1fe55eb2012177c8c9a03bd515f2619a301a1b7a996d52ac8
-dist/2026-04-14/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=da8ee89c4864aeafc89256f49f9d40371bd1dbbb2b91553176d2aaa51cfa4a5e
-dist/2026-04-14/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=c62ac733b962cc8dc559c17aae4bb55fcd1c2d5fee93d04a47591a7374523e7c
-dist/2026-04-14/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=c042154d4dc18b8fdcd9734d60857d763d34a56f794a1f9a01c1d9b721145474
-dist/2026-04-14/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=891067bb73618e7e6ff113c838dc0a564fba2941f12613330d26ed8cc5ede956
-dist/2026-04-14/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=68364bce32e6afea3041cf8c476b758530237da26000c3b413faa62a728333cd
-dist/2026-04-14/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=21e91d05d546da1e98b256b094e1fb59a9a242fa599c3a664a499a90376de45f
-dist/2026-04-14/rustc-beta-i686-pc-windows-gnu.tar.gz=bd4b9dc494a5adf72743209d8aca90d24192583c3eb9977465f052153cfd29fe
-dist/2026-04-14/rustc-beta-i686-pc-windows-gnu.tar.xz=7577925f53dbc54a2872c702a17e7a1462c4fd6611b3daa12d38f4d08c0d5cde
-dist/2026-04-14/rustc-beta-i686-pc-windows-msvc.tar.gz=709cf263932ab4190afde559bdc0862a432df6ab7e30aa4e34d3b4148a4d5bff
-dist/2026-04-14/rustc-beta-i686-pc-windows-msvc.tar.xz=63b8831ea62b767007808e477298bda0acf31528f8ca7ce0de4c31890b9ed6b9
-dist/2026-04-14/rustc-beta-i686-unknown-linux-gnu.tar.gz=fb5d2be390ec9e6355698716f5fa292b41626a737f245dfb6c9d8c118cc3798f
-dist/2026-04-14/rustc-beta-i686-unknown-linux-gnu.tar.xz=bf11c8a24b4fcf42b8ea23a941527c1d0060f222c1870aac4175a924c449ccdb
-dist/2026-04-14/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=61b6e6c27e233bb9236215682c2e452074af77a5d383a76fe597913713ff3474
-dist/2026-04-14/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=1f7b6574bd9c8f3c58d854ef432db4c8c1007fdee14c7469966f5099aa05899c
-dist/2026-04-14/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=b02f0c7e4c395768286626180f5e216d5dc6cb6e4adb71f9b55ab3d0e5c50312
-dist/2026-04-14/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=1513939ceb7afc3b7447af603b3243efbf2cca37b4b098eb9f3d5088567c701c
-dist/2026-04-14/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=57499fe1370d53c02ed33ea3ab0cd6baf131a6540b397c2f09916299c819923c
-dist/2026-04-14/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=7680b0b82da4e15cef8d934ef5cd335c7153148f43b42757b9558f94429ef016
-dist/2026-04-14/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=d8caa79cfb8bc32f6f03c6a36724ba514d0e4df1e593f4ec5008952f4433ad2a
-dist/2026-04-14/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=d81a68da3d62ffbd0696d910918617d3595460b2c96001514f8975f6d7888e83
-dist/2026-04-14/rustc-beta-powerpc64-unknown-linux-musl.tar.gz=5de50635b8b3a30ebcd1771510e443b5937aeb772ab072e4ffda9994c9001983
-dist/2026-04-14/rustc-beta-powerpc64-unknown-linux-musl.tar.xz=6d80c9118b3b49393c6b0d00112cc4007f1edaed072e2e552dc9c610ca15eb6e
-dist/2026-04-14/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fe7785ab29c9bd9d7bd3e7dec03f9246573c9cf398363280341d447ed39c94
-dist/2026-04-14/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=328679b15b417075d3de53c6a6265e7cf5bd4c8f364ea43e710490ba00d433eb
-dist/2026-04-14/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=ed6dc8119a3f7ab3377b2b9544ba5dbabb7e63dc6a49f8b4d73a61c0ea80d4b5
-dist/2026-04-14/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=cf7a33c3ff04e20f742b0ed412a32c8c79262efa9bffb32f47ff03d649c90beb
-dist/2026-04-14/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=932d92f0697bc41c4389d4974ba99f748d1a3fcf8f5c1e8d9a8a53a02cc1d009
-dist/2026-04-14/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=4570f362bf9e98cb0cac2ccf6e18f9a368bf48890b16f210b5ef859ee48fabb4
-dist/2026-04-14/rustc-beta-s390x-unknown-linux-gnu.tar.gz=03200e8cbc3e1fbba6134ed493cb14b09ca991c4aeb6086db9ee550fffa1d7a6
-dist/2026-04-14/rustc-beta-s390x-unknown-linux-gnu.tar.xz=d5650e8231957fdf3690aaf82b9537f0b62a5d0ee4efed72e4daebef37f2ff17
-dist/2026-04-14/rustc-beta-sparcv9-sun-solaris.tar.gz=73f228287087fa532f5044a11cc1aedc3378ab1afc965bdc84e53994100525e7
-dist/2026-04-14/rustc-beta-sparcv9-sun-solaris.tar.xz=010660cbf726fb142a9a6d3543963118866e0c4b4d52c2948fa9bee254a418d8
-dist/2026-04-14/rustc-beta-x86_64-apple-darwin.tar.gz=bbc772f0cd4a39df28611eeee0a0593ab43511ae67907bb2e984887855d7bcc4
-dist/2026-04-14/rustc-beta-x86_64-apple-darwin.tar.xz=e27070e6b35e442b86b2a4d6f8e0ed8f415113f3bd053fc4368fa9fe4e82c674
-dist/2026-04-14/rustc-beta-x86_64-pc-solaris.tar.gz=01520a9bd5adf08224f09e4d1e61641a87c54e091daea7269a5f259d5c9fea3c
-dist/2026-04-14/rustc-beta-x86_64-pc-solaris.tar.xz=41cd1a0146efbee090a0e3a2520413e27c4bf68889d61ce149bcf2a40e65dc73
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-gnu.tar.gz=e6896b94e55f7ca6b6321ec699274dfdee1dc463c6ec6a693403c439f9337352
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-gnu.tar.xz=bc45a96370da93dd620434a5ba8137634b721d0ce4162daf88c437d3cbfc3115
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-gnullvm.tar.gz=5c8aea2aab8599728bb90a8be7b478c48419c17a4debede8163db7329ba0bf17
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-gnullvm.tar.xz=8dcb3daa1e82820559d9a0669083f76b10333d1a048954d2e0299e11794d1380
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-msvc.tar.gz=9996f298c0f7c3be6d9779dabff2e9060a826916b6d800b9a7b738c25dd9a389
-dist/2026-04-14/rustc-beta-x86_64-pc-windows-msvc.tar.xz=594d187719c353b51e7681b5d539831f11fadc92aa6c0f8c11acd92e5855db2d
-dist/2026-04-14/rustc-beta-x86_64-unknown-freebsd.tar.gz=d418464becfe0fcefee10ccdaa19d3dd64aaf243eb79413becd47290c99b192a
-dist/2026-04-14/rustc-beta-x86_64-unknown-freebsd.tar.xz=0bb7405b32596f9c4ada34687d15d4a264ac9b3fc081f58eae75837fd23a85ec
-dist/2026-04-14/rustc-beta-x86_64-unknown-illumos.tar.gz=c789b633bb6d0ac7f8a882afd122d3706fa71213f33acbf411480f3e114d03f4
-dist/2026-04-14/rustc-beta-x86_64-unknown-illumos.tar.xz=a807261bb4636143a601ac034cb7ff24c4ebc86e6abb26d7b08a356758facd72
-dist/2026-04-14/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=202b2110c143dad291f88bb2b87434fdf212bd295cd0cb5d0ec5c9f052c1bb3a
-dist/2026-04-14/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=cb641db912cbb560398b13b76d8125b59269d315642000b347b227401b2b7f54
-dist/2026-04-14/rustc-beta-x86_64-unknown-linux-musl.tar.gz=d64ffbe28d8257b4028bfb678894e33d30e30389b23a08b92edcae5c6045e07a
-dist/2026-04-14/rustc-beta-x86_64-unknown-linux-musl.tar.xz=c800e2b4529d16ea48dfc812e00d37ce9996ba481fee6f005bdc2307d86eba18
-dist/2026-04-14/rustc-beta-x86_64-unknown-netbsd.tar.gz=8b73e9015f0192a385a8d4ddcad7ecad6122bb30b1b2d8018037e30ca791d136
-dist/2026-04-14/rustc-beta-x86_64-unknown-netbsd.tar.xz=d591f95eb864c9c81f108b12479f67af3e42fe4b208c1464bf34e1ad8fa332ea
-dist/2026-04-14/rust-std-beta-aarch64-apple-darwin.tar.gz=6013c542875c4b7b06807389ce943eda6bf421a753953ff4a0ba478cf0f065bd
-dist/2026-04-14/rust-std-beta-aarch64-apple-darwin.tar.xz=dba5d472e74055928a7a491b3849be5e20d1d4c75e327943a5358cb8e2253027
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios.tar.gz=9e0b167ef52cfae2ea2d8c6ca15618c78bb668967d542189c3896cb409428c06
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios.tar.xz=f5a033f658cb9d93fde9d4ffe5f26d1d2ce58233ee17f92e39dc9ff76668a59a
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=735b6a2edab54666c12a3f1d3b5f9240b1441b94a975c5a88be8d926076072d3
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=eb305a445467e97178e9fff0793463e1dea44bf6c151407d2523ba2e5a38d246
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios-sim.tar.gz=31af0e360e24eb1454f6baf45fe0630d0c65bd34282da7711d510b78447ad82d
-dist/2026-04-14/rust-std-beta-aarch64-apple-ios-sim.tar.xz=c1eaa173b821dba5734269037798ce8294dddf902d6f884ecacf394288799094
-dist/2026-04-14/rust-std-beta-aarch64-apple-tvos.tar.gz=71e2a7b730b09596e15ac381daff9d922d8ab30cbfa889f140a98ebd2cbbb4c4
-dist/2026-04-14/rust-std-beta-aarch64-apple-tvos.tar.xz=ea7c093c9207b2eff5400d81d21df012af45288aea2f995bcc1880db37f5353b
-dist/2026-04-14/rust-std-beta-aarch64-apple-tvos-sim.tar.gz=bc07c413c1404078d34f538a4bf40a29a5cea948c1be8063a76798d42f5a5bfe
-dist/2026-04-14/rust-std-beta-aarch64-apple-tvos-sim.tar.xz=1837af58ed6b5da3fd459b85688be51332d4fce184b5c8d38146d7f8af82f87a
-dist/2026-04-14/rust-std-beta-aarch64-apple-visionos.tar.gz=78978e79491e79ce51b89457cc8963902b76e716607d040a0ffd964a63b5459e
-dist/2026-04-14/rust-std-beta-aarch64-apple-visionos.tar.xz=6353c8dc2c985672f1a152d7ac54912a2c1d1674180d978fbcc21e690339ff17
-dist/2026-04-14/rust-std-beta-aarch64-apple-visionos-sim.tar.gz=94ef4b756be1ac66b070fb0fbadeacadc6c4757facd0dce31e085b106c6f0ca9
-dist/2026-04-14/rust-std-beta-aarch64-apple-visionos-sim.tar.xz=62620485e8b392afe687671fe35486fcabc63b3575ecbd44f5b51a114608ed88
-dist/2026-04-14/rust-std-beta-aarch64-apple-watchos.tar.gz=a052c22f70d8234638b84a7abedf0483db9e2613dcb2882398576ba1f9849b5c
-dist/2026-04-14/rust-std-beta-aarch64-apple-watchos.tar.xz=4552d9f691172dcde035ec51392cf91670309eafbbf2b9720ab7b09afc3c8cc3
-dist/2026-04-14/rust-std-beta-aarch64-apple-watchos-sim.tar.gz=8ead96cbdff29205ce3d5895ab7e8ff49113ca118b6ff2670db0934de56546f5
-dist/2026-04-14/rust-std-beta-aarch64-apple-watchos-sim.tar.xz=62617e7919793f7fc1b10a2e035f803b2b335b6b6ac0f502109b34b034abc994
-dist/2026-04-14/rust-std-beta-aarch64-linux-android.tar.gz=29737a87bb764152092cca224752ed6742844f743881ff838967f50999d8e111
-dist/2026-04-14/rust-std-beta-aarch64-linux-android.tar.xz=d6ebc87683d7a7a57b4ff185bfbc72ac50e8fca236d45f9413817639aad8aa22
-dist/2026-04-14/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=16eea786343a6e6673e4de75cd6869773a0093125faa4e83c398ab499c04e41f
-dist/2026-04-14/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=5dd472ff328477365a2d23d8db27446b512d37d164f471b0165ac1c9a8f78a7f
-dist/2026-04-14/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=c7085f64ab100996c4ac3e28ff3a40f14a9a0fc9a3675aaa4ed791bb55a64687
-dist/2026-04-14/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=9b4c2cbdac918a479c470a3bc201018e85e0d08da60645c9170d3428e763112d
-dist/2026-04-14/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c80021f80402373e2cfd6c32b582bf97c18f3ea16547ec5b22841e70418eaff9
-dist/2026-04-14/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=22978a760d34ade1abb5f215a27c2f25a1ee06c07f54bee31de2f8f14fe0ae27
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=2bf09520399cd185460d1f80d7fb43bee4687ac55e03f665efce36e8f4faedad
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=4adb753ff1779d939082479c3fb24225b17e787c8216a591790a01e2c1510aae
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=431bc53cfe5d2af7df326ca828743c55e577dcaee221a774a89f76d05bea7752
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=fbc2ec3fcadc3be21fa7918eb5a48c15c67f24a89788cd7728554358fd2ad0e3
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=4fcdf0a3f818680b824259b9706080ec72aa342546d9e1d0162ed0833972a91e
-dist/2026-04-14/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=6d24aefad9a2bfdd89322b28e2ab575fb4be439acdc167c397744bcd444ff539
-dist/2026-04-14/rust-std-beta-aarch64-unknown-none.tar.gz=34c67bcd0023e34fccb38e058dc27b27eb17ba48ee253a8fa6e4f4acc10d5853
-dist/2026-04-14/rust-std-beta-aarch64-unknown-none.tar.xz=fbe5279433bc7c596f09b500039c1a7a2d7276b4603f313b45d53d95dbb73d09
-dist/2026-04-14/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=963fd60c364013ca92907f811f0bcb55e877b10268eb00cd7691cbe6f5064295
-dist/2026-04-14/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=34442b8c9dbb730fb1f26cd7860c50be3e2820602db3aadc91cea6431128ea2b
-dist/2026-04-14/rust-std-beta-aarch64-unknown-uefi.tar.gz=e2081f1714511927cb7e9e40c60c0b22642acdc212c64a48f95cc74e8acc9516
-dist/2026-04-14/rust-std-beta-aarch64-unknown-uefi.tar.xz=eb1ed4fc8023833458ca440bc91a840d0b637d95318ae7afb7ca4fce491df148
-dist/2026-04-14/rust-std-beta-arm-linux-androideabi.tar.gz=0899ae7e5a589508fd0df89fd45d7a1abd94d36d805158dca97c2992c33a584e
-dist/2026-04-14/rust-std-beta-arm-linux-androideabi.tar.xz=f7d8f81f8240779461ea59e876abc5ca3e2f044ca6e52a6247e70c063a3d89cf
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=5df31d51a698beca3102d435c1af4982977eaba1127882411943c52180793775
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=98725b1a1d8c0424342d6266b928bef38149e77e897a22bb57a4f6580107b5a5
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2647a387059502e99afaff27957a6e3ef720a913b60b0acdeb9a27c1d6d401c0
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=8b4b9d03b0eb3bac92edda744f1856e106d37e5ca043422c07a71b6272d4d0a3
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=3ece1c0e137abfaac49646fcdbd100158f9ee0d769dc797f9c3bb2a38430c134
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=cab1ee3d87656db41dad895c18d8433eb30c0745980108457199625be496eb39
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=7fd296fc85874bd63f40173884f72134e1af4d072fc8e17cca4bc322a11857f9
-dist/2026-04-14/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=01e1760ed2b7bb0b22b1bdb74d49361354cc73a6a888b1c41644e736da8ca7be
-dist/2026-04-14/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a7b3ef47be710c1b2cf0e00103e7ca84a127ab7831466ba0c246c9d5ebc25ab3
-dist/2026-04-14/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=4ddd59b23ba17f2082b1d17ffc86b9eab8961dbf6a415ac8deb04471272ab21d
-dist/2026-04-14/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=a56cafa93dd40ee8282919d8dab0b2de139980c68f8620bd4930ee3fc89109da
-dist/2026-04-14/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=7bc9bfbcb43cab04c36b4e488eb56fd5cd9398cc98859734bf3244cbe8fa8d71
-dist/2026-04-14/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=ce1ccf6e97504c9e3f23683a3c303be5cead92f09e8fad500a905140f63e7064
-dist/2026-04-14/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=f439632779986064d0c01791a9d6a8751ec4a73158ae6f8f37b849d0df2f6d14
-dist/2026-04-14/rust-std-beta-armv7-linux-androideabi.tar.gz=d75524e780850e7002ddd0d1a6bf2deaf1ddeb7f5d0b7ace1b5c63960d3ff0b5
-dist/2026-04-14/rust-std-beta-armv7-linux-androideabi.tar.xz=5d1075a1ea9fa9ed6cc4cda2e5ce3d2ce36a26a19046acf03b8d089e6518a430
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=752e169ce834ebe749e85c5b488dc87c9e82c3426aa59dbb76ee5ca949862156
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=acd4eef57e45323ccf8723700c6fbd9eac5bd52c80789ebc8506531a5395be1d
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=7e4461d47c5c5780c0e2d14f8ed6bc07a141a542f38d1b627ab8afd194a2faf6
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=101299bd2db6e850418953e2782cf73f061b527ec1358747da3fe02510085bab
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=26e4048241c1ab874733100979afe3e7e20e0f2442cbf4c11e95b2f9aa8e78ba
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=61febc0edc1d7218fd8d954315cdb89a7ee1d90e6deab058acce1ad66ab9834c
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=408eac371812ec1b8de499211f789c1b482e922e13d7d363651fb32e51a39c35
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=b16eaead90adecd12f8381ee882ff2ada16e55db8e458754e1323c936bcd13cc
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=677263360535c84b3b97b24dbea5b13aabfe7031747d398caacdbe9b7321a17c
-dist/2026-04-14/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=3b08ab85ec8007c61d24a01845a1f3e45004cb15b1db2e108e324d466420df27
-dist/2026-04-14/rust-std-beta-armv7a-none-eabi.tar.gz=9c7ef17269b7720c2253f7c144e04f9f35f59441f40f2b5436cb2ae4e8d80d3b
-dist/2026-04-14/rust-std-beta-armv7a-none-eabi.tar.xz=1f7739485143042f4790c21f4fdb0c75728097a51818f3347efc2d47963003da
-dist/2026-04-14/rust-std-beta-armv7a-none-eabihf.tar.gz=fec1cf11cc3ec00fa2ba8c1a94e8be086e816a6e97ae64cc6efaacfec128f118
-dist/2026-04-14/rust-std-beta-armv7a-none-eabihf.tar.xz=fff07a142494aac0211524a4068b2192a71a6247475294f2b82308a9c73b4076
-dist/2026-04-14/rust-std-beta-armv7r-none-eabi.tar.gz=f0f5e5727d0a056b7486331cd79ca6a29afc2cf9b1c685cb778273fd6d18b3a5
-dist/2026-04-14/rust-std-beta-armv7r-none-eabi.tar.xz=92c269149082ed79107ff60490a3ba918f10d2c6465b1360c1261e9ed09f8588
-dist/2026-04-14/rust-std-beta-armv7r-none-eabihf.tar.gz=8706ce7c43b54b1d60aff89dc6134078e1efcdd855e9824b8a0289021a4f731d
-dist/2026-04-14/rust-std-beta-armv7r-none-eabihf.tar.xz=87426a3b108879e926231621a65f45d52847c53162c64b5e7ae91db4f50be2a0
-dist/2026-04-14/rust-std-beta-armv8r-none-eabihf.tar.gz=b35d31f454cbf07b75132cb6d22b404bf391a84cc20972ea28ea6bf534fcc1ea
-dist/2026-04-14/rust-std-beta-armv8r-none-eabihf.tar.xz=4c8c438e4ce34ff3e09dae7bb3777cfba15b6d82b66b1665cddd536eef79458e
-dist/2026-04-14/rust-std-beta-i586-unknown-linux-gnu.tar.gz=7b25c21325961de4a9e2eb9d0d597f89b84a0aad24aaf056d141c8bbe9a31c59
-dist/2026-04-14/rust-std-beta-i586-unknown-linux-gnu.tar.xz=60d7f231e43b8c4f19d910775f501ff422a715cdf2accfd7da1c5fed4608f722
-dist/2026-04-14/rust-std-beta-i586-unknown-linux-musl.tar.gz=66fdf2186dab3ab7ce4e8e80d9c06e1dec9443b1b346e13b41edbd1a1c0102f0
-dist/2026-04-14/rust-std-beta-i586-unknown-linux-musl.tar.xz=d84fb8a2e32ce007bb684a2c7343765f67308dba819c318a67f124ec4931a1f3
-dist/2026-04-14/rust-std-beta-i686-linux-android.tar.gz=1bcda5b307283fa1a09d068af8a34903b9dc8cf0a0e9df78c7cc6e9bd6d9c67d
-dist/2026-04-14/rust-std-beta-i686-linux-android.tar.xz=5c5b8cd75d90750dce6f712ce48a5b8ec36d8956a342a9bcccfb5a23c3735d6e
-dist/2026-04-14/rust-std-beta-i686-pc-windows-gnu.tar.gz=4667a8be20fcc3fc22d03fa61f7372ae7e481dc3410e55d0803102b4d8a5d8dd
-dist/2026-04-14/rust-std-beta-i686-pc-windows-gnu.tar.xz=b2e91eb407e0244e8d6261f21bd6c9dbac6e8b6b984eaf4cd5b0ed60a5e9f1b7
-dist/2026-04-14/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=64888f2e06df70ad3e9946512dbdad7d4af33e6603de982daa1a240fafbe530b
-dist/2026-04-14/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=71209cb50e94b17b3f935fd2218781d3674573f9bf106225895f3cdf81593670
-dist/2026-04-14/rust-std-beta-i686-pc-windows-msvc.tar.gz=0948bbf181985b79d1f5e6aa5f839f3d609b4c54fda4e29d421f84b71136e357
-dist/2026-04-14/rust-std-beta-i686-pc-windows-msvc.tar.xz=33a732cc6e7bf8aaabe2a178ac0bfa70e6d242f152a59a7878a924a0e8d8bf47
-dist/2026-04-14/rust-std-beta-i686-unknown-freebsd.tar.gz=1b797a89bc8a1c6bfcddc2c910244f4c50bf65f6d2ad10a02ed3b2433b177b77
-dist/2026-04-14/rust-std-beta-i686-unknown-freebsd.tar.xz=690cb307bf3370d0420b75e9b840c7650d2270aa7558cd32bc9f1e29498e9c3f
-dist/2026-04-14/rust-std-beta-i686-unknown-linux-gnu.tar.gz=87d824e3729b9563fc204ffe6802041cec062a5fa31900c584272999d791c501
-dist/2026-04-14/rust-std-beta-i686-unknown-linux-gnu.tar.xz=6a07723ee0fbdbc21f09471b00d041be3f840c988a63a174312854c3a0fcda10
-dist/2026-04-14/rust-std-beta-i686-unknown-linux-musl.tar.gz=0068d602b3b6bcd22ad055690c96a6defd909ea12dbb7a8c39474f33526b5981
-dist/2026-04-14/rust-std-beta-i686-unknown-linux-musl.tar.xz=eeb31d7361dae97764346f42ef57eb1b3dc1616d60c43f4bd42a76d50b1839c7
-dist/2026-04-14/rust-std-beta-i686-unknown-uefi.tar.gz=3f2183ec3e0a66602ac8b5f01a400affe85fa8f776e72911d777235a9c25a265
-dist/2026-04-14/rust-std-beta-i686-unknown-uefi.tar.xz=f37ea30acea8e74db40928e051d15d046758de864d87e90ae249b625d90cd5e3
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=67512594c23ee664f9d924d0487639d0a642018f27d943345cb00e0f5a8fa97a
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=43b724a9bd522900c7f658217ce48d02ea7a8c89d8f5f3f51e7df02087405bef
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=986c985e096ea86ed7b2d1a12130f526362dc28bc27d21b9bf642c06fdf7d036
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=39f0c3ec23c6be8c573ea03dddad7b61aa84956ee774ad0d7049fac78dca9282
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-none.tar.gz=57b90f6817daa0b28ea117219321a03f8ca9be26b3873d5bdeaa08f94caea8bc
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-none.tar.xz=23e84ca4d43fc6f78bf473e181f09639061eae3020d1f4a1525a980967ba897e
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=0b95e470f9564a9899420efc641abfb7b46120f27eb277c0d8dcdef692815f6b
-dist/2026-04-14/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=8923893c37f660aa08587bf9c06f796bbe4c8f469da33e9841f24697a65befb0
-dist/2026-04-14/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=b4a7eadb59dfcdddfc882c59fc059b8ac968c5c45c66ad2504e0048a712a314d
-dist/2026-04-14/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=ad408710eecf9353b3565d24cbce684b810265fac9324e96995eeeb6948f9fa4
-dist/2026-04-14/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=735d1b011f57704fb553be29ec5ec27703025dde6f4d9623fcee8e0ba60c13d4
-dist/2026-04-14/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=6a8ee3e6bfebe6f619ab33401da28385df423ab814c55c05d6eb156ce4903014
-dist/2026-04-14/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=06a4273f82bcdcc301a8dbef9b3c9cd3dbf2f88b4c242e69c23b87cab201d990
-dist/2026-04-14/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=8ca85e52af77b2f4aed7b5cf5bbe50ce5c233e86e82a9eb29bf2814202d1031f
-dist/2026-04-14/rust-std-beta-powerpc64-unknown-linux-musl.tar.gz=3b9d40c90eae335fae3ab7436484fc91802d2c6d0f94427a615ccd9781ffcf0c
-dist/2026-04-14/rust-std-beta-powerpc64-unknown-linux-musl.tar.xz=7f86fd52fb0c3290d2401d444c3687c9274abb69d707925c298cc319be46137a
-dist/2026-04-14/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=e37d1cb29035269a9c5d15cf27e30fa8d81a44d393da65ea01dd73c8564d46fa
-dist/2026-04-14/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=bb73b66a977404ed1edca3e619505929e2c6170a06852c90e12a9417d50954f2
-dist/2026-04-14/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=7ff24f319f4a0ada9cc1a38e4ac87049769e4d1dae617c7069b80591124060cb
-dist/2026-04-14/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=c20fb415904b6d2bf8d689719a2c53ed134dc94b5a7a818bd612a4e9d7ca4450
-dist/2026-04-14/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=3bf45887fe9517b57728e83cedd23bec736206ce3b6f3ad6ca647d6e2cbbe517
-dist/2026-04-14/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=561b4b200f2f1f96be5e915c28a0d42c81f419f754efdb158935baab3066758c
-dist/2026-04-14/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=c29a80ee52e8b07afb75f804b5b2a29127a45c2a1774c8fc1efd48fa5629e87f
-dist/2026-04-14/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0ff4d4e0d749c1e40aa7b59f9ee52b1594718a9bbf8d79b7627fe01e9bfa461e
-dist/2026-04-14/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=379fcac072950044871aacdda137e32fbf934976537ca2e49a23f718e8fdad9e
-dist/2026-04-14/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=64b9f736957ba67c3e0bd62bd5157fca4a788ad979e57dedaf2e601312353a9f
-dist/2026-04-14/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=f8f97c8dc2a8c1729ea90320f0760d19be0929d57abcafaf3ec2733626067554
-dist/2026-04-14/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=6339b9293a9fe88928716dd87604c018398ed678206353e8c1bc59ecbc211846
-dist/2026-04-14/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=89172756ad74df0ea7d7a03e63d44f83d5aa4a8fcecc3c6935ccf9138dfecf37
-dist/2026-04-14/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=5e87760598d9f4eb40bb664d12eff5f69832d4f8ecc97776c19ec2f592742943
-dist/2026-04-14/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.gz=148bba9bf536446383c80cf9bf866c2f882b37a7536de632b1cae77d6c4c6cd7
-dist/2026-04-14/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.xz=5df62d006ace8216d4bf5da398fd11038c1180e355d09ba4aa5d135b9e87d643
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=69eb4a6ac52e8928e8ae3062a486cb487547720eccbc3c6d19b9f7cf261e4756
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=03fe5f8bf31fdea6ae8c82eb7997581bd9e79f1faae924e02651b843877dea57
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=8c3c29f64aacf0ebaedbe1c4c5f5718b043833d23af8a9f5deb63844c3031870
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=dbd8aff208458242ee2b24240cb09f8489657775aaa2851bf3e4b7899665bb41
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=29c2d5ae7991ba8c13a84182a463d49eff6883381a9e5d56b72620a307efeb72
-dist/2026-04-14/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=405f36827c61e88081ce530ccdf4cd10b04792ce147da969cddc49848c060ae8
-dist/2026-04-14/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=bd4fdb1540d9efc276705a6c6bb885a7b2eb2576a7d898d9652b2c76f9c4d3f7
-dist/2026-04-14/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=50ecd65092814939440809320ad26e1f513b69440f9fd096cbb98febb9d73613
-dist/2026-04-14/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=c7347cd70f6e6043998f95778dd866e90d36e3869620f4911cec8c1fba8dd37e
-dist/2026-04-14/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=3fb46ec1f8b524951d726777808d02eccb60d993ffc6dd9257eb123c2608e1df
-dist/2026-04-14/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=a21c41a777bc49c7fbe1a94db0bbd967da6dbf78ea6585e8caaa979910b3e2d2
-dist/2026-04-14/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=3087f50de1e9ded03eaaaf3b0dd6df496ddc1af850760e819fabc3cc8edc35bc
-dist/2026-04-14/rust-std-beta-sparcv9-sun-solaris.tar.gz=631e3bc0c65eb53e285068141a704dc6d3f332e03b5317d001d50eabe92040db
-dist/2026-04-14/rust-std-beta-sparcv9-sun-solaris.tar.xz=fbed5576340f2edb94a6e40e851c94d3f3cc20cdaf29210a6d9868efb7ad7047
-dist/2026-04-14/rust-std-beta-thumbv6m-none-eabi.tar.gz=b5b49246ea75b70be44f75f133b5769efb0bc7e837b2bb5e73e6a633a9a0d89f
-dist/2026-04-14/rust-std-beta-thumbv6m-none-eabi.tar.xz=c20183595eb818240f2d6ae5ac2f290545f336a79a13b3d0ff47d026e97324c8
-dist/2026-04-14/rust-std-beta-thumbv7em-none-eabi.tar.gz=2350814e9a23bc50ef752c030a91d193af1ebcb472c69bb86a2a8eca1df82fde
-dist/2026-04-14/rust-std-beta-thumbv7em-none-eabi.tar.xz=ee8bd68fff8785984394be950e5a2670fab6bc97fba0fe07fc8c6b0ea4a21c7b
-dist/2026-04-14/rust-std-beta-thumbv7em-none-eabihf.tar.gz=52b95f6490f605c705f51271c3a51670b93ef656dc0f362cf80c55a8dd6a4d6c
-dist/2026-04-14/rust-std-beta-thumbv7em-none-eabihf.tar.xz=6561a6492671fed31cde55f7cc9f26ceea264d39ea8956019b191950070aa2e8
-dist/2026-04-14/rust-std-beta-thumbv7m-none-eabi.tar.gz=25be4ca3b6a10305d4a2635097c8a7004a5c7559a09c50624bdc0b702217796e
-dist/2026-04-14/rust-std-beta-thumbv7m-none-eabi.tar.xz=5aa785888c25c28f9c8dcca2b2a997ee1d98cc4d48862a54d30899623166002a
-dist/2026-04-14/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=6a40fd7bcce8973a5d43beb7e0ad44f2642fb005f2390fb53a143d695345d0f6
-dist/2026-04-14/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=753dbd9da49cfa43c48e4517b6fa978fb2f9bdac3af44969d69257cfb7db69db
-dist/2026-04-14/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=1d74c05b74148be14a7906898e388e2767087e9c7463470f4cd267d7af342e87
-dist/2026-04-14/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=7fc7ff79ba5f51588267f39c0818ff36b38a44a95aadc68313239305430cf9cc
-dist/2026-04-14/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=676370ac7fe9e68008c5d34b551375b011b462caa1615b6742887c368c92fb74
-dist/2026-04-14/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=bbd1fdc73a5fd3041a10a3d0a691ac6ad555b7e607728141561a87f6be445b71
-dist/2026-04-14/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=4775806ee6bbc4a1b3dff3d69ee9e4bbc7f24fd5f69c8fae9b1c6492ebeac0df
-dist/2026-04-14/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=83f2bd359159a9cee03d101dd81f072598f3d29e16d4ee51375fd8c6be3002a8
-dist/2026-04-14/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=0ee91403953c903c944a2095bf43712be9b8580ddc2027727cd2b9fd908d3cda
-dist/2026-04-14/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=19770040efed493c454a379c5867a559ab2aab077600179f965e6d55c00d8772
-dist/2026-04-14/rust-std-beta-wasm32-unknown-emscripten.tar.gz=17d72ddb5df498a29de994097171eb65f39e43142f9fea44c7c588a8cf7f8c89
-dist/2026-04-14/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fa5dba0405cc2bc8893de48ad0bbd47dc6b1b89897a522e5294aad405f9cb4c
-dist/2026-04-14/rust-std-beta-wasm32-unknown-unknown.tar.gz=9a214857ed14b5e99cd8a42ee597c3462f24903c5df5ed6ef18505403836fafd
-dist/2026-04-14/rust-std-beta-wasm32-unknown-unknown.tar.xz=4f8538320fa5d6a0be80b7b0cde55685e2a99f6fabae31588cb69b4664262382
-dist/2026-04-14/rust-std-beta-wasm32-wasip1.tar.gz=28ce59923c406c04da99e8042f99a3243f93dd48c4e8a7b0b48fab23a9fd4a4a
-dist/2026-04-14/rust-std-beta-wasm32-wasip1.tar.xz=dc4fc5da651395ca3d777e50fe8e756a593584848902a4bfc6a095db50ae5952
-dist/2026-04-14/rust-std-beta-wasm32-wasip1-threads.tar.gz=1e18820b7a3269c9ca89d54a2fb22c77b2803860802d9ab62085c1d28f5a70d8
-dist/2026-04-14/rust-std-beta-wasm32-wasip1-threads.tar.xz=f34935b5c8524549f6cf42d88e41f49a745149dcadf862da8b70e577af18d50b
-dist/2026-04-14/rust-std-beta-wasm32-wasip2.tar.gz=699eaba1de898d9c88bebdc2228846a53a2692ea9bcd1b53af90904f1fc905a5
-dist/2026-04-14/rust-std-beta-wasm32-wasip2.tar.xz=fbcb1d9aa12c31c26ccde00793bc3bc6d6dcc8ea2f5d42d29a9de1344a34d2dc
-dist/2026-04-14/rust-std-beta-wasm32v1-none.tar.gz=73ef93d8c72a79ff25062e8d4acee6145127edcf1d7fc2debc16d79846e931af
-dist/2026-04-14/rust-std-beta-wasm32v1-none.tar.xz=a7bd4d7ef9a6d22ba67e9f7bf2644e906ea13250e00c5799c6472433691f0540
-dist/2026-04-14/rust-std-beta-x86_64-apple-darwin.tar.gz=50c82762dba2482a5cb2d57760ed9741de19ef54b6bc23d2a8fcec01addb21c4
-dist/2026-04-14/rust-std-beta-x86_64-apple-darwin.tar.xz=57682df246caf478ba3a36a99a562276d9be91efcb43625f52f4c33efc4a24a2
-dist/2026-04-14/rust-std-beta-x86_64-apple-ios.tar.gz=40d1aeca1d258a3ba9030e718bff4d98974a1a1a9b7690c03f13771e4d9b2835
-dist/2026-04-14/rust-std-beta-x86_64-apple-ios.tar.xz=b47d2de0b8dc7374778f60f38ec4c51718cce2ce03d6b6d52f10cddd95d47e22
-dist/2026-04-14/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=42819ce12cff11d91a384a7f7c16acb31e5ed0796dbf118dcc6f09fb49989896
-dist/2026-04-14/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=44344c81123c8ff8ef719ec60bf5ef1cfe9f2c6f072fc3e6e68b67113008ae7a
-dist/2026-04-14/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=9a9a50924691cd00640c4f548637a0d0f9c0cc49992d2a18e04829b4bd979533
-dist/2026-04-14/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=cf7cae05b5426a2e6005b2b58e4aeb25e7311bba8adf619ca47dc0123f098f46
-dist/2026-04-14/rust-std-beta-x86_64-linux-android.tar.gz=7d8cdf37883335691b9d03cf32c42eccfe218bc9423d6906be8c661852759f2c
-dist/2026-04-14/rust-std-beta-x86_64-linux-android.tar.xz=9d5b7d6c2ea90a3dea1fcd0819f22ec7f5b1bdf16c1e3bd92846f21cacdfdab7
-dist/2026-04-14/rust-std-beta-x86_64-pc-solaris.tar.gz=6f478f919242151b96db59f5d76d71183a0ce84fa6d00622d386f9d084d60961
-dist/2026-04-14/rust-std-beta-x86_64-pc-solaris.tar.xz=3028c3306991de15b2b3036a6cb890550ef207adda362c087359f439f48a93cc
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=5b43f65b66f87ca4fc7233265584ec1659978cd124419a08cde3d027c6d6bbdb
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=b260fead983056e8783a222ba79bf3226114ccacd580d6202a192508d29f1b33
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=f70153e96e4f488ee7e2ecf4d75dd4df4d9575026bf53106bf3d3bb9ba8bf3a7
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=65b5ad8f6e187acde0ecf5c19ab8e655c2cc8f0583305d718cc234c90971c836
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=58406c05ce0d5b3fb66eb9817fd15e9c395b09d5787e141a15ca78a68fb98304
-dist/2026-04-14/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=868d2c22302fbec4fd0a2ba3487ab18fe42869a0220310282adc5b447c04719b
-dist/2026-04-14/rust-std-beta-x86_64-unknown-freebsd.tar.gz=f31ff0364cf1be7c402a14cc8ce405f80077beb8ca962818cc285824b8db40ad
-dist/2026-04-14/rust-std-beta-x86_64-unknown-freebsd.tar.xz=2e5675d3aad9dfdb4a1d75de9a400fa57e38b222d0719c3e52e8c289ca1047a6
-dist/2026-04-14/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=2820e5e7cdde029a1174c400c83cc41469d380c02d8221361280d8bff814434b
-dist/2026-04-14/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=e21ccec9aad3efabc99140f2a44fe9de1815eae4a58de385b2ce1d22ae7fab6f
-dist/2026-04-14/rust-std-beta-x86_64-unknown-illumos.tar.gz=bd5010155c3549a1a1bfa2b893feecf4a2793c5f816d1cb742a86f6358a65a81
-dist/2026-04-14/rust-std-beta-x86_64-unknown-illumos.tar.xz=ca1e90e5b466c94efd7a096f6fd2d374afcfeb84d8399720f05ed72017bb79c7
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=88f44c8abc2c0aa5c70ddea59dfbb89be53b5b85368176f56c076ab79174f8b7
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=fdd83dfeeeaf49f74e2e497130c21837890497f4c7d58c0a06c2ae58d1b027dd
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.gz=6eebf35f6a4ca2a3b6e9edbd14c8f744500d0099e5e4d15011db61baca5dac28
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.xz=58bb277404b0411c874c8166998c5eb9e65ad62dfc6f3ba86afd73a0914130c2
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.gz=15b046a6e773c4320254f458c55086d89a3fdaab38b74b8d5114501586287299
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.xz=ebf82cf26e6501fbcfd38bef06cd6f909511e153498b18396ecab0ebd1121406
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.gz=a38f891a40d4f1bdbe3bbf07aa110424ff2c5df9cc63563910011e87e467b5a5
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.xz=f9757ff55c259b7ff1fcd492ec06d69553938f99f0eaa711278f3d1f3bac7c0a
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=23a89fb8c8aacbfdc67e99413bed782c36a0cea5d2180a454da8b721aee11ae5
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=08675069d43335aa0b0a4edbd65a976fb9d81b75da057fe88f95d7ba0f2a98cb
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=3b0a9acfaba18dd71ffe8f2d2f370b2e6d4edcacaee2ff7df7024a233c2b1d32
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=c6a1e40a41795fcab0f197eeabc053360f59c62c3e03f94cc11d903b796f61fc
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=4d51229b6c2f4d7401a8e857152b775ee1cad28a2979279c4e177fbdb36a30a2
-dist/2026-04-14/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=174154d57be317c14591c395921eaf84577d1940f7c8bac41511c382215db391
-dist/2026-04-14/rust-std-beta-x86_64-unknown-netbsd.tar.gz=d85c23928b7ce3c8712dae2219241ee087fcfa999a719624f4d1a71096304a6a
-dist/2026-04-14/rust-std-beta-x86_64-unknown-netbsd.tar.xz=4b8115444b5c858f36979b7c4a48e5d8c4a30ffa3dc1ddbeebb31260ddfa44c7
-dist/2026-04-14/rust-std-beta-x86_64-unknown-none.tar.gz=5d4e27304c962a66c43086a8fe8e97e76a582cefcf70ba7bb552b7497998081b
-dist/2026-04-14/rust-std-beta-x86_64-unknown-none.tar.xz=d58340f1ae3119ff10c63dec6cb6d75260a4f3f5439f18795f12e64d81414fa9
-dist/2026-04-14/rust-std-beta-x86_64-unknown-redox.tar.gz=1b0f178e222e70b2ef524a6148edc8e4097dad79e4c9bc74a1b91b68eea62b4f
-dist/2026-04-14/rust-std-beta-x86_64-unknown-redox.tar.xz=7545a14f2ce4a2358a850a6196061e70f98966e52122d9835666c09a1059e5ed
-dist/2026-04-14/rust-std-beta-x86_64-unknown-uefi.tar.gz=19ef7d625c8118c5dc283c57fdc07ae3d5a503bcb04d36156146ca919893c310
-dist/2026-04-14/rust-std-beta-x86_64-unknown-uefi.tar.xz=d79bd625887bdc6339e22fecc0711b9ff211c2531fa8e9a4e1e344468da8745f
-dist/2026-04-14/cargo-beta-aarch64-apple-darwin.tar.gz=213adf0915f775399a516647bd90e4f88cd25c4b2c95eeea441939cb4ecc677d
-dist/2026-04-14/cargo-beta-aarch64-apple-darwin.tar.xz=b1b5bee9c4f4791b91c40104f18c337ca280b4c322cf3b84178fdcc0f021948b
-dist/2026-04-14/cargo-beta-aarch64-pc-windows-gnullvm.tar.gz=ce484bc7863789505f68e2df118d5819621fdb52756fc0c5ad1ec6cc7139e249
-dist/2026-04-14/cargo-beta-aarch64-pc-windows-gnullvm.tar.xz=25b0600034fd9af3a7a1c09715525782fd4c821932359c2a1e539fa6718a17df
-dist/2026-04-14/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f8b9669ec25f47ac98eac797d988dfa30c6d0e9f8506b4176c7fa57a4eb4fba0
-dist/2026-04-14/cargo-beta-aarch64-pc-windows-msvc.tar.xz=0c980f162ece80ed34fbc41a78d43f6a1486388d7b0e042b160c29186718470f
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=9c9a9c217ad3ffea38dd9868645e33b913de984e13b6fc5f06635ea45e47d57f
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=1ebfe88245ec5262f98676bee6b662b5988b6ef9f9eceb5deba88ab4f6adf498
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-musl.tar.gz=6132fda7de92ea586481f7caac8aabf900e76cc5e15e1c9cf1ec66d25ce2267a
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ba2a97b47df7a33eb77d66e3fb36a051e16d3b86e09ba9d7d430c71ad49970a2
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-ohos.tar.gz=f834b14156554d76f10ae7be9e67d39d88f3f86fd019a57560ac8d22a4fb4e2f
-dist/2026-04-14/cargo-beta-aarch64-unknown-linux-ohos.tar.xz=33065b9cf13e4f3bcae8b447a57bd91c1e7420f33f4a5f10768def727fb6ac01
-dist/2026-04-14/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=32ec7cde4277b3eb8092fe7a316af3d53ff200f4e1cb4a679d0bed86781a3dd4
-dist/2026-04-14/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=542428bf11f888825351a2330092d89e6e84ef64fc04e6f283a4d589f2f2dead
-dist/2026-04-14/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=5ffb33982db8438b6a70301ed62113aaff95762831dda734d70527a19aca98ac
-dist/2026-04-14/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=5df4b9b37067678f5b6082a9e8c78ced917a316e21abfa1558537cda8cb0a5d7
-dist/2026-04-14/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=43cb17ecb56bd720c3149826aebd7eeda20a9a94fa6ddd421cacc1c26c593a4e
-dist/2026-04-14/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=deaa36c83c4ea2debfb2ef764e8d7c3032ab78f3013ebc54ccd88bb14fa9a669
-dist/2026-04-14/cargo-beta-i686-pc-windows-gnu.tar.gz=60deced1cf0893e5041304d0b011a6c1ecb2607c73f832a07bdca51eca1db86f
-dist/2026-04-14/cargo-beta-i686-pc-windows-gnu.tar.xz=5f135deca4203757c494822f9cfcb309f014afc280855b759033b735277f5e88
-dist/2026-04-14/cargo-beta-i686-pc-windows-msvc.tar.gz=c3c180c8a2ae512b1114a10b0780436edd205ca0a0c4fbdea037f23dbed06a72
-dist/2026-04-14/cargo-beta-i686-pc-windows-msvc.tar.xz=9e5c5582ae00ef80426cb4d4de8dccf546395ddd30c67cd40f4ec477b7324ce7
-dist/2026-04-14/cargo-beta-i686-unknown-linux-gnu.tar.gz=588bba2636c67b505e8d2db45111ca23e37fde5473d33ba87d4f4a1cb69c4e85
-dist/2026-04-14/cargo-beta-i686-unknown-linux-gnu.tar.xz=0fc96483c3d372ea591bff13e06f3a0ecfb2ae2c611cc08ec3a2ba6158b12217
-dist/2026-04-14/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=57fec616e8429e94b8007539a1cba2d0d6352a7406157fb524b7293225fe9945
-dist/2026-04-14/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=854bc5862045d907f62ab4372ae8805c3decc3dbe97d688515fa2c8f65cefa29
-dist/2026-04-14/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=ad3fb29c460353031f542d923cc0a8812c6bb4a9bba887dc6496479eb71aefe1
-dist/2026-04-14/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=e8facd620a406bf3dbdbe5d76621f7fb560f13d86b52286564a25b0eb567dcef
-dist/2026-04-14/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=2a86ea9a1c2a1a2503cd676b71c3576d3ab19a06abf07d36357daf90f2bf932d
-dist/2026-04-14/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=7bf26293463c40551d53452d26753bb43e3731729f71090a2ec72474b75e8d5e
-dist/2026-04-14/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=1a9eb79a7ee2f4ec769a884ec253a8cf133fe58dbaed032248c9b6ad65d6f2f3
-dist/2026-04-14/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=a1dffc50cfb99386cd8a2896ccfa781b297cbf7949563cc84c6ff7c4fe1e4df6
-dist/2026-04-14/cargo-beta-powerpc64-unknown-linux-musl.tar.gz=aae0e1c8dfb0ebf5efa4fb8c2d8766dd6f0a97a92b401de288693198716df969
-dist/2026-04-14/cargo-beta-powerpc64-unknown-linux-musl.tar.xz=37725c9c02e32a98b9b0bf214c248757e5fed39e3ac70218a5fba7372e9df049
-dist/2026-04-14/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=722430e82753479347676a6ac17930903fc2be8e11ef63a683a1289e0ff23d97
-dist/2026-04-14/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=a2e7fee4d916323833c6f9af13da057a419b85a6bca89817dde79b8683f01a79
-dist/2026-04-14/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=931df7278f7718e96ea2585a5a39e436204686f32fb4a84fce55c689f918e9fe
-dist/2026-04-14/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=38de6ee97d0e830e9eb07551632179fd821385c3578070801c4ec290ba49952f
-dist/2026-04-14/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=27f35cc8add94c5269d5228193a97d2400d1b36170426047275266f0ad93b762
-dist/2026-04-14/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f228ebbdf135314552ed9640dd19119c4b9d064a015e93f5ca489dcc6faff050
-dist/2026-04-14/cargo-beta-s390x-unknown-linux-gnu.tar.gz=6d95df12df479b04a276bad4f41f5ec2bfc9004ec6161a1fac8b9fe0771daf34
-dist/2026-04-14/cargo-beta-s390x-unknown-linux-gnu.tar.xz=fe3e88044788f3e85bb158271a0ec9b034c9818c896ac983e990a441a82a79f6
-dist/2026-04-14/cargo-beta-sparcv9-sun-solaris.tar.gz=0654f1574b4f48a4ce71ecfd353e6bedc260112891d4516fabc5335ddda227b1
-dist/2026-04-14/cargo-beta-sparcv9-sun-solaris.tar.xz=ac52160aceb03a6dbef33d3d02585533d39308e587a2c4a365f5b50000c09d53
-dist/2026-04-14/cargo-beta-x86_64-apple-darwin.tar.gz=3937531fbf60f4eb0a153543b65c4085e63fb0f7a24f9031b39efa3aaabbbbf9
-dist/2026-04-14/cargo-beta-x86_64-apple-darwin.tar.xz=55ded2e0e71ced8150c5aad0ed3ec803e61605cba72e3f6e3310d18adde88dc5
-dist/2026-04-14/cargo-beta-x86_64-pc-solaris.tar.gz=cf270a0fa52af2bc2dcfb5e4a4a53fb63ef4104c4ceeed4db2947aead6f43aca
-dist/2026-04-14/cargo-beta-x86_64-pc-solaris.tar.xz=a9e6be85459a60a23b71f60b8d3b36cc7b30f07c22ed11d4cc0e165cf0f11396
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1fccdb6f7a4e0ce9f8f874e7e40e346f1d8a12b483c577476eaf374ff5f68313
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-gnu.tar.xz=81c0dbec9baefb620d51bc90f3974ef520686c3ca9479e1eb51fc75a08b66a5f
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-gnullvm.tar.gz=2655f6e1570112c4b059641d41e9fdbfa162e1f353500acb6bbadf1597bd3e05
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-gnullvm.tar.xz=de098a48e37880a82529fcece1bd696ca2333d9014565e1e6871d5fbd163c073
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-msvc.tar.gz=f35f2076d05aad7e2c18741958c4e11ff6d684c123c3311a4b10d53cd8b5485b
-dist/2026-04-14/cargo-beta-x86_64-pc-windows-msvc.tar.xz=e2867131b82d110755209a81eff1ab178eb01c2b0db72b76bc9d3818b4e26bf1
-dist/2026-04-14/cargo-beta-x86_64-unknown-freebsd.tar.gz=28d105b9cd197d6f79dd0dc3ed641b00db411da99bc7458570928507e24d9fe1
-dist/2026-04-14/cargo-beta-x86_64-unknown-freebsd.tar.xz=b825bad21b29c0152c94bbf6d30e4b84ffb73e7669a786a91b4d01c25e0d26c6
-dist/2026-04-14/cargo-beta-x86_64-unknown-illumos.tar.gz=3760b75f3b6cfa2424a145548d70657accc3c53e55b1f4ecf9d5f1ff05c7f567
-dist/2026-04-14/cargo-beta-x86_64-unknown-illumos.tar.xz=c7edd008d2c0b288d4f3ca1d3e51510bc5fa181149f7c874e46875e1f646a6bc
-dist/2026-04-14/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=ecc8fbb9a4423376f66096086c0b3a33747563dfc1e0221bb5ad00de2483e59f
-dist/2026-04-14/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=d08610c85372207fe77e0e9d5b0d1550d693a34cd983a8fe3e608816b6a8f9a2
-dist/2026-04-14/cargo-beta-x86_64-unknown-linux-musl.tar.gz=348988e5348c6a4c6542e7be10468b31b02d2fb2ba230b95331bff4291324b29
-dist/2026-04-14/cargo-beta-x86_64-unknown-linux-musl.tar.xz=caaf97cfad81738cd18f62a4f32e03568f5879f452001b78483457525e4911f3
-dist/2026-04-14/cargo-beta-x86_64-unknown-netbsd.tar.gz=b11d6f71aa41d5a97ace1e6ef5f0e87fc334bedf7c5b666a0c6748b4b9850a83
-dist/2026-04-14/cargo-beta-x86_64-unknown-netbsd.tar.xz=d637902fc57d547bef7d020c0ee4e673ebaab557cd422eab5574db3fac46fb93
-dist/2026-04-14/clippy-beta-aarch64-apple-darwin.tar.gz=fdfc08f98f9fc6281dc7af4ea6ae00e713515fa7d25821fe6bfa4e4c0266b8ca
-dist/2026-04-14/clippy-beta-aarch64-apple-darwin.tar.xz=0c44e33c08f00ce950ec5490478cc1f18a4d55a2f6855410a7fb541659f4b0d8
-dist/2026-04-14/clippy-beta-aarch64-pc-windows-gnullvm.tar.gz=06da22269fef9e3fd5127b1089fdf96aae9c67ff6839d22f2bb8010f7046d68b
-dist/2026-04-14/clippy-beta-aarch64-pc-windows-gnullvm.tar.xz=6d92cae636ff0731b4aeeaa7e8abd8a0d6f41df23afd8d9bbac45d977cfa168f
-dist/2026-04-14/clippy-beta-aarch64-pc-windows-msvc.tar.gz=f1cbe38245fb1350662872743e06edf824f83b86af9cb775d8231c25428f1032
-dist/2026-04-14/clippy-beta-aarch64-pc-windows-msvc.tar.xz=06aaf155e5660a17a220eb99e29fe76e9e90c4d4864b556e9b2e0091bfc0563a
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=997b59820b2628d043076a6a6085dc99267ad3ed9a2e78b1b90c58a6e3a6fe35
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=584aab51a31eaa66001a69cdf95cf0003abd378631f5bf44731f35c7aa5a1195
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-musl.tar.gz=ed573079fc0e3e33bd297b0d76bc01e3f15dcbf83f8461a5f4b43836452867fa
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-musl.tar.xz=fe5762b039fd7decf8ce9163904e6293169ab235ac7551902a1d2fbf88ea520c
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-ohos.tar.gz=01337c1c5fc537d1c447a3bf17a44d3e37e319cffa1a52996dbed7fc6c05ac30
-dist/2026-04-14/clippy-beta-aarch64-unknown-linux-ohos.tar.xz=0f36a948f1472aaa6d2191b6295b996ab59e2bea2b64ce203f9e2d90b496189d
-dist/2026-04-14/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=40a26ee6db3512212e2a57770f236976225088deacc9a339a8bab19a9f00cf6d
-dist/2026-04-14/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=27fc628812f1265c637ceeef0b7cd39cede6d0d8e3cdbc8eadd3a360c4d8fd92
-dist/2026-04-14/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3c9317e362605e3d2b6468e5564a7342384aab333479da48e32bd36996e96f76
-dist/2026-04-14/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=38291528c671589a84c1d73bdd08a1a25fea8e2b82f0493879b6f3b9581f3cf0
-dist/2026-04-14/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=75ab9dad5a01f3ac1053fb0c8c308b0381c67c85615ec4f85b2e736a1e80e4b1
-dist/2026-04-14/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=7d13b495206767a813f9011d317b5e447d23a8cde412a298b22624c2e907e98b
-dist/2026-04-14/clippy-beta-i686-pc-windows-gnu.tar.gz=d0de80d6858023f7192060c45f0bc20b594ecf980d352820939e7e3c07781c8c
-dist/2026-04-14/clippy-beta-i686-pc-windows-gnu.tar.xz=605dbe4cace24eaaefdded781d63e4c0fb7af4ad936b883348d3ab49e27f25fc
-dist/2026-04-14/clippy-beta-i686-pc-windows-msvc.tar.gz=6514ae9b9d0218b2699d7d14d8f1ccac841a28a61da6c2afd66584cbdfd8ffd4
-dist/2026-04-14/clippy-beta-i686-pc-windows-msvc.tar.xz=51793da4bde32228d9c0864cb3a321311e45d95f8a3dd0df9bbc92eea1301366
-dist/2026-04-14/clippy-beta-i686-unknown-linux-gnu.tar.gz=d8b9c4dce2d3d0b4e2aa3ff853d1fbeef272da7775588fead90d4375d1b16891
-dist/2026-04-14/clippy-beta-i686-unknown-linux-gnu.tar.xz=630996c9b6ecddaf72614f5455a94cd2a9a4421213e9984aaf0b55f1fd1c2ff2
-dist/2026-04-14/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=ad9645ffc7fdd42ed47f7ae975a2f3664b71776e1848e254f31303dd125403db
-dist/2026-04-14/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=195fc7cf769385dcc28a33ca0c529bd1a2a2f68b8e63e6b5a63257593eb85e94
-dist/2026-04-14/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=996ed71e21cf46a41151a7929cde94baf0be95886a30449ba4f037376d4b2e89
-dist/2026-04-14/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=07353278f796d7fb8195fddb9c6864f279817c9fc47797ec594658d44e02aa70
-dist/2026-04-14/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=7730841926bda3faebfdfc8b556cc6ab536bc9ea63b915f5c26fcb7b623a6651
-dist/2026-04-14/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=e7a7c37d7adcc0732b608efd73c080d322864992a3180bdb44b49375ec2fb6e3
-dist/2026-04-14/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=915aa0e233eefe2ed15eea8b1dccf23ea6540c3b8f917eb457bd4529a6ae4723
-dist/2026-04-14/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=eaea79157d9a9af8ff4ef361e3735a915dfccc508e8a3addf873666fe3191949
-dist/2026-04-14/clippy-beta-powerpc64-unknown-linux-musl.tar.gz=df714b07886cafe14c2a2fd095ab6cc0bf4d892f988549817947f4aa00b7ed13
-dist/2026-04-14/clippy-beta-powerpc64-unknown-linux-musl.tar.xz=66fef5a4671e3a86a12f749dcc36361b564a218f815f3c69f72baac8a89b11b2
-dist/2026-04-14/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=6f39657ad070bf33f683cef5e3e19521c8c0c58012f6bb36f30f728d497e4c19
-dist/2026-04-14/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=75f77ed2701ddf7b9c2c0fee5edd5e6e99b63b994522c132c5f4f1e01ce4328e
-dist/2026-04-14/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=6ea666b900910f65319e819948a9dd68340d73b399b45c903a8d712f6484746d
-dist/2026-04-14/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=6fc51ab9a2ec683106ce8064728ee89f795b0bbf2acbb1489ecaa094167b6e7a
-dist/2026-04-14/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=820ff2d0aeab4e2863af6e6369f8420d024c691714dd0a9d1f2c7c46615501ca
-dist/2026-04-14/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=3dd9a04d86dd975328b97137d5ac315f51736b7c72fe38c69fe9b306d28afb24
-dist/2026-04-14/clippy-beta-s390x-unknown-linux-gnu.tar.gz=08bee1014c5ef701574b1c03a41de7cedfa1ed01c5313526fb9d3c621559f957
-dist/2026-04-14/clippy-beta-s390x-unknown-linux-gnu.tar.xz=352b3f4c20087b3d331a7d758ffd0f7d37ae95c74c51a3adb497caed30b15e57
-dist/2026-04-14/clippy-beta-sparcv9-sun-solaris.tar.gz=967ab7ee344e265a24227ffc16da947499723f7108923d5a41eb1b6aec1565aa
-dist/2026-04-14/clippy-beta-sparcv9-sun-solaris.tar.xz=47304c45cf09fc4d79e1120b8800cd6f8660bb92dacf0a24dcf3d9488fecd978
-dist/2026-04-14/clippy-beta-x86_64-apple-darwin.tar.gz=dff3f80b3a32b592397e38694e698d6bf7b7e060b1d3c43474a8da706c6f1f14
-dist/2026-04-14/clippy-beta-x86_64-apple-darwin.tar.xz=2e5ec7a1f4e521712e73ee95fe8a3037319c4a1fb7f711786e342f09396cbbfc
-dist/2026-04-14/clippy-beta-x86_64-pc-solaris.tar.gz=d9b0a9f21f4f0f03e61870fca7aecd0fc77e2cda7307354eba8617c70b731628
-dist/2026-04-14/clippy-beta-x86_64-pc-solaris.tar.xz=c5b1ef728c858a5635e85e830900fb559f00bedf05f9e915b177dbceec02bb1d
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-gnu.tar.gz=6e8c4fb6de025286e48cfbd6733a4da6e0a00932754f88d909323db4dc61f657
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-gnu.tar.xz=b7d6838c62dd07d94adced58add5de7d2df5fdc5d208f8f6673e3f09f059880c
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-gnullvm.tar.gz=d56b5dec0a95f17e2c5582aa34f8de45202c115e7b985d54325e4a59843e24b3
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-gnullvm.tar.xz=137fd932794796421c95be2395ce79bd1dd1c4fb1b5c3f043c886ee99a113aef
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-msvc.tar.gz=2bd3935f7ad29706c964250dfc46e324dc23de4366976918c4f7fa67887cdc15
-dist/2026-04-14/clippy-beta-x86_64-pc-windows-msvc.tar.xz=b1180408bacb681fa5be86fdd26b13ef4b09e60add0058de3b499ffd9d97f85b
-dist/2026-04-14/clippy-beta-x86_64-unknown-freebsd.tar.gz=3377d3e117613e3375321905d0bb2b4dfd1661ebc21efea10c203459ddca11ff
-dist/2026-04-14/clippy-beta-x86_64-unknown-freebsd.tar.xz=2767076c74035ce97a2a3748df99bc35a908015a50a389317bdf3c6c563dcfb7
-dist/2026-04-14/clippy-beta-x86_64-unknown-illumos.tar.gz=8da6742093b92af4eb0ad2e92ba74c0135c7274960ecc2ac67cbb9dabec9ea90
-dist/2026-04-14/clippy-beta-x86_64-unknown-illumos.tar.xz=7893063f13ae3b3804da9a76c2ef86d2b1f850cc8f7a21ab1d0713090f315de9
-dist/2026-04-14/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=4b7e20a25c85c6387af23b07498c0305d78ffc9677f7f3f29fd6d688f49f6804
-dist/2026-04-14/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=822b901903aec0c08fa19816d852fc1df0bd38358af9114703529ad0d3207ed1
-dist/2026-04-14/clippy-beta-x86_64-unknown-linux-musl.tar.gz=a54f5f0b0bef55b30b69b581c3ec878431900b1aebd105ade1009b68d8fc59e7
-dist/2026-04-14/clippy-beta-x86_64-unknown-linux-musl.tar.xz=a4ac345d6574e5676fcce0819d56a22b5f7e26a0cb17e9c78ae84c3868c92bf2
-dist/2026-04-14/clippy-beta-x86_64-unknown-netbsd.tar.gz=53408e1388d3978741702cfc6678b925afdbb8a746368c3bf55d02822b059e85
-dist/2026-04-14/clippy-beta-x86_64-unknown-netbsd.tar.xz=40fa8d9d3c146e0e8cf4ac59a4720ebfc84aacd7986b5bac6655c05d062bf745
-dist/2026-04-14/rust-beta-aarch64-pc-windows-gnullvm.msi=27c559058f6946ee7903b218eaf2fcb920ac9f68431e1f087cd88ce9b376029e
-dist/2026-04-14/rust-beta-aarch64-pc-windows-msvc.msi=c2288c1aec98c255c786860c8920a11e9c1c66af7585df6c4a4046cb78782fde
-dist/2026-04-14/rust-beta-i686-pc-windows-gnu.msi=c2043bde4fbcef4a696b0e64fa590fa8c59ef0c3240c40050e9c7a8c3a0b5dbd
-dist/2026-04-14/rust-beta-i686-pc-windows-msvc.msi=a59ee54ba0f2b365c2e2d309d788fbb6c7bfe73bfcc02032f757b68dff6a8c9c
-dist/2026-04-14/rust-beta-x86_64-pc-windows-gnu.msi=99d55a913842ea31b92546f7a4e94d418fbef38edccfa8f81ad3b32dd0ae796d
-dist/2026-04-14/rust-beta-x86_64-pc-windows-gnullvm.msi=5960a87ccbc894c0dfb6150efea9d6ee02a4174764f37a45a4a25712b7ef8550
-dist/2026-04-14/rust-beta-x86_64-pc-windows-msvc.msi=69facef2e9e21de88dd680993242995f774ced5ebf2c89cca1ee225942777833
-dist/2026-04-14/rust-beta-aarch64-apple-darwin.pkg=0b5c82f82bd01814050add207c3aed0db18f9c8e42060859227d74cd1911c2c4
-dist/2026-04-14/rust-beta-x86_64-apple-darwin.pkg=be21af65a60626a081308b98de96c21187009c3aa457e918caf37f75d17d76b5
-dist/2026-04-14/rustc-beta-src.tar.gz=bd594961759ac8a575f2bdfb803a7e223fbccb1bbac5cf87fe541cee7c96decb
-dist/2026-04-14/rustc-beta-src.tar.xz=202f45516b821164e617244725fbf014742dd00664ed11525e81f7ad0882f3a5
-dist/2026-04-14/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4988e2b3c6ba0c18523b8bf980827d45d5d5d21cca50726a47c19203bc95e14f
-dist/2026-04-14/rustfmt-nightly-aarch64-apple-darwin.tar.xz=dacce0fa1c73685f979ee4cb5dd91824773f08408370ea74e719c171a044c8ed
-dist/2026-04-14/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=532847f2799ba84e4049c1a984886370cf42f3d599ab7df28d3d6e7eca8fcd27
-dist/2026-04-14/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=8abbd6f8803f214e8ed870de328822dac330051f5c0aafa5179c7eb48cb817fc
-dist/2026-04-14/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=e83b58941e1a885043024e7c1841b84facfd2285b960c895881b1f23655d74d0
-dist/2026-04-14/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=d2ff3bc238daa09ae041d88bf9a895ae4174f50757ebefadc50a90e5fe74098b
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=5a9a858ea2cbe6bfbee4eb48e819bc9e06732795883364105ff6187c551097cb
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=269ccbdb5fa3aaad14a43b0d987626a34aac6676e98082661419cbe341ec6bec
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fd4b5bc3ca04fff7324d3c9b478f4ea495d3f76237a4b605fc0611345188d049
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=7301952d391b41c022ab2c7a8ce6d336d7a08865cce07798aeb0ce122ac523dc
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.gz=c65d5e893228d1ebc675cfe3f748592b585ada56f6325071d3548473094ba50c
-dist/2026-04-14/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.xz=7e9a1f7d40f6eeba5b3ae18dd7038f3837e918df5e17ce13b60331bf5ea1b36b
-dist/2026-04-14/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=65a223192828d09cd5d74aa36ef96d725c828d5dfca405a053c8c7a8925a0b03
-dist/2026-04-14/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=eb8dd1fd0e686add3dbae3e3f7cf94a356c103e3449cace417148e88a8f30b23
-dist/2026-04-14/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7a3fff9db4c2141ac743ae2edfa5b5ab08de588c56c4eff1bad28c3068792924
-dist/2026-04-14/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=9fc87cce59f38e5397c7105ce2d48013b5e5e490c2fdfe610fa0278a297d3748
-dist/2026-04-14/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=3ca8a9fa7acde741ece6bd8e7f30717b6315b4fa804ef153fa1913c95ca28c9d
-dist/2026-04-14/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=9c8a21411f6fea0caf3532e62fe6d0e54f2ad2280b56b202491fc562cd81b558
-dist/2026-04-14/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=9fda7a3ce38f7e6ebaea9a5c0efb3c75079bfb202a8b03570e0a49a5b4fbf442
-dist/2026-04-14/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=7c1853f533eef11a23d4c4618885528f6e22c0a48e60de0f552df90cfb9a1488
-dist/2026-04-14/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1f1907befe3fd07d33ad69afaa06358003074b4d8242e09a2b28185c676d9438
-dist/2026-04-14/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=829e2618dd59669c2ba4ad56b58535c52a83eb49ec44a36c6ade93411aec244e
-dist/2026-04-14/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=e7a92c0c1bb0de3a05b61c7b1674170f9628d7e941f63e44a98e0e10d49cb427
-dist/2026-04-14/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=78c9c255cefc103e68f71212522ef8aed9ced49890b173bca8d08e74e6fcd3c7
-dist/2026-04-14/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=033e48f2213258d4836a67b4e03882599272e227870d588d597455858fffd4d0
-dist/2026-04-14/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=ece1e2a2375d4da3931ad65da0ce15dd8a21d224fd1c7d663e6575c5eefdb6f5
-dist/2026-04-14/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=c63aced5a2243c8563021ccda76ad493120a9fc65b38e044d43c48a002d0181d
-dist/2026-04-14/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=f277ff7ed2574b7b348f2f52a83988035a6e52a949806ac70e8ad082ad1412fb
-dist/2026-04-14/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=0050277d6fda982c243746a09b0aba02735bbb940864f9d910e54216665ed676
-dist/2026-04-14/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=f0702c9e3a203dcb35d2b68f2bbecfccd9bc9c3f558cc9265f20dbd9e1120825
-dist/2026-04-14/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=d401f1d7ab50200ce67dc4cafe0691197183d7d57115e2838e14125be00c64e4
-dist/2026-04-14/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=3ebabe3f3f5d8c70382d0bd25d6391eb7f903189b0ca16ff7377cb88e43c179a
-dist/2026-04-14/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.gz=65fe9a35de40d66fc4091e8ebb887395e5df510cae883b396ec11219961e5488
-dist/2026-04-14/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.xz=929456f8a5ef40256242b0ebf0600c5bd41434e6f1bb538d08fd89ca1c58c175
-dist/2026-04-14/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=edc55ab2314c81295776e2348672c9a5ff1c29161fe7379fc937479c2e36df98
-dist/2026-04-14/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=212a4ac158b0fd2fad5557e893fd1b0d97613f0695a3aee3133e3274cf646920
-dist/2026-04-14/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=1f190928db5257cd20760a898b46463693aeb40ad5d2488c05ffe2e8221e4e18
-dist/2026-04-14/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=53d26b847383e643ee9cdc331a6b7a29c7986b91a32f1580f0f640e644f175fb
-dist/2026-04-14/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=eca26358c02964a2e9691a2aa83e66150e4f96364e418dedfe3466439a82d4eb
-dist/2026-04-14/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=bc37420bde24aed17be23ccd56c151fe66b48e6dc3dd705a6c3ffc6fb4276b37
-dist/2026-04-14/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=133f46731c8f52ec0b5ed9683241a7a833bfa7477a072ae3a9e312bce26ec12e
-dist/2026-04-14/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=9995837171346bcdfdda9718074f8374df276753eecd4031b586123af0ddfaf3
-dist/2026-04-14/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=ef1f83580055a3cc717fed9af5240941c1477fe33fe1dfd9c3d049cc37180185
-dist/2026-04-14/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=587af349e6c6cb0e25f23b0a2c087caf4ca413e731bfffe00dcadd77ea8c2212
-dist/2026-04-14/rustfmt-nightly-x86_64-apple-darwin.tar.gz=c10f72edd02d6792f706f769d27cf162abf9dc88eda0ed1fc9205bee14575177
-dist/2026-04-14/rustfmt-nightly-x86_64-apple-darwin.tar.xz=78ae63443d8edd4d4f5eba8d9611f2dde46936a1563be7128af82e9b5d4f730f
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-solaris.tar.gz=0ac6f569443662279cd071353f01d9b6b41a2d6610971f35a4ecebe34b7d9c52
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-solaris.tar.xz=3c6ccc0e763adca27b8faae4d8a8a851006d3fd7ef0671edc2573a90d3461757
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=12e61bd14af8a8acfeda678e7cb348f6537534fccea8b6866ab91f4621a0aae5
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=1b995011d7e89b730d6b77a27c46596788a188a2571dcb70ed28fa14a2052cec
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=bad8817ff2785961ec1bb79357657963ddbc1f3a8856aef93d8cfc459250e462
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=27a61211a0ce149bb502909fd828f99a3e9128f66c05194443f6e1e9b2e04586
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=885f882e2a5e66c05e348f3617ba90399da734e21e76b6933eee4f23a83ba9d2
-dist/2026-04-14/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=afbbc1dd8cf74d92378287ab44e6e1af4f532894767dab00eba428228f3c6c66
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=b928d87957ccdbedab31b1b6fa549f5c2958e9a811792b9c862469e3d8435fb8
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=4c71a9a131e2a97b6bba902e97da1c6e953b435f6e322ea9508ee1f060293cc2
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=d12933f927b321fb4c579ec894e4372d14b33df9ac772df86824a1019925e042
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=91229ad6671f25d347453a49ef1b25971fc200985d7f4862457310e61deb1ada
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=71acc8c0c52483725dcce94f5098c5a3d042f7faf478fcda60de2e809b2d642a
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=333fc4731da2c724e70f9e60ece6ad932fd5eda912aa188149275dda1997c0b9
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=36eb2999e9d542f540b5ed9c9b7dfe62db95c43f168752f32efaa4f874a085c5
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=51e35060d731ef9b5917315915621a8b0e924d9c3dd8f346bfd32e20d17c4711
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=8cd2a11a20148e96b8b030329d0830b3ee168d8c71d31eae4893d77a5e0fae6d
-dist/2026-04-14/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1f2da033ccebd5e1f055019e9e6d0f6d3ce2fd57e46a08ff6a3357572050a234
-dist/2026-04-14/rustc-nightly-aarch64-apple-darwin.tar.gz=13a70dbb3aaf2a5296367832e92975d4a6636d944275de5b9cc1d4592a9b1805
-dist/2026-04-14/rustc-nightly-aarch64-apple-darwin.tar.xz=78f8b383c22eef6e27f9e2f2255af63eed306a96adfc851a305a6a33e11d1f2a
-dist/2026-04-14/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=772b59c215cb8dec79bd3a537681c8b37051390e52d75986db8af5843c2f7341
-dist/2026-04-14/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=d29721ff7624cd3df53ec69f78c9d8f75e24455b7dd2c0dd3dd1ca53f66b71e2
-dist/2026-04-14/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=4f9cf47d1560dc516b63913e4e89c17d1b89b5c8cfa677ecd8fa538bfc4afe12
-dist/2026-04-14/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=67fa760544169a924211457b5150f4bcef0b2e3deb717c67677b346edaad3f4e
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=f51048b6622957f10a314a09889c8749234c8456b5c826958069a6856e0166fe
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=2c22b92466453884f6afed1f6f733c982492f247e03740892d253930c66b6d45
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=d478bb6dc0af51fd4e7e007a825e09d26fdefe8d2eff251e8a055e67dc82830a
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=335947b16552795ec3c5f525b1bcb2b82c54bd0726146d3d8685f7b0202e8b4e
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-ohos.tar.gz=3ac6ea0c484ca7c4b020a2b333cefdd01830fa1ba2d3fa8efbd911ca810bfa3c
-dist/2026-04-14/rustc-nightly-aarch64-unknown-linux-ohos.tar.xz=4125e5b0940f0859a3778b0cb441a8504c8276064e1b7413c174e5cecab05795
-dist/2026-04-14/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e764a83c5818b6ec8c06a448bcba7d89e02b071a3e8666ddef61943e1b3c9952
-dist/2026-04-14/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=c2b69576d1fc1bf8e2803bbada5766af3dd388912f9609125d514e28d7898b09
-dist/2026-04-14/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=909e94363fdc0f04e0e2fa43afce22f85626a89d6305f0e578d0c45ab1b41e2f
-dist/2026-04-14/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=75581145a7bcd75e628bbb29f833b4faab31647bc2a846ac5a5403047974a594
-dist/2026-04-14/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=e0fb27cd6686bb340754ce148eb99ea07d1b0a0cacdb47d555979159d3238bf3
-dist/2026-04-14/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=5f2dd01b77130d610ea5f0c964f8d90a556619a9ac8be27ca194ab3fb69548f0
-dist/2026-04-14/rustc-nightly-i686-pc-windows-gnu.tar.gz=a75f7a65711135059bbfa680d0e1008accdc01bedaa281de20f4a6243a8a9702
-dist/2026-04-14/rustc-nightly-i686-pc-windows-gnu.tar.xz=be1bcad0c88c3e1b513d316cb944d2d292dbc76fbf9e5f65e7932d45187ef6b0
-dist/2026-04-14/rustc-nightly-i686-pc-windows-msvc.tar.gz=a910ea7aba73b75b330b4fafbf519c708659f85e6cc76b2701f12b93619fb7d8
-dist/2026-04-14/rustc-nightly-i686-pc-windows-msvc.tar.xz=693e043882ebc1ebea21d65bfd1babc96bfe80a0d43f8ae2b9a70a9070683b33
-dist/2026-04-14/rustc-nightly-i686-unknown-linux-gnu.tar.gz=c1cd472c333178e1566687758a3e8026e6c686ec825c48730eb99a5133645fd4
-dist/2026-04-14/rustc-nightly-i686-unknown-linux-gnu.tar.xz=c30771464bbbcfa1ce7843644c461222e8c0ddd41a339af857d71e64929aca36
-dist/2026-04-14/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=716ea63ccbf0578e96aa70909a4855f68c577da5c08874a10750e217df480966
-dist/2026-04-14/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=f8d499e4777cbd664e12d475caa50728464ee3f430d1ce01ed13b6d23534ff70
-dist/2026-04-14/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=fca3a60606670897286d5ba99629051d79fb5f8a58c775eacd630e22f2f6c0c0
-dist/2026-04-14/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=29c2d67bf1cb3200821dbf50125b478b131a6a5c122c543770897716a5b5ba72
-dist/2026-04-14/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=dd15b14de18d033d47ca8329b61f1908f34de0255dfce43f5e215ae5274b1bdf
-dist/2026-04-14/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=3501229024c2474d887a8b0c6d7a06454209c472cd70884e6f90bd507d62e3af
-dist/2026-04-14/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=799a80733eb84738fe79719177ffb17d81382369159393fb8c5b03f88650c406
-dist/2026-04-14/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=6f3b41f9d936e70f1a2e617068a999f02c051f1e6211481c0630c9bbdf6e7f25
-dist/2026-04-14/rustc-nightly-powerpc64-unknown-linux-musl.tar.gz=1cc73dd3187a70c20d8e790fa56a2d6ecb278e4547fdf77e562fa22d69e2177a
-dist/2026-04-14/rustc-nightly-powerpc64-unknown-linux-musl.tar.xz=4da7e7cc44d8370c911969f8e35454f23a6284029ca6ebf81ab6ff6c100072f8
-dist/2026-04-14/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=ef97408edbc38ab58f8e86261e53f60196790b186567bdff3924ad959d755976
-dist/2026-04-14/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d3a3cb98454f10d0a27009a4a3bcc38d164a81ab592dbc722381f62654d309c7
-dist/2026-04-14/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=d8f15c170e7a8bc856e28012eca5c45686f194f0c21e45de9008cf92170646d2
-dist/2026-04-14/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=4e616a529c502fb4b445eb8d55cac1247c037a2e9800b614187a4a86936eb9b2
-dist/2026-04-14/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5162ebc9cfc3ff76226c0ed3d4a718939be4a74fca1aa5288e0dcddaab7fa7d3
-dist/2026-04-14/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=82879c0c9b55855204f3d6869aae565a5553b9cc281a97d427ce81101f1658ae
-dist/2026-04-14/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=cc40c7d8d692719b7f3e5a8dd85272d42af4ce3f33528fa945b335d0639adeff
-dist/2026-04-14/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cd36435e1c3a8f888ee7fc531f5efc0e5a1d375b9df8e64efe977ae8a6f7b2b0
-dist/2026-04-14/rustc-nightly-sparcv9-sun-solaris.tar.gz=ddee30c3e11f137cc02679949c5e8b808d50f70090cf074d0eecbdeb3b9610e7
-dist/2026-04-14/rustc-nightly-sparcv9-sun-solaris.tar.xz=21fdb743e692f55bd0a66fb131cc5906f13adb023e51e1a29b385cde3a5932f5
-dist/2026-04-14/rustc-nightly-x86_64-apple-darwin.tar.gz=e391518e93bbc18fcf3e46360afe00ad1ea9f6798aec64124818a152715f922c
-dist/2026-04-14/rustc-nightly-x86_64-apple-darwin.tar.xz=14e16b07cf7c1d001568085eda8112a8a11c1736518eb743205f6b049b75b39f
-dist/2026-04-14/rustc-nightly-x86_64-pc-solaris.tar.gz=fa1ba81680171e30652b18923a67d9875500ec5a4a5ca2b9d58bfa0a6a605091
-dist/2026-04-14/rustc-nightly-x86_64-pc-solaris.tar.xz=8133fe568daca53cfc8b7d7dc5ff4451e82bbb68ed315c678cc00335323550fb
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=8011fcdcc2c893e6035fc57b1dd364ecdd8cd7e6a0aa4e283d12466c0e7c4dc6
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=5a6cefdf79ed1cd62ab6f9f72c2cba9096c0f4ee22639fd64cdf97b5370dd0d0
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=801f914fcd1b4b322b3aa5951b81b53a207ceee4ba097d8224c756de115643e5
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=3532130975072968bf35fdce94f98115de2d2a0cd5e25aed9c29162795f3a297
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=500703a85e38b7a4ce00e36655e931558ef23db4b32fd5c7bc676676c84c4faa
-dist/2026-04-14/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=2bd9987d711b7e1206398b7a9d7d4352b5c917259728f1de223d57e61b5451f2
-dist/2026-04-14/rustc-nightly-x86_64-unknown-freebsd.tar.gz=ad67954b068b5e4c0390344b7821141a5586958ba40c93ba50b59f0f16579850
-dist/2026-04-14/rustc-nightly-x86_64-unknown-freebsd.tar.xz=2dc93c054383ad661700450419c0b634cb7f07d4785db1bf8282b418c30ced35
-dist/2026-04-14/rustc-nightly-x86_64-unknown-illumos.tar.gz=cdd1e60cdec961885d8257e326e9aa4fcad01e254de05d3d06c72f5ae8a6c968
-dist/2026-04-14/rustc-nightly-x86_64-unknown-illumos.tar.xz=fed43cb199d09a8bc21eff285fae0307fba8b75e9f94173d4016eee53e51c59b
-dist/2026-04-14/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=75ff840114825b1d828c478d77db5617f17329e8309868ba94cdfd994172ae52
-dist/2026-04-14/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=a54f0205c6b7068f54e424a5b923834e8222d28ddcfa7da677ce268e88ff2c52
-dist/2026-04-14/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=43071bdad63347cf9deaa0b860ad9bc086323fa0cb4c5519f2246d39180586c2
-dist/2026-04-14/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=d8ed67a9d66e9536827df84157770ff04fac04283afd4f2eff791cdf6a83a282
-dist/2026-04-14/rustc-nightly-x86_64-unknown-netbsd.tar.gz=8c16b7deaeacd2a2631a7ecc7338d47ac4bdecfa52f71ac70d7b93513fb0e2ed
-dist/2026-04-14/rustc-nightly-x86_64-unknown-netbsd.tar.xz=6c20270030613b1f2c98b33dd8310929558e6f58048e21f7a36423e50de0fc98
-dist/2026-04-14/rust-nightly-aarch64-pc-windows-gnullvm.msi=f78cc56f163c90311b025181a8e1db9dda59d58b3556968c0cdf3dbb4507097f
-dist/2026-04-14/rust-nightly-aarch64-pc-windows-msvc.msi=95550ae060542483ad774574b2fc8cb79a5f2f70a3b06bb82cbf5a40bc871757
-dist/2026-04-14/rust-nightly-i686-pc-windows-gnu.msi=97efc785c12cb0fdb6906456e4726d0eb2adbf85a4dacb2daa61f6a6319b036b
-dist/2026-04-14/rust-nightly-i686-pc-windows-msvc.msi=26a28eac06d0aa20aa226747ad8e1629552c2550b572a8c97a85cc2d1d8ea1db
-dist/2026-04-14/rust-nightly-x86_64-pc-windows-gnu.msi=01e35ac3cbfd26ccdffe93e9d2eea55381cc9b6faff8d65326bece13527fbbc9
-dist/2026-04-14/rust-nightly-x86_64-pc-windows-gnullvm.msi=8d0454333d8b187eaa6fd3a2275948999a2208f2b6a88706c2ace747b112a85f
-dist/2026-04-14/rust-nightly-x86_64-pc-windows-msvc.msi=72b999b71ccbbd63f0603640a0e6152d2ba2d285bf0879e5dab8f5576e5aeb9a
-dist/2026-04-14/rust-nightly-aarch64-apple-darwin.pkg=09cf7f8fb13d38435739546cf11e690fab6011a8aae6cb23661c839f7e1a5318
-dist/2026-04-14/rust-nightly-x86_64-apple-darwin.pkg=ad30ba52b79c11e3dc7e00f50fea9d411d37d52b44f1e6cc6fa320a81bfa8ea3
-dist/2026-04-14/rustc-nightly-src.tar.gz=57aa9382fbcf1cce748da037f94062404652d9f48514567a973322304e8c6975
-dist/2026-04-14/rustc-nightly-src.tar.xz=5ab46adda987bcc2bdf2335088c5c4114b80d8bdd657803ddb9b775e67743e67
+dist/2026-05-31/rustc-beta-aarch64-apple-darwin.tar.gz=34f24131e52a4532854ec59757921f57319d0a24cd567a949fe3ebfef28ff510
+dist/2026-05-31/rustc-beta-aarch64-apple-darwin.tar.xz=6926e56a75676d509c668ff80d8fbc96e15d4cfbbc7fd3ad9d55b731f4032c49
+dist/2026-05-31/rustc-beta-aarch64-pc-windows-gnullvm.tar.gz=341a7131f6f24c06645c5cc5941885c6f9494e7660e945a5822bf55b0d1c2ee2
+dist/2026-05-31/rustc-beta-aarch64-pc-windows-gnullvm.tar.xz=e3df15b81702e760935c6496dc3b31eb86c876ec8a20590d3517000d71c62831
+dist/2026-05-31/rustc-beta-aarch64-pc-windows-msvc.tar.gz=6876f60d0b1c53f1ee72655483f57280e41b7c3209857448ef00da66fa985d2c
+dist/2026-05-31/rustc-beta-aarch64-pc-windows-msvc.tar.xz=6fdbac65a3798818278ab722587367176c28fc4085186d85ec1f521b90e75a8f
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=2b28557ef7433d0fd307eb2da64fa2e56a0fa4704698e66b219b003ebf6997af
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=48bfaa33fd3382c5cfd1b06bea061b1e7594528fb06e1ff522af7d16ce41ebb2
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-musl.tar.gz=1bcaf05d6a21d2fa98dcbcd51bf0799f7a6a115fadca29133f9f10fb498513fb
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-musl.tar.xz=0198b65d94ca7a18000f4f759efff39080b0f02d95d5ccea521c5d2f2ac85b90
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-ohos.tar.gz=053f3c069b5b1cf482d4febeab6c71875b32f227887a4b1176c103564bc918fa
+dist/2026-05-31/rustc-beta-aarch64-unknown-linux-ohos.tar.xz=f0e7aa55795fe7706177c553b7071991d3804d9e3c48e4dd9e8fa09aa6caa137
+dist/2026-05-31/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=76cb17c7125cae2b45ac5205a307ef69a43c3d1a7a0e5895df6f68f00cba190b
+dist/2026-05-31/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=4ae18f7a4bf12b00ffb92eb7a7242c02e2137e3a9843bba0dc00093d4e0c7db3
+dist/2026-05-31/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=474439ee8b363b2a84e1af1f71b501f4b06d1f86c0a92ffd1f97d34715cc8b3e
+dist/2026-05-31/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e3e4fceb93b25230361b29ed86f8ee241394827c36eaf4f50650bafac7d81684
+dist/2026-05-31/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=7a66c4ee6c4e617fe9df2162d38a60bda5750793c17be23ad65eac620d15e489
+dist/2026-05-31/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=961d89af06130ccd32600bb1b0def20d0047767dac3c53ac5e2f92a4af57171e
+dist/2026-05-31/rustc-beta-i686-pc-windows-gnu.tar.gz=e23f9ca62e0c9e23acd9b184de348f6d9555bfe9756dc68a8eae5d69f1771a19
+dist/2026-05-31/rustc-beta-i686-pc-windows-gnu.tar.xz=38439a3c87744fd0c68c8558ad3bebf280985a5147b95d02b3d6f3bed98cb820
+dist/2026-05-31/rustc-beta-i686-pc-windows-msvc.tar.gz=18eacda07c4f5c31429871eef3ddd00bbce67171b8fd528d82e8f2a9961757c2
+dist/2026-05-31/rustc-beta-i686-pc-windows-msvc.tar.xz=783293ec4f38c0d3e9f08320047df95c5da6d1447a4a31ae253f6f2b75c28211
+dist/2026-05-31/rustc-beta-i686-unknown-linux-gnu.tar.gz=1ad6204effe8cf74032aaef59b9132fc91a9a0b7e9cb67e262c2b81aa20853b5
+dist/2026-05-31/rustc-beta-i686-unknown-linux-gnu.tar.xz=a71499a05ff4dc01c036d93d122eb144611f3cca6cdd25e4610abf8ba94febc7
+dist/2026-05-31/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=581f157002aa5d4be653a6e083db9b010f6f0993aeeedb5a2eb132f1bab2031a
+dist/2026-05-31/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=49c5b0aa877458b5aacfa85a4501992c9998748d808ebeb4ffcd7368ced97b70
+dist/2026-05-31/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=4fafe68738ff6e16a5de64406b961fc8faf541a08faf80d0bff8370f8c2e1d20
+dist/2026-05-31/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=f945962368279584106eb7a2847334824c035c9dab9a31044f484b5e4e04c502
+dist/2026-05-31/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=371773cfdc02c3cf8f40db27765590b5fbfd741b11476ad6aa49935869404ead
+dist/2026-05-31/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=d68d372479e779cb63a3738b8c1ae0b5299fcac56e83c3c4ef16279dee34b5a6
+dist/2026-05-31/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=1211dfef6caaf023c5952fd43cf87e7f8242426c914cdafbdd5b1139f02919bc
+dist/2026-05-31/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=532a4dadc849f9cb86cacd7fa2387c9ec783a3a06169d822bb74f7154acfd683
+dist/2026-05-31/rustc-beta-powerpc64-unknown-linux-musl.tar.gz=3d43c0602d6290adef323f6ffe1c4604f58a32a8764f007d9601c4d37c18dac9
+dist/2026-05-31/rustc-beta-powerpc64-unknown-linux-musl.tar.xz=94e389e5627030707b86a39d872a9fde191e802b644a180f3ee5cde3ac8bbd2a
+dist/2026-05-31/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=a91480097de9fb4b36449f5a0dbbb696a69a26e5443d7689f9cf58cede0d8814
+dist/2026-05-31/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=c9227a2b7a81829ab0786c857dcb85f7d1ceb0f42579be825b0e6c5e1bd96999
+dist/2026-05-31/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=96fda34e1b2c0f83a1f2f0a69633f05c6af669298555b652961645049a827829
+dist/2026-05-31/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=329b1e9366c79d1e8ebaeabd2a3b8a630b607d9dd3f497ff6eea8e1ebb5a7534
+dist/2026-05-31/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=546e44e9d89b05229bf0718b3dd63d42f1bb53f26068dcd67a9eb2d64b679f12
+dist/2026-05-31/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=93d32baaf69d55ab684d5bad63e80a1ef836669c7bc868277f084c32aa5feb9a
+dist/2026-05-31/rustc-beta-s390x-unknown-linux-gnu.tar.gz=41543dbe54924e1da679547f8c57191d4d87f98fc72222b7090804482f31b4b5
+dist/2026-05-31/rustc-beta-s390x-unknown-linux-gnu.tar.xz=3d27774a545afa047876d7709a064e13f5e72feab093e8cd9e140b2573b6445a
+dist/2026-05-31/rustc-beta-sparcv9-sun-solaris.tar.gz=d0f9f5ecf9024dda2f3873375354f5bf4263adaaf9ef335c47e391e69e03ed5c
+dist/2026-05-31/rustc-beta-sparcv9-sun-solaris.tar.xz=027ad46bb5b849a836e97a23ef17f2caac2763e8a958b72609bb7986a57a44f1
+dist/2026-05-31/rustc-beta-x86_64-apple-darwin.tar.gz=6dbe69125e221dbe6c83617f3b9d319a2deaa4fe3a00d27898e84c7988fdca41
+dist/2026-05-31/rustc-beta-x86_64-apple-darwin.tar.xz=ac060156191336af7a6a1e0d4fd4a49c095442981149f36543b4accf55f54cf3
+dist/2026-05-31/rustc-beta-x86_64-pc-solaris.tar.gz=dd56565609d3995e63024e4052094179f905502837a4ec8b8cdfce17694a673e
+dist/2026-05-31/rustc-beta-x86_64-pc-solaris.tar.xz=e41810bf9bcfdb4fac0fea0b07820ae9b2d73b2b6751bda97f59a0ee61bdde62
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6398a55ff7e14b390342fce1d8aba0c08e7ad6f5db62a60b184f8a00d9e31dca
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-gnu.tar.xz=54453ee4b6a20e817fad213afb4f03ae22c3c028fb505837f7e9bc38c7247e98
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-gnullvm.tar.gz=f6490dafe8fc300aa1d5860b5ca5c23cb5b6365f5d0c93c2f94e4a3e68323ee1
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-gnullvm.tar.xz=9eba0cfd987e9e0d302fdfc1a8e346e2dbf181551b995f6427b0eae953eede0e
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-msvc.tar.gz=305f5cda5e0270149b506df694f5edacaf6c231d0e130235d9ea7df475fee280
+dist/2026-05-31/rustc-beta-x86_64-pc-windows-msvc.tar.xz=21a824d4fb0388a1ad4cabc34624a51a54c4649fba18cd3d971d371980cd6462
+dist/2026-05-31/rustc-beta-x86_64-unknown-freebsd.tar.gz=b66546833e986bb7e5f8fa0be20004896bfdc592d6d5f2bb597aea3814e2f544
+dist/2026-05-31/rustc-beta-x86_64-unknown-freebsd.tar.xz=0dccc47a20e0a19542991f09413c8be3340bb763b866861f84450d48e14cd4f3
+dist/2026-05-31/rustc-beta-x86_64-unknown-illumos.tar.gz=d7beec032683ac638d5e8781200dbd2f667dc59496241fbc411b7ebea9281336
+dist/2026-05-31/rustc-beta-x86_64-unknown-illumos.tar.xz=9286ff0ca05c307ca9871cbb9dc8101100338124a8af08f3bcaf38bebc60e018
+dist/2026-05-31/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=6ba6876645586ae2730eb87d29f057a80760e30bf79074e20c0cdb53b98d60ca
+dist/2026-05-31/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=660b1974618b830ea396379b8adc3ce77fc8632510bbd60caddffb0b0173d130
+dist/2026-05-31/rustc-beta-x86_64-unknown-linux-musl.tar.gz=54497899f700e39dcd9f9654dce5d7f11bde6e2326cb42e42a9ff522047cd88e
+dist/2026-05-31/rustc-beta-x86_64-unknown-linux-musl.tar.xz=03f66fde2672e7317df403b687390197e76e620a57c569a28dccbcc3b4d48985
+dist/2026-05-31/rustc-beta-x86_64-unknown-netbsd.tar.gz=9d6341d1d2fba2b5da9ea7c7b1a6efb7cf80055654e09bcfd361bdc75c12e3f2
+dist/2026-05-31/rustc-beta-x86_64-unknown-netbsd.tar.xz=784f4f29cc0f621726841742b09101496142a0013d1836e3b7f027cf5e79d4a1
+dist/2026-05-31/rust-std-beta-aarch64-apple-darwin.tar.gz=6277ea79b49e886debd4cc9601ff69ad5eced57417b0f3a7d0108cd0e6fb9c03
+dist/2026-05-31/rust-std-beta-aarch64-apple-darwin.tar.xz=994b401e71fead4fb2eafe10a4ea5f81966c4320301524f9d2dd60e3f30aea51
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios.tar.gz=6f77194e77932c54e8bec920544481e83ea84b5e4180a2ab3332c5162b1f43a9
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios.tar.xz=a3d369824b8837a6deaac735a989110a8a94803f90d8bc0d8b410530a3fd4b59
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=86d6fee9f0042a732e0da47ce288797fbbc06087d8ef23d58d78e781da35d7bb
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=624b2028d019bba1d13f0ff26961775c9ba8ec7a7f26b61878aa40cf7613ebeb
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios-sim.tar.gz=6ea722e2c1e7adf11b29db66c016778442213818f3dd86679bd1d05e85cae589
+dist/2026-05-31/rust-std-beta-aarch64-apple-ios-sim.tar.xz=8f3329daa8743896f8d33633adf9e3799c5432a25ddeaed1f57ac4f9081834d8
+dist/2026-05-31/rust-std-beta-aarch64-apple-tvos.tar.gz=b3a762d804fbeeb2f68d95a736faf460d251c6d1622bbd00588cc58f4385478b
+dist/2026-05-31/rust-std-beta-aarch64-apple-tvos.tar.xz=135313b93c57cc7ee2a04387da01ce9b2610c64bf1d93c2aa27ea650c5f6ec32
+dist/2026-05-31/rust-std-beta-aarch64-apple-tvos-sim.tar.gz=78991aad24b18b476a92b42ec3c158693ccea9699d91991a296b85a046c454ac
+dist/2026-05-31/rust-std-beta-aarch64-apple-tvos-sim.tar.xz=f107dedc09aee14d06f2da844a4e1f6acb88f54721f19386dac6833b5d7a86b6
+dist/2026-05-31/rust-std-beta-aarch64-apple-visionos.tar.gz=cd6dee7e0f6fdd7a41b88604dd52b9d03903e7b8a08826cde7d08e75a430e159
+dist/2026-05-31/rust-std-beta-aarch64-apple-visionos.tar.xz=8a317391a40cc0b062b2cfc9059c782c0b4381d3fba3220e879afd23ac9b6fd5
+dist/2026-05-31/rust-std-beta-aarch64-apple-visionos-sim.tar.gz=ae876e432df02b397605f77d2fc79ecd1f3b296315e3caecbc97561bfb9ac144
+dist/2026-05-31/rust-std-beta-aarch64-apple-visionos-sim.tar.xz=cd4a27a1924f75e98a3ca0b62962bc4581c5998fc30f68b056e21ebacc67c3a1
+dist/2026-05-31/rust-std-beta-aarch64-apple-watchos.tar.gz=3e637f5bfe95caecf91a93b1df01d1330772f8f791b61508c86dadded086ab50
+dist/2026-05-31/rust-std-beta-aarch64-apple-watchos.tar.xz=17cc0d4434c763b63bf5868f5e56a7d595d0872e75e1f49fcd3f572ddc309e69
+dist/2026-05-31/rust-std-beta-aarch64-apple-watchos-sim.tar.gz=3424b12aa735a6add668d89c033cad7c8222a08c56ebe9111b2db29f1e53f28a
+dist/2026-05-31/rust-std-beta-aarch64-apple-watchos-sim.tar.xz=fbbd0539393fe1f031a2aa48e68fde2a4f3f68de94196c81c0b140741682cd80
+dist/2026-05-31/rust-std-beta-aarch64-linux-android.tar.gz=67b5183097b7a514743e6ef23a476749af76bd5094eac023d9cf428f61e83730
+dist/2026-05-31/rust-std-beta-aarch64-linux-android.tar.xz=9654ed32908883d83bdaaca6350a88e5e69a4e95f0165723c8c2e9e08cde6cf2
+dist/2026-05-31/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=6a847b41e08219b50469aedba2594a0a66b3c35083f261e9ccbee51bbaef140d
+dist/2026-05-31/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=bc59bf7d1b2cb0460828fbb115f8f54b334b26e353ed2bfdbf83fbc1184af486
+dist/2026-05-31/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0e7706e33b4b38abc1daf5fbbd19f93b385ba9d83ec6dc1485e07c9152574dc4
+dist/2026-05-31/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ee252e3fcda22d824fd4eb9f8beca05ed630e45a8e9d233be4be0b25079ac51f
+dist/2026-05-31/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=2238924f0dd1070f5c140028fbbe5d9798e0ae15016ec9a923aa676c826e08dc
+dist/2026-05-31/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=144270b13ee0b9158384ec423b1bb49fc87a2309f5dac015a79591c5b743c19f
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=d43084c16b7332fea665cfcbecff3818bdddcdec429ed4546e151aa8bf2ab4b7
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=46edeb803e1bc7d08046b979aaae648fc69e1459d74aa62ff8fd5639dee1dbf7
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=3c595fab996d75d6eb3f804910a57557438aaa63ea865c3f4b4bbeebc4655ede
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=8ecee597bdb0389e359ca41048819f2568ee5db94509242d9aa92cd0bc2f6016
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=05e80e252ba2339e61082fbf7072d3d2842d292dad3351e25f927e0e54f15ba8
+dist/2026-05-31/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=ea0ca1f0e4717f92666643a5572879aa12b32cc35d145cfca4795411553206f7
+dist/2026-05-31/rust-std-beta-aarch64-unknown-none.tar.gz=202c8b8ff1e9dd60eb53be7db155e35e082fd43034db10f48735edd44bb40856
+dist/2026-05-31/rust-std-beta-aarch64-unknown-none.tar.xz=b4275504cd0c8fa6ee3ac45f33ffd215c70e8db230a3d3461a269f752d1a1121
+dist/2026-05-31/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=a48a9810a1c3ba52536bd22a3d82dcd12faa6296d890c6a1c128231638817acc
+dist/2026-05-31/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=499ddbb6cff60c0b81dcacae1f25eb080e6d7b7fd00ce360cf2bf99f3113f20d
+dist/2026-05-31/rust-std-beta-aarch64-unknown-uefi.tar.gz=3d809d88548bd3d7c89dad1fe071455570cc10e4b390b8b722606755c093ac27
+dist/2026-05-31/rust-std-beta-aarch64-unknown-uefi.tar.xz=c990843580fcda9a9925bd29cd28302e0f5362fedf5b8f5be1fdc4bf68be5da5
+dist/2026-05-31/rust-std-beta-arm-linux-androideabi.tar.gz=01157bfac833961057b1e384b126c84eaade8ee4083af16f6921abd0a908bb68
+dist/2026-05-31/rust-std-beta-arm-linux-androideabi.tar.xz=c00a8f228e4e96c158a23dcf6ce4e8c8d206b29603473c8a14201549a61c0181
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=8c7277ae77501921f6704eec131c9b5a8c230f177fc627dcdc30bdfaae7c5905
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=32dbb018e7924a87d1b98e1f9033a0dff0405cb1ef1fd8b0ef98012ae5baa008
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=d09f2980e154a8fd9903581d5b9899c894a9563796a4fa86899ddeb66863b000
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=511235d1285a42c98c72c2d63545aefdfdc2ca1bd6ebc1908fcd8550230abdc6
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=782a0684b7fee0d44f97cc754b2780ac28582011b4554fa4dc14761be1ec6033
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0337204b3d28e95763657701b04613748e9c2e287e84c557fd94b131a31f88b3
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=29f920a5a449d7022ed2f0df1405e806ed13d1fb9ab409f0bea22c3449c0c038
+dist/2026-05-31/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=04536c647ac4dd045ad0fcd765d8232fbc2f34ade54b785e5138d8cf0864de6b
+dist/2026-05-31/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=50d5ab9266bafedde5f0570b1fd1507a214d33a90ff27b5d13ed89c7c794c6aa
+dist/2026-05-31/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=71b22f58c8610cc93b5aeb0a9b3d63067c94579d5ed9838a095d96059d68fd72
+dist/2026-05-31/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=2610d7fd2fc002f48e5c6e9308dfdeb1dbc54ebb2887f1d9bfd674f41dc41081
+dist/2026-05-31/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=7029d90f70a8c200b5588762a4c5b6b65b0a9e8ffe602487250db987fdb7a530
+dist/2026-05-31/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=de9ea71b7ddac45b08c2e6f4c69c6dc3d9e810db0de200c75093ab82e82b2ced
+dist/2026-05-31/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=20bedb469371694034b03f5bd95496b5a143567061eb09b05259ae0b229488ed
+dist/2026-05-31/rust-std-beta-armv7-linux-androideabi.tar.gz=04c75235a0a1777bd9e3cef1628d10963c3238d9231e3486c997436581e097c7
+dist/2026-05-31/rust-std-beta-armv7-linux-androideabi.tar.xz=eb2da650b78a081f32780f55d73ffeb6bb06dd3475fafe19c473ab3ce251f55c
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=d35a5fe89502dd275507ff0b47bb9e14af830bd6ec08cd2c8b54479351521581
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=186b0f50eaffe82aa2859baac7d018043586dcd2a8372268d792d557d91623c0
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=e5012e3c3a9a9dc22b82c5d8626398472f68809a27bf574bac300f71d3b99f39
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=b6a6ed0c00d460b616722cbcc43bb6899c582d8b66b50f9c717391a35b2332b6
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=13216e65baf6e6bee603965497f0c3b2e4600a48f3636a006e6b738c4a683f1f
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=2c2060e5ded3bd47343d7137d80572041c5e45f9cf5696fe97eb1eb21bef2038
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=003cced8c4a87e1fb7caa521c7ae22d0a6564df527609e2147a03eaa804197ba
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=b77598c3475e8fe001d9288e6e012bb40bc0dd5babf2d318b160891c5b21cf7a
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=383f90d6748cca6a15440091328d2c26dbff98ed9b248e43f03d91b46bdba486
+dist/2026-05-31/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=c3cb5264989ba04d3e6c5974339ed236833bb10a6844db22d804c08747ed816a
+dist/2026-05-31/rust-std-beta-armv7a-none-eabi.tar.gz=38fc5126dfdf224bc4e367c1e7fcce8738b8c1a5dc2b1f8676fac9123902a71b
+dist/2026-05-31/rust-std-beta-armv7a-none-eabi.tar.xz=992519a5e91ea68ea530b64c4ea44f16d01b02410503b8d98e31875de1b44b19
+dist/2026-05-31/rust-std-beta-armv7a-none-eabihf.tar.gz=5a78c4eb815c5920d8f1ed9c7112134cf7885da58b49e7038851a9a2b2489811
+dist/2026-05-31/rust-std-beta-armv7a-none-eabihf.tar.xz=e1e4015921e7dce969e545e8ebf3184e30c9e0b9b2defefdbe8182838e948169
+dist/2026-05-31/rust-std-beta-armv7r-none-eabi.tar.gz=d393f8fc7bc7a0bcee21751cb475026fd4f9ab3677365629b750a12aeed5ba40
+dist/2026-05-31/rust-std-beta-armv7r-none-eabi.tar.xz=db0a0a83d2b367249d99f36c82c3216bc87ace2a06218eb58a6998369e9ff9a6
+dist/2026-05-31/rust-std-beta-armv7r-none-eabihf.tar.gz=aeb46e64f66cf3dd08388fad373781e4acedd9936a645ee4d63ad43d2f188591
+dist/2026-05-31/rust-std-beta-armv7r-none-eabihf.tar.xz=f252b53ab4443f2c647d4de64e00cfddbb72eb8c1167f1b50415d9c6b7b2f366
+dist/2026-05-31/rust-std-beta-armv8r-none-eabihf.tar.gz=a97a003a9ebd3122b311fb2e6baffb28f8ad830b93235eb4b161e6a856502c60
+dist/2026-05-31/rust-std-beta-armv8r-none-eabihf.tar.xz=97d4320614650f0043fc24c96230552b462772f5490cd903a025fd1912205eab
+dist/2026-05-31/rust-std-beta-i586-unknown-linux-gnu.tar.gz=0a69f51d712b9417f9aa0ebe0f053fb2881562fcaa97408970b83d2676fe81d7
+dist/2026-05-31/rust-std-beta-i586-unknown-linux-gnu.tar.xz=7490e25399242aab980859f7fed3ac60fd9c67d560b533f208c187eddb174dab
+dist/2026-05-31/rust-std-beta-i586-unknown-linux-musl.tar.gz=e8b9f0baf6b8e0ce9d2489da619ec80ae4ca36ee9eeb6383b5a433e8396a2b16
+dist/2026-05-31/rust-std-beta-i586-unknown-linux-musl.tar.xz=3020a63efb7b4f99654d11011909596348c11e2bb46eec8d0e24f1180079c831
+dist/2026-05-31/rust-std-beta-i686-linux-android.tar.gz=7665e67f8d29844e1b70ca22c5fae2d197238d53270c99c3bdddf99666c66a31
+dist/2026-05-31/rust-std-beta-i686-linux-android.tar.xz=f7544f9f68a8dfca72a26d55429fb18c9a3f09fc44a1d3069f3797540c9f7339
+dist/2026-05-31/rust-std-beta-i686-pc-windows-gnu.tar.gz=c715e39143af479723e5a5edc4e5ce5bad30a6a746f443cebbc1ee477d5902b4
+dist/2026-05-31/rust-std-beta-i686-pc-windows-gnu.tar.xz=b2c4a3401ba40b984cdec962cd2ad95a3e677ba911e9caae5f8db400be8be123
+dist/2026-05-31/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=5c842c9b691ff6a3c2a950ab85f08e5df7046874df1ac748a3bdaace630110af
+dist/2026-05-31/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=92a9be1eb8504ec4a3991231b51386499a054ee963ed4f55238ceae09af01515
+dist/2026-05-31/rust-std-beta-i686-pc-windows-msvc.tar.gz=066cf09763e1e389c4a26f31c1c0a251ca5407e77bc91cc69ced826d17824049
+dist/2026-05-31/rust-std-beta-i686-pc-windows-msvc.tar.xz=d0efc08346b0f0ec81698997d9b823f2a386cf57490beef4bfd5fa5c2c83db39
+dist/2026-05-31/rust-std-beta-i686-unknown-freebsd.tar.gz=a15817a1488da28f298d0c849a19c7103c15fc4ecefc9e9f2c3a9784300ef661
+dist/2026-05-31/rust-std-beta-i686-unknown-freebsd.tar.xz=715a1cdf09ad6b1837a40fba4e8c97cca38d39b3903c155978c97307ed294715
+dist/2026-05-31/rust-std-beta-i686-unknown-linux-gnu.tar.gz=bf00e0df238fce1e89bce8d425ae11e5578816d99e603b5d13ae3e5a36328567
+dist/2026-05-31/rust-std-beta-i686-unknown-linux-gnu.tar.xz=80ae8c730567a32e5fc7edd33e59cc7d9c921448d9867b654afad3ef834ab13c
+dist/2026-05-31/rust-std-beta-i686-unknown-linux-musl.tar.gz=8a700d1df78b9ff7ab8cf9d807799c63abe672d2aea3250feec5062b8ea8e1dc
+dist/2026-05-31/rust-std-beta-i686-unknown-linux-musl.tar.xz=e385fc1087d67358e3a402c826b6b27f97d2c85140caa49f7ec2cbedf2e25ada
+dist/2026-05-31/rust-std-beta-i686-unknown-uefi.tar.gz=6cbb40c805f8cacaea3afcd410cf69f6ba1e5052109897ecbff44249c8f08a8e
+dist/2026-05-31/rust-std-beta-i686-unknown-uefi.tar.xz=0956009592fe270d24459c4d17cf18911a5911a09c9ad3089d9c25c26a5b7dcb
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=f56888bd6915515c4b7579804fc4157e3c1360b4a47553e78ecd320d597ef106
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=996cd2e7e258faae0d11cac51482af31c561a8bbe83ff9253b459cd92f3b171e
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=16fe3890a06e98c64f1da200a6d30296d1eb8ef03f98e3ccdbe985797f759216
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=b1607ee88f215767b0120371af91221bea65d512d90ed8470547a3ba9f61dabe
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-none.tar.gz=d9cb12e0fed1a06d04121bd710bfed12f13c6fc37bdb80f7b4db7c03bea97fe6
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-none.tar.xz=78d5b40299a84fc00402f76ae91ae6e4a8269d20539174f61afe833a1ec207ee
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=48adba20b71d67fa0f1b2f17cb94393f07a00898a0c22d86468afd3b8140c088
+dist/2026-05-31/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=5d997a888b9483d1955bcd2907e082ab90ddbedfe6f5c83725bf5b7bf3d10611
+dist/2026-05-31/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=e20441a4ec1724bcffb131bf089bb77dfedfd5538f9c2d9927a3fc780cae55dc
+dist/2026-05-31/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=2cb9a7b3c6583eddb228eb2f999f9c0643559ca0960dc99f24126637ce140067
+dist/2026-05-31/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=4afd5406142597569f79908ad55f1b4e0291d9129b63b32fd2b4469210af54f4
+dist/2026-05-31/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=b2bb5bb8f570d77d47e2bd52b28ac97d3bf1ac2d88ed0ddf9972bc2816bef14c
+dist/2026-05-31/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=8f21e01cf4d9b81a6b720e4d4d564cfbfab3918090aa95b1a5c02f128def95c3
+dist/2026-05-31/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=49778b0b6444509b543c1ca1c8b966b4f1ab67be5a9ce789045cc02f00051fae
+dist/2026-05-31/rust-std-beta-powerpc64-unknown-linux-musl.tar.gz=082183af170536d7e4838d1c18e6afbdebdf9bacff9bf392d3ff7a9604310f38
+dist/2026-05-31/rust-std-beta-powerpc64-unknown-linux-musl.tar.xz=374d0a18c451dc113be50c05edee17be3285cc269bcae59eb798eebc95b6d1f3
+dist/2026-05-31/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6fc86c3cecf1b5ccdb93669210bec92200ddcbcb0ccb69def3109394e82d1ad7
+dist/2026-05-31/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=0e1b9dc2103a8d930844ee337f8f15829cf6b931e87b4af2731901a5331f1278
+dist/2026-05-31/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=b6ce0c1b526bc91afc766e12ad00cf27a005f7d1334daa22962b4fd0fb0fc30e
+dist/2026-05-31/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=55355071659f646be2c51a69d50668ed43c6a7abbb9b446a0ad176c8b8c5e409
+dist/2026-05-31/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=1e85fc0936b667f5c896043c0c6ca9c264eb3a7134c832f710baab978639c707
+dist/2026-05-31/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f4977fa1085d827cd2cee3b595d0f021a472b6625d311df5cdbc9816fdba4a47
+dist/2026-05-31/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=352e8f5612fb5fcd65e0dc3534bb0a44ca9c4213cf8f1b9f3f324896a1487fc4
+dist/2026-05-31/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=357f218f42c7daf84a1e4ca415660096d352a17c0945fe400c42c07f92f2a7ab
+dist/2026-05-31/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=79e5f7654be86dd00578d43ae21cc8783a41b8f427fe68a15e6a114c249a4db8
+dist/2026-05-31/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=10c3a6b527040790ac364d1ae9bf33f2f3d182108ec2f913491f96d3a5e25c65
+dist/2026-05-31/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=fef14a79671ca99d47a80a81982464da71b9efb4766d18e705c8e706afafe164
+dist/2026-05-31/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=6d409ec81ddac2ad63757e7f2081033477ccf7e0ec35622f0649110654d95d3f
+dist/2026-05-31/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=d1e3beb29aaba18c4dccd2b819c46677080ab42556501754bf9adce602c9c66f
+dist/2026-05-31/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=72f9bcae4a99d611a8f2fa8094c4093beae5f03a96210fb76a1a3d13e203185b
+dist/2026-05-31/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.gz=c9d025ee108ef9ae057fc9a8a65a00d645ceea09e305d7072373cca1ba9a703d
+dist/2026-05-31/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.xz=929395398ca07755591a216eb180b759594cbcfe7b3a1a291484866fc1cad30f
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=a7560e666897a1bc73350e568dc972141372a1da6957e42d347ce54cf77a49b6
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=237048ca73ed24877d5c8669f7dd2fcd6ea6da00d3b4ba64ad3d350bb3b0fdbe
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=52caa0f69f2c5a3b18e79044cf54873711c606c850dc619650670f29ca9298b6
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=3fbc8ef68e0045236a45994c4d629ccc5cd673a526767df3200e1ecba0f59424
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=9c08157f38cc93f5acaffef14878ed5aa2940d856e6f6933ff0cdaec9f976025
+dist/2026-05-31/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=88276d8767e8dbd0d9e5c07e1e7b9d0c0c2ca8810c0a79a23a5d355e1266ece4
+dist/2026-05-31/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=54cc920299bb182b0b9840ec2323c190d8b412926d675374d80e1177674641e1
+dist/2026-05-31/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=903d87c8745aa146df20c933e1af6b744d1baec6b944ee7a5bca229993addf36
+dist/2026-05-31/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f2a6eed8c1a8b2d4d63be9932b6438d5a7e0ecf2534491334ca523df8f5b63f7
+dist/2026-05-31/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=a6035fe5eb7f235e2e4f1e238665d302e7e3b2a462b2eeddafcfab7ed51156bc
+dist/2026-05-31/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=f2dc3d960db0c1ef7e7523274e4cc3f06068ab058b6750be2526b99de694748c
+dist/2026-05-31/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=3c03c76ce458524490f71266f807f2e54238b23b7d8c2f56070c27d577daf321
+dist/2026-05-31/rust-std-beta-sparcv9-sun-solaris.tar.gz=26e35b5d3b104825532c7875f12760343bcde48d4652d39dbd7b7f6748eeb4ed
+dist/2026-05-31/rust-std-beta-sparcv9-sun-solaris.tar.xz=82438f074014eb1040bec07334afa1e5218e63468815f1fd3856e0d63a2020da
+dist/2026-05-31/rust-std-beta-thumbv6m-none-eabi.tar.gz=9d4b04b7874057a38b2b0abe1912af8fd149e402ba783433717fc76e317f65a5
+dist/2026-05-31/rust-std-beta-thumbv6m-none-eabi.tar.xz=e20dc700f450d3641e8db2f03f542136eff0e8dfe904a54da864b37a0b3507f0
+dist/2026-05-31/rust-std-beta-thumbv7em-none-eabi.tar.gz=8b250c320120d2bb450576395f1e7e4500c4983ef5ffe5b01a1f44a012e903d8
+dist/2026-05-31/rust-std-beta-thumbv7em-none-eabi.tar.xz=8fd0476356c4157ee45c90e9cbadcaa65148a7e230769cd0af91ba2f84c40324
+dist/2026-05-31/rust-std-beta-thumbv7em-none-eabihf.tar.gz=6ebc0e0bc5698434b1f182f0d08414a8574874c6650e6216408ecfc7bedf76d9
+dist/2026-05-31/rust-std-beta-thumbv7em-none-eabihf.tar.xz=be5e3f4d470339242cee9691e2f3dacad182620c8372ddca50d8a75c7c1a995f
+dist/2026-05-31/rust-std-beta-thumbv7m-none-eabi.tar.gz=1158ba54404fac9f73d3a8692d53719b5d0fc7922c2c2b83f1e299eb82091a26
+dist/2026-05-31/rust-std-beta-thumbv7m-none-eabi.tar.xz=d569465b06aa8f760069b18f81186f0e0ecbd2c24b1f12aaa79f2cd9c26e90b2
+dist/2026-05-31/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=43c3f73803fd2d28a4b7536654ba6b6b72edea68a7ab32877205c0547dfad2c1
+dist/2026-05-31/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d9fdfb9a500447a6981e016cc974618633b49eaf543a763487e2c55cc8507ce7
+dist/2026-05-31/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a4ca69fbb4aaca0716d20acc07914565b51bc861c4e7ce02ca3ecc731e872b56
+dist/2026-05-31/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=34cb7a58573fc691177e7375c4447bae7708c258937246d8f657d7c2addbef76
+dist/2026-05-31/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=a4117f22d6bb2addde5aad12d3e10402fd6bf25c32ab4d58cae5fb90d5a09614
+dist/2026-05-31/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=aed0e1540a0074ac92ce365a695e09e3a2adb98adce48fa80d5054914450e863
+dist/2026-05-31/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=a5fee984a814ecd123b464df42c716d8750e1e9d6b941a33266c716ef721a672
+dist/2026-05-31/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=7d6b58c8f8e093d4dbb22a2f5e6865042771d646f7d2ced1bf97ea2a576eb4a7
+dist/2026-05-31/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=6d61b99cfab733f42a011d0966779facc656c9df9d614f0461aef91701eaf80f
+dist/2026-05-31/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=0016cb035770e29324980bfad83d784640f42b4366056e004da3176f1208b319
+dist/2026-05-31/rust-std-beta-wasm32-unknown-emscripten.tar.gz=916163b3d13c051bbfd6f0f5586a017a1c0caead5ea0286f1b2a9823d728d702
+dist/2026-05-31/rust-std-beta-wasm32-unknown-emscripten.tar.xz=ddaf50ffb33797a83435eb386592948bbcf982959656b996deb869e7f0e14bc6
+dist/2026-05-31/rust-std-beta-wasm32-unknown-unknown.tar.gz=b3dd42b05bedf9c6309279d8c14af4d88cf470f3304af0233931544b611dfafa
+dist/2026-05-31/rust-std-beta-wasm32-unknown-unknown.tar.xz=1f6a038ae4fbc3dfa925d948b63d8de5b15d4cfa350420f89caf6c1b77a0f342
+dist/2026-05-31/rust-std-beta-wasm32-wasip1.tar.gz=45748a59b117bc94e3990adebf05e44503e53d7ea9a433b59196a4ea5d98ea6e
+dist/2026-05-31/rust-std-beta-wasm32-wasip1.tar.xz=3850d5226483c1f1facbd756df8a6243d86f470390c93b9f108c3308866950fc
+dist/2026-05-31/rust-std-beta-wasm32-wasip1-threads.tar.gz=040ebfc13e209396b7ad1be1b4fc787cc00e6325f387fa6b07e62fd0872707ca
+dist/2026-05-31/rust-std-beta-wasm32-wasip1-threads.tar.xz=d65469a04e580a62f2dad81e49aef3f9d38333212d6f7b7f32b2c69f68e119be
+dist/2026-05-31/rust-std-beta-wasm32-wasip2.tar.gz=3c7eada5c22596ec506690f07f1c740374dac9663b3d77e8bc3a764a3564a604
+dist/2026-05-31/rust-std-beta-wasm32-wasip2.tar.xz=6eb9ecf63c600975bed7391243579068bd7a826ef9abd39b8d85a45c2f09b6f3
+dist/2026-05-31/rust-std-beta-wasm32v1-none.tar.gz=6938ceeda493d602c3ff3f6f4b71db30772e1a78eec0f1acea8f24aa175210cc
+dist/2026-05-31/rust-std-beta-wasm32v1-none.tar.xz=0252a1345238ad9e6ffa3eccb5f3213f82097f3e83cd7f4d3a065a4bafe42fe8
+dist/2026-05-31/rust-std-beta-x86_64-apple-darwin.tar.gz=82ce494e1499cd0881cc1778388f9531bfa26c7d2692c0eaaee37df0095dc602
+dist/2026-05-31/rust-std-beta-x86_64-apple-darwin.tar.xz=42e843d1cdee6bcd3fb5da8ab79cfb09437516060878654a6913292c0ffa0d95
+dist/2026-05-31/rust-std-beta-x86_64-apple-ios.tar.gz=24e3af3f960fec1531bea89794763fb26a5b3ae926293c29c66ba0e4538d03d8
+dist/2026-05-31/rust-std-beta-x86_64-apple-ios.tar.xz=f6b9ca4f29f764041b621df402528c8ba7cd7aca22d72c5dffcfde62bc47ac5f
+dist/2026-05-31/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=9ea44810f3486cf3367ab5e0f046a91b80028a3cd2ac7ce21cad54267bf5fd72
+dist/2026-05-31/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=ff12073d3ea95f694e0a7bb0aeb266fea8a0f0f6dd718aed337b867e09f0ca73
+dist/2026-05-31/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=f661cbaf71b2708c60af67b784c8b5ec9ba8e2c58406c78e54e5060043dd17fb
+dist/2026-05-31/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=1dccd346264eff7a18a8a970a2e0f6302eede7abaa70492ced9e9062e2874685
+dist/2026-05-31/rust-std-beta-x86_64-linux-android.tar.gz=ed444f3b8a40231cdb5f15d390c30c6429ec36171424b27e6b17e1e66435a76a
+dist/2026-05-31/rust-std-beta-x86_64-linux-android.tar.xz=d20b095d5ded63ab85c56808d384023654f0637631c4dadf9c4e579c2e4731d4
+dist/2026-05-31/rust-std-beta-x86_64-pc-solaris.tar.gz=6e627ce0b32b1cf44c3295676b173ba5cbc6c04acc4a5285b0a0c28cf12c5313
+dist/2026-05-31/rust-std-beta-x86_64-pc-solaris.tar.xz=138c3f578d484f0f25a214327d1c3fb3b1ae21b35b92bd1f6fd53babf1931634
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=d0751477f19baabd0464c162408f206c218fb1d51b5b07dc8117010902fa275d
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=8cde4ff1a3f74b5bf7d6cd5d6e82764cf40bf147108fd9cc2d1bc7e97ba69c5f
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=a179839a623682445dff140cf7ee52e10099a62bd533dcbcb5dfec0bfbbdbd09
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=d7aa76321c3fb05aa8a2c35524cb9394587327eb59be376bcd8c3066ad1e2599
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=4060f1a20649937eb2debbb86b167e6eda095c59e01064b2a57d579cfcb6f144
+dist/2026-05-31/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=6ef9f6e9a60afb480418160243eeb37dfbff336dd0e3b5a67287efbb467f9f47
+dist/2026-05-31/rust-std-beta-x86_64-unknown-freebsd.tar.gz=158b877a47220ae229c1f8eca1ef3d9284dc96a10f9445ee88e788568eec0149
+dist/2026-05-31/rust-std-beta-x86_64-unknown-freebsd.tar.xz=77b21d734a10feeaf5d42e864079c3623e30027f22cd60a324856479c47e44e3
+dist/2026-05-31/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=19fca9cf6205a9f61dc36e41467895c3903bc55a10721a44e5c505f76239df2c
+dist/2026-05-31/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=b488ac15b80437d227e1364d86b2053f0b046d206faa30b10041175fb4757283
+dist/2026-05-31/rust-std-beta-x86_64-unknown-illumos.tar.gz=739941e626b216c5dfe8b81026e1b7f86286bd31dba51ed4fb1bb8a465f56575
+dist/2026-05-31/rust-std-beta-x86_64-unknown-illumos.tar.xz=3ba5b93f735574f527c9ab2d7f1a91314b30c6735a7b328f32b40155cb750e57
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=e5effbc8ff54a318ce2dcf187bdfcf33b4e3c28d130f68725165c7e1c68f1816
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=ebe326c6bcdd77399cc451dcb999dc61c0175ede55ec1153c9693bdbdabfb7db
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.gz=052b996b23da17b3dbb87eb9146852c6408904d6730605f0ed700ea3846aad0d
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.xz=6afa47a4a44edfa739dc3a0efae39a414b9cc25bc15e164c3330ec60dc61962f
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.gz=08e5c7fff840c4042ed92512bdf7762421ffb99815ec3ac6a4a6e1151f8de512
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.xz=cbf16acce5235bffa65024e71c13da0e56153659997086abd97953a097e76675
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.gz=e5cbe002a1efded21a7f170ef1b3822d86f54d773ce8f05789cb3e248d5a8419
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.xz=a62657cbde4bab3edd76d2a4dd14ca0a6347eb8c3c2b3a0be15adf2cc3a8d82e
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=1f3f6d8623597c89b542a5a7526e1231fb4386f1ebb96281e4a23700d579949c
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=a9a6ed95e11328ae9be2664dc9e5cda06c524cd9a830192eacc6e212e5412370
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=9c869cf57773c4f0790df55535b97262a8bb9ba3ed3fef06a29c45fafda671c7
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=91417e7a121b8e5b1d906c0fce37ed8c02a3a97b1f8a8f3e60f1102b38ba3216
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=1ad7fc6eff07a0bbe7f141720e71e27e6cc08dd219ca9a225c4adf6de88209f7
+dist/2026-05-31/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=4dd2c2ad749da32b90d1cbde4b4e160f83c0d1c973badec47f1435f98049e688
+dist/2026-05-31/rust-std-beta-x86_64-unknown-netbsd.tar.gz=6e98efadf54a09e83993dadcb7eeb803fb2182fb68262fc1de7e026b70cf7a35
+dist/2026-05-31/rust-std-beta-x86_64-unknown-netbsd.tar.xz=29d2762d0eafb8167081cb9f3cc119c08faba1c5590ea25bf0f4e14afe2ca73e
+dist/2026-05-31/rust-std-beta-x86_64-unknown-none.tar.gz=be21df6336d5b53ed82cfa4ff47e8170cbfdb64632657097e0f905cd69f30eb3
+dist/2026-05-31/rust-std-beta-x86_64-unknown-none.tar.xz=e626563d7bee3d38d62c563273a3fa0b5baffc14f41600e1f61ee5488ebd07f1
+dist/2026-05-31/rust-std-beta-x86_64-unknown-redox.tar.gz=f5b6fbb78b85f9df67078c383d8109a6a4b90e714b2375c21a4aa4cfd9933bfa
+dist/2026-05-31/rust-std-beta-x86_64-unknown-redox.tar.xz=65b7176f5c06513e1f36dcf31470ebb2de20eb68520bee5366e110ad4595bc3b
+dist/2026-05-31/rust-std-beta-x86_64-unknown-uefi.tar.gz=e732d76443090b133a1b9d451c79d5fe49dc7fb225a12d0da1316fcd954c0bbd
+dist/2026-05-31/rust-std-beta-x86_64-unknown-uefi.tar.xz=df8bb3f70f9fb22a7d084386f8872a620070da1535f02d335d25341c60a095e5
+dist/2026-05-31/cargo-beta-aarch64-apple-darwin.tar.gz=1c900db5f022cb3f95392e7856d1b1e3511b75f821ac77e1cb8a6d655d30de94
+dist/2026-05-31/cargo-beta-aarch64-apple-darwin.tar.xz=53e0f2cf674fe3b753833997df6344250c02f9f83b50ea8c3771b3286fc1024e
+dist/2026-05-31/cargo-beta-aarch64-pc-windows-gnullvm.tar.gz=58f632902a71caa0818bf4838a7cc9e0555b29e49b81025d3be8913ac21969c1
+dist/2026-05-31/cargo-beta-aarch64-pc-windows-gnullvm.tar.xz=c18dac963e3ad7c1b40676cbc8a0667407c8e9e877abfb744551d5b393e57b1f
+dist/2026-05-31/cargo-beta-aarch64-pc-windows-msvc.tar.gz=20407421bbb671cc7ae833da5f4b7ec75c18bab571f085069b5507c10eee8b0e
+dist/2026-05-31/cargo-beta-aarch64-pc-windows-msvc.tar.xz=be0dcbb902f6798cda78e5d4f59da0e1710da93f2f7fd3c68fd9a15a84d518c6
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=db8ba59332d2d9b1b8992112727a2e33210e12b990cb8620cb149023ba9d0ab0
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=4e4fc9d07fa80d591605e969d87981e27d37fea7533152b2f9a65e2001658f93
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-musl.tar.gz=2c454d3d4f13fb3bb8d50b64641f31e1fd6c9cc36e5d252b693d0675142240d5
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-musl.tar.xz=6b8bbbdac787dc7d7fdf65287ac6836ec01fc22b875546989f62b9263ab26aec
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-ohos.tar.gz=0e81dd209c80ebecfe693f5c88cf1dfaea50f82d6a427b9c7685ae30b5c5882c
+dist/2026-05-31/cargo-beta-aarch64-unknown-linux-ohos.tar.xz=8caae8dcddbdf62ff3927a905c7405e0bcf0d4cf11dced8c51a5edd6cc62b4ce
+dist/2026-05-31/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=0e756c44c07cf9a31c3f07402416e96cbeaff9287a8d823144fe15fb7b8a914d
+dist/2026-05-31/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=1fcd0adaddb4270c49a284be5fdfc81dcb4ebfd65cca21aa790d162a4486e60e
+dist/2026-05-31/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=1d195cb636ee8915fe6dc57111f373d3281a963660ab9ad01bf63821a3bfee4b
+dist/2026-05-31/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=3add2f1f39bdf40aaabf755b0e91bb8872519d2feab30f039f6ba6f15f500f2b
+dist/2026-05-31/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=38247e44a39eb60651ff707d7605ccaf5bfaf0557d9093fa27097e84478b67f0
+dist/2026-05-31/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=08cf61296a7153440b1daf6c16c1fba703eb191c0686104999848c752f2b44e7
+dist/2026-05-31/cargo-beta-i686-pc-windows-gnu.tar.gz=3966d33b73cbc721068ac6d89703083478eb292d8e7b22296365c1bae1af8181
+dist/2026-05-31/cargo-beta-i686-pc-windows-gnu.tar.xz=d6cd37f8f84b7e2ef29edac542f2bf62f3d7ff25a5b57f88457ff2c9b40278b9
+dist/2026-05-31/cargo-beta-i686-pc-windows-msvc.tar.gz=36f9fae072a21a32ce6aa66d6ebb45c25175ab9bd54fa128e582a2f51e76e35a
+dist/2026-05-31/cargo-beta-i686-pc-windows-msvc.tar.xz=1aeee058c51fccb4ae53e9472d39ba6369e5a7f7cf95c3ff8232d9bb5aaeec41
+dist/2026-05-31/cargo-beta-i686-unknown-linux-gnu.tar.gz=21e989ace70f785dc6b0753078d720461643a523be923a01f3a11de435ddb3a7
+dist/2026-05-31/cargo-beta-i686-unknown-linux-gnu.tar.xz=48074a8ce5ed2a7d1ea2a18f7b96099b270806df116c61a3738829f084c6dd80
+dist/2026-05-31/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=f5f052145d530efde4518c2fd60f608cda568539246ac93698236d920edc081d
+dist/2026-05-31/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=40408fcd941c5b90b93ea2d5b23fbad053823b9861791e85322bfcac19782215
+dist/2026-05-31/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=b067654cf1bd26cacbac609718eed59b1bd74d99c326929a7995325676062d4d
+dist/2026-05-31/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=8df33ecb473c500cde55dd861976150c1d5d28b11c23c37b6db0adf013df8e55
+dist/2026-05-31/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=818ffafcde74771ff6439dc66819f7040cecd9eca2f6dbca3af0b0066a218a8c
+dist/2026-05-31/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=3563ff89159fa199546e91d3b297c8fc71c8b0c48896bf91d8d643cf7a178c3d
+dist/2026-05-31/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=406b5c772125746c258f3ffc317135929c8cefd4489e556319f86045bca4d19a
+dist/2026-05-31/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=4dd7d8b879274428eaf580c2b077a668cd02ba41356354a59fbcc3b4f76c8b5f
+dist/2026-05-31/cargo-beta-powerpc64-unknown-linux-musl.tar.gz=2fdb37111cd53aec01ca50db4e50058f4f5318fd44e6c464adbeb3820d009f13
+dist/2026-05-31/cargo-beta-powerpc64-unknown-linux-musl.tar.xz=68586a1e2eed2f87778eb956a9ee0da9032a76808a54155c3af4b7a615edac80
+dist/2026-05-31/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=ecfed65ca58521c441ba9a53522eadf121e1fa89390594f5d73a95906c7a7e56
+dist/2026-05-31/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=9d14fe65382427e672cbbef50a90e8a0229849090fbe27019df2a7c4f621ab14
+dist/2026-05-31/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=23f4357111b4af9f6b8759f2e3ce84428e571787287d637a4fa1e6ce31cf51f4
+dist/2026-05-31/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=6b31a49219259a20366646b21b7c6ea3d3968bf9639d698bb9e374b8ede298e1
+dist/2026-05-31/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=48f1d385b802edf5abe455f899d8c2df52d7f0c906976d4905e3e37db6cbace6
+dist/2026-05-31/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=9ec55313368199793de5af8167095aa03af60b86999dbb9715effe25270b3e26
+dist/2026-05-31/cargo-beta-s390x-unknown-linux-gnu.tar.gz=070ee86f9ab2e14962f4bfd6a9c820021056164cb2993f8e821f967f48e4fcfe
+dist/2026-05-31/cargo-beta-s390x-unknown-linux-gnu.tar.xz=87cde65ae28b9490c4991a388928a763f4dd546f86b6e4f496c3521f9e73f09a
+dist/2026-05-31/cargo-beta-sparcv9-sun-solaris.tar.gz=46c8d673e363cb85cf96d694b4a4db791262d6b8a9f668effb7c1dd76d809026
+dist/2026-05-31/cargo-beta-sparcv9-sun-solaris.tar.xz=4fe556875b35f2b6f3088dc1f6527fe4b512934dc918559f914a5f05d47e88ba
+dist/2026-05-31/cargo-beta-x86_64-apple-darwin.tar.gz=4296494d43955daeab2a9eb1ecd0a4b901c57680399e4c9874a7eaef7cedd99c
+dist/2026-05-31/cargo-beta-x86_64-apple-darwin.tar.xz=4830b4d2b90f4134d6dd1fb1ca7b0b2804b38d2d2c2474df1479ff7ae37b4e82
+dist/2026-05-31/cargo-beta-x86_64-pc-solaris.tar.gz=793c5192918045305bc542ac676b4cd31814e6bdc0104054884f2979e3eca118
+dist/2026-05-31/cargo-beta-x86_64-pc-solaris.tar.xz=356efef4c2620d5a44010cc76f2a1d67c3b8abe022c8d70a45b82b06fcfbf992
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-gnu.tar.gz=dbd3b6db322da4d9757a09e66dc7c5a941defe4b1dab68e2a5f1795bb6d8c45c
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-gnu.tar.xz=a749691fd83d687d59c2985dfe6930d9de1ec675e4e40e097bea99800f4427dd
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-gnullvm.tar.gz=fc907f16bd9a0335ee2321ed3224d032ccb2b1ca6ecea30bbd068de5d9f861a3
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-gnullvm.tar.xz=ad5b9130c4cd28a370f47f1f56b9d6a9cdcb5b020f5ed4d9f50117e13dcd24e2
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-msvc.tar.gz=bc00b88edc99b2df3e949061e750c52c3e5d35e790ebf9394daee35b85830a30
+dist/2026-05-31/cargo-beta-x86_64-pc-windows-msvc.tar.xz=65900ca0ea4a2bd6a0652a384976837852ba652d615033d9e66f1cb1ac3eb549
+dist/2026-05-31/cargo-beta-x86_64-unknown-freebsd.tar.gz=84876aa77f233d3a444f8799b0dcff010d66f58ac737064c374258d6c8da7d37
+dist/2026-05-31/cargo-beta-x86_64-unknown-freebsd.tar.xz=7a105782f5152c52b8e7e9dd57e2c65b762b851c4b69486eb2cffe5d3eaa25a3
+dist/2026-05-31/cargo-beta-x86_64-unknown-illumos.tar.gz=e7d7618a7751304e5c566b7252492e173c4245c342c1824cadc661431057ca32
+dist/2026-05-31/cargo-beta-x86_64-unknown-illumos.tar.xz=dfc578416acd49116b928995d5d15c6084e36428ec834cefe5697676f7cafd83
+dist/2026-05-31/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=92707c779a57b060935e613398a89e757afa88e41af9913ac1f220b8e4aa9aeb
+dist/2026-05-31/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=53a486f2e75ac6a05497181ef7a2c2c58ace6e5be401f1be0c1e8c9d3c9d306a
+dist/2026-05-31/cargo-beta-x86_64-unknown-linux-musl.tar.gz=49327822da061abab51833426c050b3d929c929efd8799bf893e868073034881
+dist/2026-05-31/cargo-beta-x86_64-unknown-linux-musl.tar.xz=e21a7d7c92b0415b4ac31ae281a492ce8f32d2c3163700c76d54c3f621fa7fbe
+dist/2026-05-31/cargo-beta-x86_64-unknown-netbsd.tar.gz=f1ee55d99c157d1a3b1d2fad0663696c909aad33c69b0f329e7015b3d45ce95c
+dist/2026-05-31/cargo-beta-x86_64-unknown-netbsd.tar.xz=f89f8a5e49fa6f8d094b462abe9e98dcedf89943bfe09be9a84578f9d2e50e8e
+dist/2026-05-31/clippy-beta-aarch64-apple-darwin.tar.gz=03bf7914cce99504f7208e6692f0c40131176c74e8fa5d8afa1099b5415404d9
+dist/2026-05-31/clippy-beta-aarch64-apple-darwin.tar.xz=2ba04f76ebeaae175f35b97d24604cafd5fe8bf5775a008bf61821f59fa138ac
+dist/2026-05-31/clippy-beta-aarch64-pc-windows-gnullvm.tar.gz=5adea05303c1b1ed4722ad76e1374fad62f0288a4d0d606ed9fbd50326a656bd
+dist/2026-05-31/clippy-beta-aarch64-pc-windows-gnullvm.tar.xz=98b203708d28f69f72fb54278a57ffc31db6a98c359fceba646c9d5e1f21bca2
+dist/2026-05-31/clippy-beta-aarch64-pc-windows-msvc.tar.gz=67a87985180739f66655a1c2142c1f910baf2c3ea0ff96b72edee4020811beb6
+dist/2026-05-31/clippy-beta-aarch64-pc-windows-msvc.tar.xz=d41494ccef3467b0c99728a574c9340046e77c418f982a2f638ac3d9876a9f6d
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7ed41d42d8381300415783ae79c1c8e603d386d72087887b667d4c31e22078c1
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=b6ee14b1909ec4165a086696e3a99f69c877285831bc9bc1eb9af0188897f8ad
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-musl.tar.gz=970ac19de12bba3c8de4eed9bf8c886aa3cfd95006d9b29e8c9b1f1eb142e41e
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-musl.tar.xz=0128005591dc0bf88f61e4598c6ae29f9f644e1a9fcb20ce2f790fb2366906d7
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-ohos.tar.gz=0154d57504d5b8fbd9a6890ac4ba209de9ad2c190d4ce7feaf28898166e18fef
+dist/2026-05-31/clippy-beta-aarch64-unknown-linux-ohos.tar.xz=640a089ff8e818235a57080e96e8e6dd079a7678f708ffb190b7dfb709dffbce
+dist/2026-05-31/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=c4427a48c50a61a69a3af0fca8c9e192b6af25417fe7ebebc48db63233ce15fd
+dist/2026-05-31/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=e13b6b309378a111f122b43c51253947c66121bdb854640aff776f938217634a
+dist/2026-05-31/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=81bf0d76529c051b85f662c854b8b1c0aa0d171d6886f42067eaa3df4c5c679d
+dist/2026-05-31/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=9cde407ef664b330c4f3cb1abe71cc8e093e3425e81e93f693b93ff364a62852
+dist/2026-05-31/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=4e7d043ba1ce22f3125b3077e0ebb1f0e5784026b17ef7eee6f9f3fb9e71f168
+dist/2026-05-31/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=c628fdb9f73d5ac90bbccf0584d266646b798c4a47076785b3bffb1d9dddd27f
+dist/2026-05-31/clippy-beta-i686-pc-windows-gnu.tar.gz=74c9cb6870baec95a190d04290292d52604103a26c3ff23bf58cc57a3ec3a684
+dist/2026-05-31/clippy-beta-i686-pc-windows-gnu.tar.xz=6d8494d3ec111c6747e53d63cceddc79c9c85f18f882bcfccf44c941194088c8
+dist/2026-05-31/clippy-beta-i686-pc-windows-msvc.tar.gz=19f70d7b1fca8c89955490a783aa013384158ecf11d738c5e3e92ef6f4da0889
+dist/2026-05-31/clippy-beta-i686-pc-windows-msvc.tar.xz=a02e16a60761aa49357661219d21633ccc6f955f3776b5543873e0e0e9dfe55c
+dist/2026-05-31/clippy-beta-i686-unknown-linux-gnu.tar.gz=3506ad8d1224b418e2e31019e134eefdbb5785143053351e5ef25de097ebc004
+dist/2026-05-31/clippy-beta-i686-unknown-linux-gnu.tar.xz=ca8898139d60944c65b145e1488606a440f21138cc71b1926eae5af045a23380
+dist/2026-05-31/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=89885d77c76c846faae60773b85806ebedc4a2331ba2b53aae6bd9b7e845057b
+dist/2026-05-31/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e0a9d861575b488f74c5f57b20a66392ae2614cc48c691502e5b91528fe16d70
+dist/2026-05-31/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a929da7c2dfe11bdde2198d51f0237e279db488d67f54d1300a13372e1d33ddf
+dist/2026-05-31/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=7240afdb080f28dfc7b3a67eead8a334ebfb99f105af7ef63ce7bde920865fdb
+dist/2026-05-31/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=5cd081b5bb591c0efd4d5eb60d73c639b510f9d72b34180bb468302dd90c32f5
+dist/2026-05-31/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=afa4dcb192eba24166ae2ab88f9f58acdff32bb4227084b3ad466dde8e120811
+dist/2026-05-31/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=32fa368bedd0c0daf428c1f445e2078f2829d5cf6277035997d64a917db2b6ed
+dist/2026-05-31/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffe7d27a8eeceab74473d59ebfd4f1f989416e58bb465bf94d43de6184b9eb34
+dist/2026-05-31/clippy-beta-powerpc64-unknown-linux-musl.tar.gz=aca70525b41759e6f19710e8eba254ed103646cede478532949e04a7027342e2
+dist/2026-05-31/clippy-beta-powerpc64-unknown-linux-musl.tar.xz=163c545a90372fda13fd943d134574ef825e385200ae457960c9aa8e2a29004b
+dist/2026-05-31/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=f811c0ace4f085eaadd3d77d760f5d6140ccbd7c9da4ef872ad641d5ac6533c2
+dist/2026-05-31/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=2471cca5ed2e2ad9017f02607f265e879362d7c988eac4644e68fadd1240ecbe
+dist/2026-05-31/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=abe1dac9162d49429250169e574ccca1007a562f7b1e495062d03a00f4231e3b
+dist/2026-05-31/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=acf0b8777d4a9d6fadacb41e36a7759b7c601a09d9836009d06d29a5f888acd2
+dist/2026-05-31/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=04bd419b04f3a4a6a413d55744f8b9f272ad692b288db22f14c261347f93d04d
+dist/2026-05-31/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=6e4a17d917aa0c9af399021780658ecc40b029fb651950a38bce29292510982b
+dist/2026-05-31/clippy-beta-s390x-unknown-linux-gnu.tar.gz=cff3fa61dec3aba56e257d976527d3d02325a553852a83a479588f8f459ea476
+dist/2026-05-31/clippy-beta-s390x-unknown-linux-gnu.tar.xz=595c2021637c76ffaa4d3f894b0b4543a36d4fd428f7346401f8939b71bb8a99
+dist/2026-05-31/clippy-beta-sparcv9-sun-solaris.tar.gz=4f348b56a47f5c0ab479dea0b21d66ed50bd6a650866c27608a7372a5ce5ef9c
+dist/2026-05-31/clippy-beta-sparcv9-sun-solaris.tar.xz=dba9344309b302e3502fd8c8e7a83550828e7f60c31a6b0e60034fff4b625918
+dist/2026-05-31/clippy-beta-x86_64-apple-darwin.tar.gz=af80ff15d68325e10be4c38801139201bfa6827ae281f9f52aa2f3b012d2d9d5
+dist/2026-05-31/clippy-beta-x86_64-apple-darwin.tar.xz=60faf6befae389fb3a125c35b6631254e3cae412f1a782ac5c201a8d92a29d07
+dist/2026-05-31/clippy-beta-x86_64-pc-solaris.tar.gz=378c4b2fd68ccb79c06fe559e2fc0a86e3f919af70a1f2e95ec0c6ed208e9ecb
+dist/2026-05-31/clippy-beta-x86_64-pc-solaris.tar.xz=8e0192565709dc60ed548ac8b8ccdae84c7cfe3055d1b627cb4e5dbbf0041687
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b038826ca7655ef42a3f8164a0314481824226dedeee35fc1a5e79a22ca45764
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-gnu.tar.xz=df9e7951003975e7688b8cefe9d0876623ddb0d583bd781e542209b5108d82b3
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-gnullvm.tar.gz=89f05e8e4af3354ac52e10008671edaf32399cd584d8bb880feaf8df60f21c5a
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-gnullvm.tar.xz=c08b4891ea22e0be76bc3d4a83b5da927a333df0700dc00e005852419a66dbf9
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-msvc.tar.gz=71312f07a8f4740a427c50a774fa8df9fe8f6ea92f0b3c81774c4d20b3246b35
+dist/2026-05-31/clippy-beta-x86_64-pc-windows-msvc.tar.xz=f5177c9be79db7cadc374c5ee402bfccd7c97164774e7adb73205e03f940dd24
+dist/2026-05-31/clippy-beta-x86_64-unknown-freebsd.tar.gz=6579b6ae0f5ae8b00acb0ea434a05d54ac31672eb041edbfe5a04b6e7b7dd599
+dist/2026-05-31/clippy-beta-x86_64-unknown-freebsd.tar.xz=3433e211efbeb473fb852bd1a3380b89e6b5328bf6497cd5deee33d3b7b0d424
+dist/2026-05-31/clippy-beta-x86_64-unknown-illumos.tar.gz=bac54b25472f58174749f96b278b754d3123b51a9b1953c73e70fb451b0ed5f2
+dist/2026-05-31/clippy-beta-x86_64-unknown-illumos.tar.xz=9604da4bd585b9ca90028d2495357061e5b879eb3e067b6e67f3a3b3f4c79cca
+dist/2026-05-31/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=43ca95afd64c5b7de748d1718950e81c4bdc7240b96b956853285c07df560f8a
+dist/2026-05-31/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=eaa27bd3c1f3967f4abd65c13c8f194b6882895e3f72a44010e64fc3d77fddb9
+dist/2026-05-31/clippy-beta-x86_64-unknown-linux-musl.tar.gz=4f6af8894db329227bd7e18a33902074bfedcc8094efd054947eff9a8f8b5b1d
+dist/2026-05-31/clippy-beta-x86_64-unknown-linux-musl.tar.xz=9efd36d821bf77220dde5e579920de3dfd9c8a77c7d7dc56b68dce85325ed1e1
+dist/2026-05-31/clippy-beta-x86_64-unknown-netbsd.tar.gz=6612095b10ec432613e4a6016e66b1766ea5986ad7cbb7f3b5f9f40eaa6db1de
+dist/2026-05-31/clippy-beta-x86_64-unknown-netbsd.tar.xz=26fcca04e88fd6b8246281f0492c0890f8d2b75bd9ae5cabfee8e7b6e21a9448
+dist/2026-05-31/rust-beta-aarch64-pc-windows-gnullvm.msi=4e6361603d237f4308016d19b120e3fb6a4a8fd4cf1d311d5a5384142882d55c
+dist/2026-05-31/rust-beta-aarch64-pc-windows-msvc.msi=9cf05def9b998abcf5a1276316a2a5ce527636b29837fef7559fe3220ed212be
+dist/2026-05-31/rust-beta-i686-pc-windows-gnu.msi=43cfa1da9086e0089552a3b1377b36197b7117c3bffefbe434744f221a95de8d
+dist/2026-05-31/rust-beta-i686-pc-windows-msvc.msi=01f7600b4ddd2045e6112a3d52e7978622de881dc084d8be6cb070ebf3329d3a
+dist/2026-05-31/rust-beta-x86_64-pc-windows-gnu.msi=d0aab810281771b90636029c8c02185773acee1baef7f89c82b828105586d58d
+dist/2026-05-31/rust-beta-x86_64-pc-windows-gnullvm.msi=9065b660d61a57a24df8fc703927d45e2903a8c14909f1392f1d6984892cda68
+dist/2026-05-31/rust-beta-x86_64-pc-windows-msvc.msi=061e4275ce0fee329e85df242af9445f57aeb4e4387d7673b78086684e347713
+dist/2026-05-31/rust-beta-aarch64-apple-darwin.pkg=fe0c51c6410b68058a6afdf0df0888c1aab0423e33f9195c2b8b593519b879a4
+dist/2026-05-31/rust-beta-x86_64-apple-darwin.pkg=4bdd11ed0d11b072cae4ea46229edc9a31ee74e985b782d497f3e696da28b8ec
+dist/2026-05-31/rustc-beta-src.tar.gz=218f419ec231e359c26d2f460d87edbc4554a58577c6fb9846a4b5fdeeb697db
+dist/2026-05-31/rustc-beta-src.tar.xz=a16f707bed3e23e7d386fb68e0d8a5e140cf87962f20e616fd35b365cf556f8c
+dist/2026-05-31/rustfmt-nightly-aarch64-apple-darwin.tar.gz=7ef7abcc5cbb1323bc21922e08db55acd0d2aca6de0507d350325abd3da45cfd
+dist/2026-05-31/rustfmt-nightly-aarch64-apple-darwin.tar.xz=b19fe339eed9e0848052f4b96624ee57beb7e99f32ecfb2c8d603be6226167db
+dist/2026-05-31/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=1f4d3d5c03f1c757414f71c5b389b66cdf45ffb032d2f1acd9b3a8515ddd1397
+dist/2026-05-31/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=a79a8ef4a557c68f310adf5a8559a018b0a689ff44149ec25e5fdc2518ad49b5
+dist/2026-05-31/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=b4ebb1d61a066f2a382b30635e660982d9bef94ac61d183fe5462caee5530f65
+dist/2026-05-31/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=721baffda8df4216be1e5ce85ddbc288df40e467c14720e0792277f4dea34eb1
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=1155ad522b0e18f8e7cf2a1719ca9ba9b1ebe01d6351a3a38ea20f5427a14756
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=0c8269188672669fdd6e42ac032c3be94c8efad8bd71e53dc6b1518ffab170f4
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=99722c75048a61a2eb8d4907202b75c142713075ec91493c64d521299563b4da
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=0e2544760db1e15083774357a7a4138279706785ed830bb3a64f6a2d5ff3d9c7
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.gz=98112e47d93ef38f8a1014d5cde3c412645ce62b64ac05778fb21dbfb1ece284
+dist/2026-05-31/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.xz=da3771725571b276baf36574c6b0e4b540096e1a05839a995223d3a8f7f95ea5
+dist/2026-05-31/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=46aa7b65b86c6d3dcd8536cc2d136c379d2c0a15dfa51c2b30f0422d29bff6bc
+dist/2026-05-31/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=e6cb1a5444b613d8dfc83908626a90c5d7946aea5372d55937a7be11cc0139a6
+dist/2026-05-31/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=41e8276e0e379e479a037ff9992e9099cb5fb712aae538583cdf4a0c62fd0b95
+dist/2026-05-31/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=e8de286da7aea2dcfa8eff8a4d258c88b10b676639f8c6656c7a2cf82a2cb224
+dist/2026-05-31/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=cd8ee346b95773f4c85eb7ed9309d4630992cb85948f328404ebbc2bb72e653d
+dist/2026-05-31/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=e2da42681fcb37a20ab4b80d8087ea703bb0b7968f768715589380f0853608f9
+dist/2026-05-31/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=d6beb0c1e789497a86623c6762125dffc67507c22de8ab2fbcd9a30b6226e711
+dist/2026-05-31/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=cab762357d6b3ef5c1196602d3c9aac72e24babdf9effd189b3d55578adc7426
+dist/2026-05-31/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=21dcc5cb65001eec0adbadd4e9b3c94dbb8609436423b8387f410f6b6bbfa09e
+dist/2026-05-31/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=76d66710bf2222099370e31f31c7f84542329d38b4bbb0ac1d31776c20f7bdd3
+dist/2026-05-31/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=2b331926d04adb029c06496f83a64e4fa977c6567dd18db5a4c25844235f2466
+dist/2026-05-31/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=ff8070bfc0563d148dce52d167e834c58f39a7c169986db5cd95eb2e69a236c0
+dist/2026-05-31/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=6c70c4fe99121fbf83bea7c0aa20b399baed50334631ba64c3a4b65fd3be3504
+dist/2026-05-31/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=a55fe92ef4fe6cf8f38464c1b7333e30555a30dc4a7344dd27bd8d6fde8e1c01
+dist/2026-05-31/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=fb86b3dccaa12991853e6672ad8b06e06caeaa215173597d92d3c3b08f2707ab
+dist/2026-05-31/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=e9b73f4b77fd6197e22c9d78390c1ae9ed082cee61fedf8ba873f4a1ade75fd7
+dist/2026-05-31/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=8de504772cf86a4ef64b754f93d2ad37ffa7c21a4d02ab22650f29b4db0fac5d
+dist/2026-05-31/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=944f518fac7880aecc862a1fc530051339fb400eaef82570b2be800acf89b03b
+dist/2026-05-31/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=02a2218c1535bdfcf8b354d1ef282563292791e6db7b5959e289af59d708f0c0
+dist/2026-05-31/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=c9b000a2b632fc1203ae3499c59716615707dbdc14ba1a2a11ed4522af0bd10e
+dist/2026-05-31/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.gz=f667f7b4b1221a6ec54aac2ae28e4f1b2cd78043d6be9313e3b464b40b876a2c
+dist/2026-05-31/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.xz=a3243f16753ea345107f0c6b982eb67c5c1491f3d158d019e10dce0e29a1b50a
+dist/2026-05-31/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=6fc4a673875384aaa6f5e1528e88b8d2d4eb080e2d2da1e921d466f105c50b00
+dist/2026-05-31/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=8b2ccf65a543a19b818abbff38ea52284f46a0bf88fc543d6438b37613941684
+dist/2026-05-31/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=0530be30dbe6d248114ede9b8b2b5010b58239c069c772d20829d390bef4ef43
+dist/2026-05-31/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=419ee44daad1cdd35215efd019671c75641ee3227611f8a2a7804ef587211275
+dist/2026-05-31/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=9ee29dec86368d195c38e89ebca6756e3212fb2757887b0dbf761f09d4514d50
+dist/2026-05-31/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=2196928b6dd22f8b8c306628e8b9a0a34f295b4f17e776c662a5933c756e4627
+dist/2026-05-31/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=13dd2bce3ce3e44af85133d33093f2f81d13d59946e784414d63184ce7cfa550
+dist/2026-05-31/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=4b53598ea77d5de5f11ad3510d387c43af52578f0e1485a9ee8507ddccc2a953
+dist/2026-05-31/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=77cb5086f5c06fc7371ad2df69887cd4214ebd520ccf7ac29be566af282b49ee
+dist/2026-05-31/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=86589cd9d0999dde31bcfaf816c0116002e981886e80aa3d77949ba555671579
+dist/2026-05-31/rustfmt-nightly-x86_64-apple-darwin.tar.gz=28dc9324e5c3376df220c8363763c7e547d0fe69b54dfc4cb095d57643c6b4d7
+dist/2026-05-31/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e16bb80d1b2ff1c15d5bb8840a10b855b913968b693beecb6122f32738204233
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-solaris.tar.gz=05897234f66823dfb8c9e441210e0956cece4e60217831f8ac07f1a181950df7
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-solaris.tar.xz=a52ea8f5b8ea5441170663dffde68613032d07e9cc57c11a6f964dfd7f87e76a
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=ffcac357f10efecb3bf15516ae1f56034ac73005e361ee9ef4cf5091fae228fd
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=af825aecbf9ac84a0a0196341d2a0e8a154a05e4f3716e1ff3b664654af41245
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=81276ffc7a9f51deb156b8f4c15e72d2811c8a4791f4143783a63d0ac0ac75ae
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=7a3f739815996d3b48030034192dd3f09be7422d27fa3c39b756444d00bc2c40
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=aad35435802d476c5e08542e5779eaf0d2560282b36f8cf1e9128d9348992d6b
+dist/2026-05-31/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=2bd3fe07f04c8bcdf8958953e6263b282ae467618121da64d3fb30eabdd0ce89
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=815d52dcc657c8ad79800b7d178c76b8375faa7744f6e6f570db7774b9b1d886
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=035d8abfc3f81a2a3171fc446b2954cd83963cdf09b3a08fbdc4182a4b413664
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=49754b9cfb03063fd4b43109bbe1c7f1cf0e2d2583c79eac7f017bc1b8641b76
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=11c4bc5b10fcc7a80776d6781c25e8d61b0f1f0c02885a4a7b73b8b29cb699d4
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=2f5805a998ec16092dc96083053848c986a3205da189e53dd7635137df0a2128
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=adf8b6f2dd54c37fa8567b2e51aaac4a2b05d0f707f6a49166326478a4fd3cc2
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=2980b7e2db4226119e28aa1b9cb80f985d4849723406f4e98795ca47e8380995
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=820a029ad73d4fb25daed611e53519e8af98d2cdb6c1d9fbbb6cfe2474e7352e
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=d051cfa9ff99043e78beec3370db15aeb5751380cae9f8f85e95443774f3b5fa
+dist/2026-05-31/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=ae7f39dc77f115bbc1b2227f78eca146cd29da3a65ee60ea2e6c9f9375bd43f9
+dist/2026-05-31/rustc-nightly-aarch64-apple-darwin.tar.gz=f64a94faec87e7221e988c48fdb7097b8f17da78e97af32b441615cccae33976
+dist/2026-05-31/rustc-nightly-aarch64-apple-darwin.tar.xz=8fa187c933c2e135bc0cd43febbad7becfb227aae4fcfad50dbeb8b108821e8a
+dist/2026-05-31/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=669ca8966f8d3254967cf20259443448b0071a73c9be117e847a76b5afef8951
+dist/2026-05-31/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=228065e4a422c437a69556795bad4ca1cd6e432b1feadca0456ea9da50faae47
+dist/2026-05-31/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=8e58bb4c479c5e7646ba477f1bd3831c26eeaf09d00efa1e295e4c792c0ab483
+dist/2026-05-31/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=70a241124b464d0055a862529d50c59c990b05387b578857fba17a5f83113527
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=76cc8b6e3c089635cf621e5e0b63f5815c8a166b9c93eabc6ef998a896bcbc3e
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=cdb6ab3a77b8983debde49073a8e86c2312a021e4a435e2043dd86fc6e921793
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=3aff40200c2a2e400942070e9dd0515a2f6a85fcbd8526ed1288572412513aee
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=b2043b343fce0f62bd3f41a5398df2223d97b6f7c76814c72f1cf6df19c02228
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-ohos.tar.gz=3ea57a254ed6debc3f3b2af4df16ee0b85d069b36d318c4afc948d1c772d7999
+dist/2026-05-31/rustc-nightly-aarch64-unknown-linux-ohos.tar.xz=a72f39844e55c5f1555083c6901671a4a0aa6fc4e6359d118785d29fbffd7fc8
+dist/2026-05-31/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e5f00ab08d6c8b88938b351deecd445be00f588483ecb7c38af7b68675378d8d
+dist/2026-05-31/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=71de91cd3052ddc6c0ef6bdc4ba9f64d95c9772784fc81f6d70dd4179a9c7087
+dist/2026-05-31/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=877661a8fbc6a2d65f238e7704e235bf801f0dd84c6e12588d795586646da1f8
+dist/2026-05-31/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=07bce3f19daaacb4af680a8b223fc5f9737de6921de867de21e56d2248e7e43c
+dist/2026-05-31/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=68606d7a7e2c5afbd342f45044c2db1bb1183930308113d73d076c753e6795ac
+dist/2026-05-31/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=984ca8deaeb6d555a41698de83743452954cc7d55f93494ce2ca1f0f4a68f421
+dist/2026-05-31/rustc-nightly-i686-pc-windows-gnu.tar.gz=827b546af3b19b59966c7781c7c7b1549b6fe3d2dfd1327b1a40c6c9cbc109ae
+dist/2026-05-31/rustc-nightly-i686-pc-windows-gnu.tar.xz=558ace34ab751d5ac55d66e6fa2faeca61dba29cf1a3dad83e12572490030972
+dist/2026-05-31/rustc-nightly-i686-pc-windows-msvc.tar.gz=fec033ac85f13820a1c6a4e977094682431c8ab0855e9066333ef8fbe1e79f62
+dist/2026-05-31/rustc-nightly-i686-pc-windows-msvc.tar.xz=ca6a712ae1fc9a71b71a32e954bd3fa4d1397388fe891048e94e6e202d3958c7
+dist/2026-05-31/rustc-nightly-i686-unknown-linux-gnu.tar.gz=65399a15ee91b71ab984e943894ec4c3bf55797b3447e1748f2ee08d61be9c1e
+dist/2026-05-31/rustc-nightly-i686-unknown-linux-gnu.tar.xz=4230f0c6e76cae9afb70f99a1a35847e4f409d1965aedde2077fd822d2814f16
+dist/2026-05-31/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=7a9876c80fe5d1a49148b4a00770f4a68c4beb8a84c99bae2e674b59971a8deb
+dist/2026-05-31/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=4c923ea2b5cd10e8a4e59bdb5dfee38e949aa0e99daaa1873001cde017d865e7
+dist/2026-05-31/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=422791db69cd1c5ee724e7facef2911e98ff0c4d53cc1f2e6e90507990412b3e
+dist/2026-05-31/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=b54065508ea14e258d666572177eb15fa5bb52fc8c2b7690df8cf8ffcad448a9
+dist/2026-05-31/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=f9113f3a98999b382702ebb373c4b1cfd1ba1e0fff8878ebb1d5d58a3fe7fe68
+dist/2026-05-31/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=0708702033d4acf822eb394f19dc4c8cbcb46f18c6bb56e4d5fb3a421633ed6b
+dist/2026-05-31/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=02b6f3471fd4c05c92e9db51a4c8832230aacbfb8e66d71824509cfd8dfccd2f
+dist/2026-05-31/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=362ca90cf2d2cc5e106282124e2874f53436cf250b5afed6756b78d3eaa7b950
+dist/2026-05-31/rustc-nightly-powerpc64-unknown-linux-musl.tar.gz=c0fcf14b566e451a30806ddeecf14c8e52258aea425a85ffad48cdb2ec1b1136
+dist/2026-05-31/rustc-nightly-powerpc64-unknown-linux-musl.tar.xz=04ad70f3e20339221525114fe2c31ebcf21deee097b5a1ba0366ffa7c741025e
+dist/2026-05-31/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=12174c0eab7baac2c83a557f58ca74edc073f409da73c395a01a960c44f14e9b
+dist/2026-05-31/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=b4e38aea2fbfe4e950f29cfd9ec95ad8d38dfdaa2c450834278bc4f62db8017a
+dist/2026-05-31/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=682823a1d65e4206dd40c72dd9a55506e768cf7807fc9db2c2a5692f0dd6f254
+dist/2026-05-31/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=05e44578ae389d810ce384df607139a238292a49720b0ae240f26d828f5062a7
+dist/2026-05-31/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=12ed400a30df16c3301edb61a5621751e0f3fe46c6cd4a6f0d961c9822addde9
+dist/2026-05-31/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=4c23be664e79351fa9a5870da59e243cf6ed66808dbb9bba149f60820dcddb77
+dist/2026-05-31/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=5a74d07a33f032ea9a945e1b659709900fd0c2e5cdeee23de990129cecd59676
+dist/2026-05-31/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=8297d3d59dfbe395f512ccae3d3080b12be40639d15bb053ea437caa9a559caf
+dist/2026-05-31/rustc-nightly-sparcv9-sun-solaris.tar.gz=17c673f3f2ea3a3e0b6659292ad9087f821d18adf46cb7a9a0a9df3658fc94bd
+dist/2026-05-31/rustc-nightly-sparcv9-sun-solaris.tar.xz=e4582238380badead24a2bf1657cbebce9e5f40bb304ceba3f3cf25554120213
+dist/2026-05-31/rustc-nightly-x86_64-apple-darwin.tar.gz=e4c17c5fffe4a4d064744a37fc9c5bbe47ab9c2d96d08e45bac01546531ea7ef
+dist/2026-05-31/rustc-nightly-x86_64-apple-darwin.tar.xz=441b0dca028e7ed8768cba07e6892eca12df8db44a943eceb93eb9f04f99c2a7
+dist/2026-05-31/rustc-nightly-x86_64-pc-solaris.tar.gz=594af7051ba69174fc4c5d7e8a9d8ef3a2e9073fe9cc2820fd326c797ccc0307
+dist/2026-05-31/rustc-nightly-x86_64-pc-solaris.tar.xz=f95417fbc5f32792718bcb27699a38dbc70465c7d3625f390dc5cdecf6e272ed
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=29127efeb8975a5b9c9bd0608684970e0df41d21902a1b73b11d8339e73a56ff
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=3e947d6fd4e0153458b2bb155fc6e75d55a0bd57649590f054f6e34c689a06cb
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=ea52c3e92f26fbb839c2e76bdd96ad2fac757568a387ae9a13e9dd9b5303e414
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=e9a92f60037bbdbe7fc4ae4ca2d498d2f33ecb598ed4ec06890105961394c963
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=f4b3f5c239932293296b2f5ff8fd262f4457c3a274b413f63077d88f6289e196
+dist/2026-05-31/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=df15abc80b1249954fd4668f5abcd2de04e3274f24813db76de8dc673c64dd76
+dist/2026-05-31/rustc-nightly-x86_64-unknown-freebsd.tar.gz=fbee62d3d9db30b5c42afe1b6067cf8d44df8f569a43c72da9f865e6efeaff09
+dist/2026-05-31/rustc-nightly-x86_64-unknown-freebsd.tar.xz=b4941bca65b416c1f7254a7afc18c208c3bbf7b47f06c81ab83a5f323e0e97ce
+dist/2026-05-31/rustc-nightly-x86_64-unknown-illumos.tar.gz=214a91ce3ff3eaf62d05b60c7c43fd35ad817aa526a82e3e4d3943cc1a7b396a
+dist/2026-05-31/rustc-nightly-x86_64-unknown-illumos.tar.xz=bcde414eeb270fd1ce7bdcbafaa6aa3ce94edca2f7ac0c914433d67b9033eeb5
+dist/2026-05-31/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=c57dd5dc0d0bc85d59dca541f20cf04250e9b2f210550ce1425e97b401714131
+dist/2026-05-31/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=9e6ac5e346606f4245930ff868e187d339a1ad5c2e60557bfacdd25a51689bf4
+dist/2026-05-31/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b57e6d4aee9066c2446907b3e76fecd406367424bb8148b3f3fd0a7b524ef0c8
+dist/2026-05-31/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=01ed8e2e055a2c458aab74da6b1a7fbaba671127b56cc27448ef6b449eaf21a0
+dist/2026-05-31/rustc-nightly-x86_64-unknown-netbsd.tar.gz=857213a5e914b564999ee822f89d4e7001647010bde5965ea0acd9176a5c139a
+dist/2026-05-31/rustc-nightly-x86_64-unknown-netbsd.tar.xz=d03bcfb657873fadca8dbcfb4992eb3d493ee03b870d48ab8a56acb567fe6e7e
+dist/2026-05-31/rust-nightly-aarch64-pc-windows-gnullvm.msi=084b4cda2fa73ed97c3590391b11cf4c08a6c2863df9f7caacd1acb43641f61d
+dist/2026-05-31/rust-nightly-aarch64-pc-windows-msvc.msi=c1fc78a40bcd8fc5c1ea96bd7ccba626c84b753c41073af646c058053d4d04ac
+dist/2026-05-31/rust-nightly-i686-pc-windows-gnu.msi=9a904617784e8fa219350b2612f6e7d190ab40b95f5d5cb4acf293b10a2e86f2
+dist/2026-05-31/rust-nightly-i686-pc-windows-msvc.msi=e5044302a4e2e0ac33027478c60d0620364603820c18f0f5d1cef9750e354727
+dist/2026-05-31/rust-nightly-x86_64-pc-windows-gnu.msi=b43cf69de39e26aba92531dcdb5a97c567ed68ac91f0852a657073ddff4eec94
+dist/2026-05-31/rust-nightly-x86_64-pc-windows-gnullvm.msi=33476b08c55dddada9c80c82320dfde599248882d42c9c2e10fbb8d5aa207b9d
+dist/2026-05-31/rust-nightly-x86_64-pc-windows-msvc.msi=4a1534f3e442d0f0e305a793794981c75be08817578ad9a7231f7bf62b07ea5b
+dist/2026-05-31/rust-nightly-aarch64-apple-darwin.pkg=454b5dba457745e975e2bf128e9302f4724b7b0a20731feb7071a2858e557ad1
+dist/2026-05-31/rust-nightly-x86_64-apple-darwin.pkg=fcb32eab11dd7fd0afd5dc84e38e12fda8e364d154c7768507af3a3566b0dc4a
+dist/2026-05-31/rustc-nightly-src.tar.gz=c1bdee6cc2db9b7f620ba00c00218b9766080064ac4b7cf9ca92fc05450b8b90
+dist/2026-05-31/rustc-nightly-src.tar.xz=7ff0812c7e90b03a1dcc5ae87722d71e9295d4505f33cdb1f17f5487f2320c95
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 5494d3f..0836caa 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -705,7 +705,7 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
         "src/etc/gdb_load_rust_pretty_printers.py",
         "src/etc/gdb_lookup.py",
         "src/etc/gdb_providers.py",
-        "src/etc/lldb_batchmode.py",
+        "src/etc/lldb_batchmode",
         "src/etc/lldb_lookup.py",
         "src/etc/lldb_providers.py",
     ];
diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs
index 0d41c29..be2430f 100644
--- a/src/tools/compiletest/src/runtest/assembly.rs
+++ b/src/tools/compiletest/src/runtest/assembly.rs
@@ -23,7 +23,7 @@ pub(super) fn run_assembly_test(&self) {
 
     fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) {
         // This works with both `--emit asm` (as default output name for the assembly)
-        // and `ptx-linker` because the latter can write output at requested location.
+        // and `llvm-bitcode-linker` because the latter can write output at requested location.
         let output_path = self.output_base_name().with_extension("s");
         let input_file = &self.testpaths.file;
 
@@ -31,7 +31,6 @@ fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) {
         let emit = match self.props.assembly_output.as_deref() {
             Some("emit-asm") => Emit::Asm,
             Some("bpf-linker") => Emit::LinkArgsAsm,
-            Some("ptx-linker") => Emit::None, // No extra flags needed.
             Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")),
             None => self.fatal("missing 'assembly-output' directive"),
         };
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index f2f13bc..b666c73 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -1,6 +1,5 @@
 use std::ffi::{OsStr, OsString};
-use std::fs::File;
-use std::io::{BufRead, BufReader, Read};
+use std::io::{BufRead, BufReader};
 use std::process::{Command, Output, Stdio};
 
 use camino::Utf8Path;
@@ -260,6 +259,19 @@ fn run_debuginfo_gdb_test(&self) {
                             "add-auto-load-safe-path {}\n",
                             self.output_base_dir().as_str().replace(r"\", r"\\")
                         ));
+
+                        // GDB visualizer scripts aren't properly embedded on `*-windows-gnu`
+                        // at the moment (see: issue #156687), so we need to load them in
+                        // manually.
+                        #[cfg(target_os = "windows")]
+                        {
+                            script_str.push_str(&format!(
+                                "source {}\n",
+                                self.config
+                                    .src_root
+                                    .join("src/etc/gdb_load_rust_pretty_printers.py")
+                            ));
+                        }
                     }
                 }
                 _ => {
@@ -407,9 +419,7 @@ fn run_debuginfo_lldb_test(&self) {
             "command script import {}/lldb_lookup.py\n",
             rust_pp_module_abs_path
         ));
-        File::open(rust_pp_module_abs_path.join("lldb_commands"))
-            .and_then(|mut file| file.read_to_string(&mut script_str))
-            .expect("Failed to read lldb_commands");
+        script_str.push_str("script print(lldb_lookup.FEATURE_FLAGS)\n");
 
         // Set breakpoints on every line that contains the string "#break"
         let source_file_name = self.testpaths.file.file_name().unwrap();
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index e07a078..e7455fc 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -78,6 +78,20 @@
     ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
                                     "core/slice::sort_by_key", "core\\slice::sort_by_key",
                                     "#method.sort_by_cached_key"]),
+    ("core/io/struct.IoSlice.html", &[
+        "#method.to_ascii_uppercase",
+        "#method.to_ascii_lowercase",
+        "core/io/slice::sort_by_key",
+        "core\\io\\slice::sort_by_key",
+        "#method.sort_by_cached_key"
+    ]),
+    ("core/io/struct.IoSliceMut.html", &[
+        "#method.to_ascii_uppercase",
+        "#method.to_ascii_lowercase",
+        "core/io/slice::sort_by_key",
+        "core\\io\\slice::sort_by_key",
+        "#method.sort_by_cached_key"
+    ]),
 ];
 
 #[rustfmt::skip]
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 14978c2..73a6d90 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -155,6 +155,18 @@
           cd ../rust # ./x does not seem to like being invoked from elsewhere
           ./x check miri
 
+  # This job is intentionally separate from `test` so that Priroda can be
+  # developed as a separate crate inside the Miri repository for now.
+  priroda-build:
+    name: Priroda
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v6
+      - uses: ./.github/workflows/setup
+      - name: build Priroda
+        working-directory: priroda
+        run: cargo build --locked
+
   coverage:
     name: coverage report
     runs-on: ubuntu-latest
@@ -168,7 +180,7 @@
   # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
   # And they should be added below in `cron-fail-notify` as well.
   conclusion:
-    needs: [test, style, bootstrap, coverage]
+    needs: [test, style, bootstrap, coverage, priroda-build]
     # We need to ensure this job does *not* get skipped if its dependencies fail,
     # because a skipped job is considered a success by GitHub. So we have to
     # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
@@ -252,7 +264,7 @@
   cron-fail-notify:
     name: cronjob failure notification
     runs-on: ubuntu-latest
-    needs: [test, style, bootstrap, coverage]
+    needs: [test, style, bootstrap, coverage, priroda-build]
     if: ${{ github.event_name == 'schedule' && failure() }}
     steps:
       # Send a Zulip notification
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 3d0716a..550a2e2 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -517,6 +517,10 @@
   track interior mutable data on the level of references instead of on the
   byte-level as is done by default.  Therefore, with this flag, Tree
   Borrows will be more permissive.
+* `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness` disables uniqueness assumptions for
+  `Box<T, A>` where `A` is not `Global`. The exact aliasing rules for such custom allocators are
+  still up in the air, and by default Miri is conservative and rejects some allocator
+  implementations that incur relevant aliasing between the allocation and the allocator.
 * `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
   `4` is default for most targets. This value should always be a power of 2 and nonzero.
 
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index a87c6fa..f7c0b73 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -150,11 +150,10 @@
   i686-unknown-linux-gnu)
     # Host
     MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
-    # Fully, but not officially, supported tier 2
+    # Not officially supported tier 2
     MANY_SEEDS=16 TEST_TARGET=aarch64-linux-android run_tests
-    # Partially supported targets (tier 2)
-    BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator
-    UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
+    MANY_SEEDS=16 TEST_TARGET=loongarch64-unknown-linux-gnu run_tests
+    # Partially supported targets (no_std, tier 2)
     TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
     TEST_TARGET=thumbv7em-none-eabihf  run_tests_minimal no_std
     ;;
diff --git a/src/tools/miri/priroda/Cargo.lock b/src/tools/miri/priroda/Cargo.lock
new file mode 100644
index 0000000..25c97f8
--- /dev/null
+++ b/src/tools/miri/priroda/Cargo.lock
@@ -0,0 +1,1260 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aes"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66bd29a732b644c0431c6140f370d097879203d79b80c94a6747ba0872adaef8"
+dependencies = [
+ "cipher",
+ "cpubits",
+ "cpufeatures",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
+
+[[package]]
+name = "bumpalo"
+version = "3.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
+
+[[package]]
+name = "capstone"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f442ae0f2f3f1b923334b4a5386c95c69c1cfa072bafa23d6fae6d9682eb1dd4"
+dependencies = [
+ "capstone-sys",
+ "static_assertions",
+]
+
+[[package]]
+name = "capstone-sys"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4e8087cab6731295f5a2a2bd82989ba4f41d3a428aab2e7c98d8f4db38aac05"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
+[[package]]
+name = "chacha20"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "rand_core 0.10.1",
+]
+
+[[package]]
+name = "chrono"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "chrono-tz"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
+dependencies = [
+ "chrono",
+ "phf",
+]
+
+[[package]]
+name = "cipher"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "cpubits"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
+
+[[package]]
+name = "cpufeatures"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "crypto-common"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710"
+dependencies = [
+ "hybrid-array",
+]
+
+[[package]]
+name = "directories"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "futures-core"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
+
+[[package]]
+name = "futures-task"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
+
+[[package]]
+name = "futures-util"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "slab",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi 5.3.0",
+ "wasip2",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi 6.0.0",
+ "rand_core 0.10.1",
+ "wasip2",
+ "wasip3",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hybrid-array"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.17.1",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "inout"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
+dependencies = [
+ "hybrid-array",
+]
+
+[[package]]
+name = "ipc-channel"
+version = "0.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180"
+dependencies = [
+ "bincode",
+ "crossbeam-channel",
+ "fnv",
+ "libc",
+ "mio",
+ "rand 0.9.4",
+ "serde",
+ "tempfile",
+ "uuid",
+ "windows",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
+name = "js-sys"
+version = "0.3.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
+dependencies = [
+ "cfg-if",
+ "futures-util",
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
+name = "libc"
+version = "0.2.186"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+
+[[package]]
+name = "libffi"
+version = "5.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0498fe5655f857803e156523e644dcdcdc3b3c7edda42ea2afdae2e09b2db87b"
+dependencies = [
+ "libc",
+ "libffi-sys",
+]
+
+[[package]]
+name = "libffi-sys"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d4f1d4ce15091955144350b75db16a96d4a63728500122706fb4d29a26afbb"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "libloading"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
+dependencies = [
+ "cfg-if",
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "libredox"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "measureme"
+version = "12.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
+dependencies = [
+ "log",
+ "memmap2",
+ "parking_lot",
+ "perf-event-open-sys",
+ "rustc-hash",
+ "smallvec",
+]
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "memmap2"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "mio"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "miri"
+version = "0.1.0"
+dependencies = [
+ "aes",
+ "bitflags",
+ "capstone",
+ "chrono",
+ "chrono-tz",
+ "directories",
+ "getrandom 0.4.2",
+ "ipc-channel",
+ "libc",
+ "libffi",
+ "libloading",
+ "measureme",
+ "mio",
+ "nix",
+ "rand 0.10.1",
+ "serde",
+ "smallvec",
+]
+
+[[package]]
+name = "nix"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "option-ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "perf-event-open-sys"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b29be2ba35c12c6939f6bc73187f728bba82c3c062ecdc5fa90ea739282a1f58"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "phf"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
+dependencies = [
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "priroda"
+version = "0.1.0"
+dependencies = [
+ "miri",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "r-efi"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
+
+[[package]]
+name = "rand"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
+dependencies = [
+ "rand_chacha",
+ "rand_core 0.9.5",
+]
+
+[[package]]
+name = "rand"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
+dependencies = [
+ "chacha20",
+ "getrandom 0.4.2",
+ "rand_core 0.10.1",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.5",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
+dependencies = [
+ "getrandom 0.2.17",
+ "libredox",
+ "thiserror",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustix"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "siphasher"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
+
+[[package]]
+name = "slab"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
+dependencies = [
+ "fastrand",
+ "getrandom 0.4.2",
+ "once_cell",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "typenum"
+version = "1.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "uuid"
+version = "1.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
+dependencies = [
+ "getrandom 0.4.2",
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.3+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
+dependencies = [
+ "wit-bindgen 0.57.1",
+]
+
+[[package]]
+name = "wasip3"
+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+dependencies = [
+ "wit-bindgen 0.51.0",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.121"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.121"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.121"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.121"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "wasm-encoder"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
+dependencies = [
+ "bitflags",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "windows"
+version = "0.61.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
+dependencies = [
+ "windows-collections",
+ "windows-core",
+ "windows-future",
+ "windows-link 0.1.3",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
+dependencies = [
+ "windows-core",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link 0.1.3",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-future"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
+dependencies = [
+ "windows-core",
+ "windows-link 0.1.3",
+ "windows-threading",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-numerics"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
+dependencies = [
+ "windows-core",
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+dependencies = [
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+dependencies = [
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "windows-threading"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
+dependencies = [
+ "windows-link 0.1.3",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+dependencies = [
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.57.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/src/tools/miri/priroda/Cargo.toml b/src/tools/miri/priroda/Cargo.toml
new file mode 100644
index 0000000..084773f
--- /dev/null
+++ b/src/tools/miri/priroda/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+description = "Debugger for Rust MIR."
+license = "MIT OR Apache-2.0"
+name = "priroda"
+repository = "https://github.com/rust-lang/miri"
+version = "0.1.0"
+edition = "2024"
+
+
+[[bin]]
+name = "priroda"
+path = "src/main.rs"
+doctest = false      # and no doc tests
+
+[dependencies]
+miri = { path = ".." }
+
+[package.metadata.rust-analyzer]
+rustc_private = true
diff --git a/src/tools/miri/priroda/README.md b/src/tools/miri/priroda/README.md
new file mode 100644
index 0000000..246fa93
--- /dev/null
+++ b/src/tools/miri/priroda/README.md
@@ -0,0 +1,37 @@
+# Priroda
+
+Priroda is a step-through debugger for Rust programs running under
+Miri.
+
+Current focus:
+
+- simple CLI prototype
+- single-threaded stepping with Miri's interpreter
+- commands: empty Enter, `s`, or `step`
+
+## Setup
+
+From `miri/`, install the pinned toolchain and the local `cargo-miri`
+command:
+
+```sh
+./miri toolchain
+./miri install
+```
+
+Then build the Miri sysroot and export it for Priroda:
+
+```sh
+cargo +miri miri setup
+export MIRI_SYSROOT="$(cargo +miri miri setup --print-sysroot)"
+```
+
+## Run
+
+Priroda currently reads `MIRI_SYSROOT` directly. After setup:
+
+```sh
+cargo run -p priroda -- tests/pass/empty_main.rs
+```
+
+At the prompt, press Enter or type `s` / `step`.
diff --git a/src/tools/miri/priroda/rust-toolchain.toml b/src/tools/miri/priroda/rust-toolchain.toml
new file mode 100644
index 0000000..c5d0b97
--- /dev/null
+++ b/src/tools/miri/priroda/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "miri"
diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs
new file mode 100644
index 0000000..775f240
--- /dev/null
+++ b/src/tools/miri/priroda/src/main.rs
@@ -0,0 +1,147 @@
+#![feature(rustc_private)]
+
+extern crate miri;
+extern crate rustc_codegen_ssa;
+extern crate rustc_data_structures;
+extern crate rustc_driver;
+extern crate rustc_hir;
+extern crate rustc_hir_analysis;
+extern crate rustc_interface;
+extern crate rustc_log;
+extern crate rustc_middle;
+extern crate rustc_session;
+
+use std::io::{self, Write};
+
+use miri::*;
+use rustc_driver::Compilation;
+use rustc_hir::attrs::CrateType;
+use rustc_interface::interface;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::EarlyDiagCtxt;
+use rustc_session::config::ErrorOutputType;
+fn find_sysroot() -> String {
+    std::env::var("MIRI_SYSROOT")
+        .expect("set MIRI_SYSROOT to the path from `cargo miri setup --print-sysroot`")
+}
+
+fn main() {
+    let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
+    rustc_driver::init_rustc_env_logger(&early_dcx);
+
+    let mut args: Vec<String> = std::env::args().collect();
+
+    args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string));
+
+    let sysroot_flag = String::from("--sysroot");
+    if !args.contains(&sysroot_flag) {
+        args.push(sysroot_flag);
+        args.push(find_sysroot());
+    }
+    //TODO: handle the same `-Z` flags that Miri accepts.
+    rustc_driver::run_compiler(&args, &mut PrirodaCompilerCalls::new());
+}
+
+struct PrirodaCompilerCalls;
+
+impl PrirodaCompilerCalls {
+    fn new() -> Self {
+        Self
+    }
+}
+
+impl rustc_driver::Callbacks for PrirodaCompilerCalls {
+    fn after_analysis<'tcx>(&mut self, _: &interface::Compiler, tcx: TyCtxt<'tcx>) -> Compilation {
+        tcx.dcx().emit_stashed_diagnostics();
+        tcx.dcx().abort_if_errors();
+
+        if !tcx.crate_types().contains(&CrateType::Executable) {
+            //TODO: support non-bin crates by listing functions and letting users call them with manually entered arguments.
+            tcx.dcx().fatal("priroda only makes sense on bin crates");
+        }
+
+        let ecx = create_ecx(tcx);
+
+        let mut session = PrirodaContext::new(ecx);
+        let result = run_cli_loop(&mut session);
+
+        match result.report_err() {
+            Ok(()) => {}
+            Err(err) =>
+                if let Some((return_code, _leak_check)) = report_result(&session.ecx, err) {
+                    //TODO: print the evaluated program's exit code and return to the debugger prompt instead of exiting Priroda.
+                    if return_code != 0 {
+                        std::process::exit(return_code);
+                    }
+                },
+        }
+
+        Compilation::Stop
+    }
+}
+
+fn create_ecx<'tcx>(tcx: TyCtxt<'tcx>) -> MiriInterpCx<'tcx> {
+    let (entry_id, entry_type) = miri::entry_fn(tcx);
+    let config = MiriConfig::default();
+    miri::create_ecx(tcx, entry_id, entry_type, &config, None).unwrap()
+}
+
+pub struct PrirodaContext<'tcx> {
+    ecx: MiriInterpCx<'tcx>,
+}
+
+impl<'tcx> PrirodaContext<'tcx> {
+    fn new(ecx: MiriInterpCx<'tcx>) -> Self {
+        Self { ecx }
+    }
+
+    // TODO: return a StepResult enum once we distinguish breakpoint stops,
+    // program exit, and other debugger states.
+    pub fn step(&mut self) -> InterpResult<'tcx> {
+        self.ecx.miri_step()
+    }
+
+    pub fn print_location(&self) {
+        let span = self.ecx.machine.current_user_relevant_span();
+        let location = self.ecx.tcx.sess.source_map().span_to_diagnostic_string(span);
+        // TODO: skip noisy std/runtime spans and avoid printing `no-location`
+        // once the basic command loop is solid.
+        println!("{location}");
+        io::stdout().flush().unwrap();
+    }
+    fn run_command(&mut self, command: SessionCommand) -> InterpResult<'tcx> {
+        match command {
+            SessionCommand::Step => self.step(),
+        }
+    }
+}
+
+enum SessionCommand {
+    Step,
+}
+
+fn parse_command(input: &str) -> Option<SessionCommand> {
+    match input.trim() {
+        "" | "s" | "step" => Some(SessionCommand::Step),
+        _ => None,
+    }
+}
+
+fn run_cli_loop<'tcx>(session: &mut PrirodaContext<'tcx>) -> InterpResult<'tcx> {
+    loop {
+        print!("(priroda) ");
+        io::stdout().flush().unwrap();
+
+        let mut input = String::new();
+        // TODO: handle EOF explicitly so scripted input can stop the CLI instead
+        // of being treated like an empty Enter step.
+        io::stdin().read_line(&mut input).unwrap();
+
+        if let Some(command) = parse_command(&input) {
+            session.run_command(command)?;
+            session.print_location();
+        } else {
+            println!("no command");
+        }
+    }
+}
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 4a823e1..aaeb424 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-1f8e04d34ab0c1fd9574840aa6db670e41593bfb
+bef8e620f19adbfd1530e916ab8caa296ef9c3ee
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index ba66234..442f96f 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -12,12 +12,10 @@
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_hir;
-extern crate rustc_hir_analysis;
 extern crate rustc_interface;
 extern crate rustc_log;
 extern crate rustc_middle;
 extern crate rustc_session;
-extern crate rustc_span;
 
 /// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs
 /// and https://github.com/rust-lang/rust/pull/146627 for why we need this.
@@ -44,15 +42,13 @@
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use miri::{
-    BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, MiriEntryFnType,
-    ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode,
+    BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, ProvenanceMode,
+    TreeBorrowsParams, ValidationMode, entry_fn, run_genmc_mode,
 };
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::sync::{self, DynSync};
 use rustc_driver::Compilation;
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::{self as hir, Node};
-use rustc_hir_analysis::check::check_function_signature;
 use rustc_interface::interface::Config;
 use rustc_interface::util::DummyCodegenBackend;
 use rustc_log::tracing::debug;
@@ -61,11 +57,9 @@
     ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
 };
 use rustc_middle::query::LocalCrate;
-use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{CrateType, ErrorOutputType, OptLevel};
 use rustc_session::{EarlyDiagCtxt, Session};
-use rustc_span::def_id::DefId;
 
 use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers};
 
@@ -85,53 +79,6 @@ fn new(miri_config: MiriConfig, many_seeds: Option<ManySeedsConfig>) -> Self {
     }
 }
 
-fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
-    if let Some((def_id, entry_type)) = tcx.entry_fn(()) {
-        return (def_id, MiriEntryFnType::Rustc(entry_type));
-    }
-    // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point.
-    let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
-        if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
-    });
-    if let Some(ExportedSymbol::NonGeneric(id)) = sym {
-        let start_def_id = id.expect_local();
-        let start_span = tcx.def_span(start_def_id);
-
-        let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi(
-            [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
-            tcx.types.isize,
-        ));
-
-        let correct_func_sig = check_function_signature(
-            tcx,
-            ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc),
-            *id,
-            expected_sig,
-        )
-        .is_ok();
-
-        if correct_func_sig {
-            (*id, MiriEntryFnType::MiriStart)
-        } else {
-            tcx.dcx().fatal(
-                "`miri_start` must have the following signature:\n\
-                fn miri_start(argc: isize, argv: *const *const u8) -> isize",
-            );
-        }
-    } else {
-        tcx.dcx().fatal(
-            "Miri can only run programs that have a main function.\n\
-            Alternatively, you can export a `miri_start` function:\n\
-            \n\
-            #[cfg(miri)]\n\
-            #[unsafe(no_mangle)]\n\
-            fn miri_start(argc: isize, argv: *const *const u8) -> isize {\
-            \n    // Call the actual start function that your project implements, based on your target's conventions.\n\
-            }"
-        );
-    }
-}
-
 fn run_many_seeds(
     many_seeds: ManySeedsConfig,
     eval_entry_once: impl Fn(u64) -> Result<(), NonZeroI32> + DynSync,
@@ -526,6 +473,8 @@ fn main() -> ExitCode {
                 Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams {
                     precise_interior_mut: true,
                     implicit_writes: false,
+                    // We default this to "unique" for now to keep the design space open.
+                    box_custom_allocator_unique: true,
                 }));
         } else if arg == "-Zmiri-tree-borrows-no-precise-interior-mut" {
             match &mut miri_config.borrow_tracker {
@@ -547,6 +496,16 @@ fn main() -> ExitCode {
                         "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-implicit-writes`"
                     ),
             };
+        } else if arg == "-Zmiri-tree-borrows-relax-custom-allocator-uniqueness" {
+            match &mut miri_config.borrow_tracker {
+                Some(BorrowTrackerMethod::TreeBorrows(params)) => {
+                    params.box_custom_allocator_unique = false;
+                }
+                _ =>
+                    fatal_error!(
+                        "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness`"
+                    ),
+            };
         } else if arg == "-Zmiri-disable-data-race-detector" {
             miri_config.data_race_detector = false;
             miri_config.weak_memory_emulation = false;
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index f986444..f11799e 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -226,9 +226,12 @@ pub enum BorrowTrackerMethod {
 /// Parameters that Tree Borrows can take.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub struct TreeBorrowsParams {
+    /// Controls whether we track `UnsafeCell` with byte precision.
     pub precise_interior_mut: bool,
     /// Controls whether `&mut` function arguments are immediately activated with an implicit write.
     pub implicit_writes: bool,
+    /// Controls whether `Box` with custom allocator is considered unique.
+    pub box_custom_allocator_unique: bool,
 }
 
 impl BorrowTrackerMethod {
@@ -236,6 +239,7 @@ pub fn instantiate_global_state(self, config: &MiriConfig) -> GlobalState {
         RefCell::new(GlobalStateInner::new(self, config.tracked_pointer_tags.clone()))
     }
 
+    #[track_caller]
     pub fn get_tree_borrows_params(self) -> TreeBorrowsParams {
         match self {
             BorrowTrackerMethod::TreeBorrows(params) => params,
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index beca399..4831198 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -869,12 +869,7 @@ fn sb_retag_ptr_value(
             RetagMode::None => return interp_ok(None), // no retagging
         };
         let new_perm = if ty.is_box() {
-            if ty.is_box_global(*this.tcx) {
-                NewPermission::from_box_ty(val.layout.ty, mode, this)
-            } else {
-                // Boxes with local allocator are not retagged.
-                return interp_ok(None);
-            }
+            NewPermission::from_box_ty(val.layout.ty, mode, this)
         } else {
             NewPermission::from_ref_ty(val.layout.ty, mode, this)
         };
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 4160576..efeab43 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -127,7 +127,7 @@ fn new(
         pointee: Ty<'tcx>,
         ref_mutability: Option<Mutability>,
         mode: RetagMode,
-        cx: &crate::MiriInterpCx<'tcx>,
+        cx: &MiriInterpCx<'tcx>,
     ) -> Option<Self> {
         if mode == RetagMode::None {
             return None;
@@ -143,15 +143,7 @@ fn new(
         // `#[rustc_no_writable]` attribute. For performance reasons, only performs the lookup if
         // is_protected is true as implicit writes are only performed for protected references.
         let implicit_writes_enabled = is_protected && {
-            let implicit_writes = cx
-                .machine
-                .borrow_tracker
-                .as_ref()
-                .unwrap()
-                .borrow()
-                .borrow_tracker_method
-                .get_tree_borrows_params()
-                .implicit_writes;
+            let implicit_writes = cx.get_tree_borrows_params().implicit_writes;
             let def_id = cx.frame().instance().def_id();
             implicit_writes && !find_attr!(cx.tcx, def_id, RustcNoWritable)
         };
@@ -234,6 +226,14 @@ enum Part {
 /// the implementation of NewPermission.
 impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    #[track_caller]
+    #[inline]
+    fn get_tree_borrows_params(&self) -> TreeBorrowsParams {
+        let this = self.eval_context_ref();
+        let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap().borrow();
+        borrow_tracker.borrow_tracker_method.get_tree_borrows_params()
+    }
+
     /// Returns the provenance that should be used henceforth.
     fn tb_reborrow(
         &mut self,
@@ -326,15 +326,7 @@ fn tb_reborrow(
         }
 
         let protected = new_perm.protector.is_some();
-        let precise_interior_mut = this
-            .machine
-            .borrow_tracker
-            .as_mut()
-            .unwrap()
-            .get_mut()
-            .borrow_tracker_method
-            .get_tree_borrows_params()
-            .precise_interior_mut;
+        let precise_interior_mut = this.get_tree_borrows_params().precise_interior_mut;
 
         // Compute initial "inside" permissions.
         let loc_state = |frozen: bool| -> LocationState {
@@ -487,22 +479,25 @@ fn tb_retag_ptr_value(
     ) -> InterpResult<'tcx, Option<ImmTy<'tcx>>> {
         let this = self.eval_context_mut();
         let new_perm = match *ty.kind() {
-            _ if ty.is_box_global(*this.tcx) => {
-                // The `None` marks this as a Box.
-                NewPermission::new(ty.builtin_deref(true).unwrap(), None, mode, this)
-            }
             ty::Ref(_, pointee, mutability) =>
                 NewPermission::new(pointee, Some(mutability), mode, this),
+            _ if ty.is_box() => {
+                let box_custom_allocator_unique =
+                    this.get_tree_borrows_params().box_custom_allocator_unique;
+                if box_custom_allocator_unique || ty.is_box_global(*this.tcx) {
+                    // The `None` marks this as a Box.
+                    NewPermission::new(ty.builtin_deref(true).unwrap(), None, mode, this)
+                } else {
+                    // No retagging for boxes with custom allocators.
+                    None
+                }
+            }
 
             ty::RawPtr(..) => {
                 assert!(mode == RetagMode::Raw);
                 // We don't give new tags to raw pointers.
                 None
             }
-            _ if ty.is_box() => {
-                // No retagging for boxes with local allocators.
-                None
-            }
             _ => panic!("tb_retag_ptr_value: invalid type {ty}"),
         };
         if let Some(new_perm) = new_perm {
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index b730b9d..7d9001e 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -856,6 +856,23 @@ fn unblock_expired_deadlines(&mut self) -> InterpResult<'tcx, Option<Duration>>
 // Public interface to thread management.
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    /// Public because this is used by Priroda.
+    fn miri_step(&mut self) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        if !this.step()? {
+            // See if this thread can do something else.
+            match this.run_on_stack_empty()? {
+                Poll::Pending => {} //keep going
+                Poll::Ready(()) => {
+                    this.terminate_active_thread(TlsAllocAction::Deallocate)?;
+                }
+            }
+        }
+
+        interp_ok(())
+    }
+
     #[inline]
     fn thread_id_try_from(&self, id: impl TryInto<u32>) -> Result<ThreadId, ThreadLookupError> {
         self.eval_context_ref().machine.threads.thread_id_try_from(id)
@@ -1289,14 +1306,7 @@ fn run_threads(&mut self) -> InterpResult<'tcx, !> {
             }
             match this.schedule()? {
                 SchedulingAction::ExecuteStep => {
-                    if !this.step()? {
-                        // See if this thread can do something else.
-                        match this.run_on_stack_empty()? {
-                            Poll::Pending => {} // keep going
-                            Poll::Ready(()) =>
-                                this.terminate_active_thread(TlsAllocAction::Deallocate)?,
-                        }
-                    }
+                    this.miri_step()?;
                 }
                 SchedulingAction::SleepAndWaitForIo(duration) => {
                     if this.machine.communicate() {
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index c9b2b76..19b6ff7 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -12,7 +12,10 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::FatalErrorMarker;
 use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir_analysis::check::check_function_signature;
+use rustc_middle::middle::exported_symbols::ExportedSymbol;
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutCx};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::EntryFnType;
@@ -31,6 +34,56 @@ pub enum MiriEntryFnType {
     Rustc(EntryFnType),
 }
 
+/// Finds the entry point Miri should execute.
+///
+/// Public because this is used by Priroda.
+pub fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
+    if let Some((def_id, entry_type)) = tcx.entry_fn(()) {
+        return (def_id, MiriEntryFnType::Rustc(entry_type));
+    }
+    // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point.
+    let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
+        if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
+    });
+    if let Some(ExportedSymbol::NonGeneric(id)) = sym {
+        let start_def_id = id.expect_local();
+        let start_span = tcx.def_span(start_def_id);
+
+        let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi(
+            [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+            tcx.types.isize,
+        ));
+
+        let correct_func_sig = check_function_signature(
+            tcx,
+            ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc),
+            *id,
+            expected_sig,
+        )
+        .is_ok();
+
+        if correct_func_sig {
+            (*id, MiriEntryFnType::MiriStart)
+        } else {
+            tcx.dcx().fatal(
+                "`miri_start` must have the following signature:\n\
+                fn miri_start(argc: isize, argv: *const *const u8) -> isize",
+            );
+        }
+    } else {
+        tcx.dcx().fatal(
+            "Miri can only run programs that have a main function.\n\
+            Alternatively, you can export a `miri_start` function:\n\
+            \n\
+            #[cfg(miri)]\n\
+            #[unsafe(no_mangle)]\n\
+            fn miri_start(argc: isize, argv: *const *const u8) -> isize {\
+            \n    // Call the actual start function that your project implements, based on your target's conventions.\n\
+            }"
+        );
+    }
+}
+
 /// When the main thread would exit, we will yield to any other thread that is ready to execute.
 /// But we must only do that a finite number of times, or a background thread running `loop {}`
 /// will hang the program.
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 160f31d..9b5573b 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -9,6 +9,7 @@
     feature(abort_unwind)
 )]
 #![feature(rustc_private)]
+#![feature(dirfd)]
 #![feature(f16)]
 #![feature(float_gamma)]
 #![feature(float_erf)]
@@ -69,6 +70,7 @@
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
+extern crate rustc_hir_analysis;
 extern crate rustc_index;
 extern crate rustc_log;
 extern crate rustc_middle;
@@ -146,7 +148,7 @@ pub mod native_lib {
 pub use crate::concurrency::sync::{CondvarRef, EvalContextExt as _, MutexRef, RwLockRef};
 pub use crate::concurrency::thread::{
     BlockReason, DynUnblockCallback, EvalContextExt as _, StackEmptyCallback, ThreadId,
-    ThreadManager, UnblockKind,
+    ThreadManager, TlsAllocAction, UnblockKind,
 };
 pub use crate::concurrency::{GenmcConfig, GenmcCtx, run_genmc_mode};
 pub use crate::data_structures::dedup_range_map::DedupRangeMap;
@@ -154,7 +156,7 @@ pub mod native_lib {
 pub use crate::diagnostics::{
     EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_result,
 };
-pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, eval_entry};
+pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, entry_fn, eval_entry};
 pub use crate::helpers::{EvalContextExt as _, ToU64 as _, ToUsize as _};
 pub use crate::intrinsics::EvalContextExt as _;
 pub use crate::machine::{
diff --git a/src/tools/miri/src/shims/aarch64.rs b/src/tools/miri/src/shims/aarch64.rs
index 6a914d5..deab856 100644
--- a/src/tools/miri/src/shims/aarch64.rs
+++ b/src/tools/miri/src/shims/aarch64.rs
@@ -196,10 +196,9 @@ fn emulate_aarch64_intrinsic(
                     _ => unreachable!(),
                 };
 
-                let [left, right] =
-                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
-                let left = this.read_scalar(left)?;
-                let right = this.read_scalar(right)?;
+                let [crc, data] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
+                let crc = this.read_scalar(crc)?;
+                let data = this.read_scalar(data)?;
 
                 // The CRC accumulator is always u32. The data argument is u32 for
                 // b/h/w variants and u64 for the x variant, per the LLVM intrinsic
@@ -207,13 +206,36 @@ fn emulate_aarch64_intrinsic(
                 // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsAArch64.td
                 // If the higher bits are non-zero, `compute_crc32` will panic. We should probably
                 // raise a proper error instead, but outside stdarch nobody can trigger this anyway.
-                let crc = left.to_u32()?;
-                let data =
-                    if bit_size == 64 { right.to_u64()? } else { u64::from(right.to_u32()?) };
+                let crc = crc.to_u32()?;
+                let data = if bit_size == 64 { data.to_u64()? } else { u64::from(data.to_u32()?) };
 
                 let result = compute_crc32(crc, data, bit_size, polynomial);
                 this.write_scalar(Scalar::from_u32(result), dest)?;
             }
+            // Polynomial multiply long (64-bit x 64-bit -> 128-bit).
+            //
+            // This is the same as "carryless" multiplication, see
+            // <https://en.wikipedia.org/wiki/Carry-less_product#Multiplication_of_polynomials>.
+            //
+            // Used to implement the vmull_p64 and vmull_high_p64 functions.
+            // https://developer.arm.com/architectures/instruction-sets/intrinsics/vmull_p64
+            "neon.pmull64" => {
+                // LLVM and GCC group pmull with the AES intrinsics.
+                // Also see <https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612088.html>.
+                this.expect_target_feature_for_intrinsic(link_name, "aes")?;
+
+                let [left, right] =
+                    this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
+                let left = this.read_scalar(left)?.to_u64()?;
+                let right = this.read_scalar(right)?.to_u64()?;
+
+                let result = left.widening_carryless_mul(right);
+
+                // dest is int8x16_t, transmute to u128 for the write.
+                let dest = dest.transmute(this.machine.layouts.u128, this)?;
+                this.write_scalar(Scalar::from_u128(result), &dest)?;
+            }
+
             _ => return interp_ok(EmulateItemResult::NotSupported),
         }
         interp_ok(EmulateItemResult::NeedsReturn)
diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs
index 26f98a5..25dca7b 100644
--- a/src/tools/miri/src/shims/files.rs
+++ b/src/tools/miri/src/shims/files.rs
@@ -1,9 +1,10 @@
 use std::any::Any;
 use std::collections::BTreeMap;
-use std::fs::File;
+use std::fs::{Dir, File};
 use std::io::{ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write};
 use std::marker::CoercePointee;
 use std::ops::Deref;
+use std::path::PathBuf;
 use std::rc::{Rc, Weak};
 use std::{fs, io};
 
@@ -362,6 +363,7 @@ fn is_tty(&self, communicate_allowed: bool) -> bool {
 #[derive(Debug)]
 pub struct FileHandle {
     pub(crate) file: File,
+    pub(crate) readable: bool,
     pub(crate) writable: bool,
 }
 
@@ -380,6 +382,10 @@ fn read<'tcx>(
     ) -> InterpResult<'tcx> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
 
+        if !self.readable {
+            return finish.call(ecx, Err(ErrorKind::PermissionDenied.into()));
+        }
+
         let mut file = &self.file;
         let result = ecx.read_from_host(|buf| file.read(buf), len, ptr)?;
         finish.call(ecx, result)
@@ -468,6 +474,39 @@ fn as_unix<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription {
     }
 }
 
+#[derive(Debug)]
+pub struct DirHandle {
+    #[cfg_attr(bootstrap, allow(unused))]
+    pub(crate) dir: Dir,
+    /// Fallback used under `cfg(bootstrap)`.
+    #[cfg_attr(not(bootstrap), allow(unused))]
+    pub(crate) path: PathBuf,
+}
+
+impl FileDescription for DirHandle {
+    fn name(&self) -> &'static str {
+        "directory"
+    }
+
+    fn metadata<'tcx>(
+        &self,
+    ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> {
+        #[cfg(not(bootstrap))]
+        return interp_ok(Either::Left(self.dir.metadata()));
+        #[cfg(bootstrap)]
+        return interp_ok(Either::Left(std::fs::metadata(&self.path)));
+    }
+
+    fn destroy<'tcx>(
+        self,
+        _self_id: FdId,
+        _communicate_allowed: bool,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        interp_ok(Ok(()))
+    }
+}
+
 /// Like /dev/null
 #[derive(Debug)]
 pub struct NullOutput;
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index bff93a7..e4daab7 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -857,6 +857,14 @@ fn emulate_foreign_item_inner(
                     this, link_name, abi, args, dest,
                 );
             }
+            name if name.starts_with("llvm.loongarch.")
+                && matches!(this.tcx.sess.target.arch, Arch::LoongArch32 | Arch::LoongArch64)
+                && this.tcx.sess.target.endian == Endian::Little =>
+            {
+                return shims::loongarch::EvalContextExt::emulate_loongarch_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
 
             // Fallback to shims in submodules.
             _ => {
diff --git a/src/tools/miri/src/shims/loongarch.rs b/src/tools/miri/src/shims/loongarch.rs
new file mode 100644
index 0000000..e5a57fb
--- /dev/null
+++ b/src/tools/miri/src/shims/loongarch.rs
@@ -0,0 +1,70 @@
+use rustc_abi::CanonAbi;
+use rustc_middle::ty::Ty;
+use rustc_span::Symbol;
+use rustc_target::callconv::FnAbi;
+
+use crate::shims::math::compute_crc32;
+use crate::*;
+
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    fn emulate_loongarch_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: &FnAbi<'tcx, Ty<'tcx>>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx, EmulateItemResult> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.loongarch.").unwrap();
+        match unprefixed_name {
+            // Used to implement the crc.w.{b,h,w,d}.w and crcc.w.{b,h,w,d}.w functions.
+            // https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#crc-check-instructions
+            // These are only available on LA64, not on LA32, and are part of
+            // the LA64 1.0 baseline and therefore always available and don't
+            // require a target feature to be enabled.
+            "crc.w.b.w" | "crc.w.h.w" | "crc.w.w.w" | "crc.w.d.w" | "crcc.w.b.w" | "crcc.w.h.w"
+            | "crcc.w.w.w" | "crcc.w.d.w"
+                if this.tcx.pointer_size().bits() == 64 =>
+            {
+                // The polynomial constants below include the leading 1 bit
+                // (e.g. 0x104C11DB7 instead of 0x04C11DB7) which the the
+                // polynomial division algorithm requires.
+                // Note that Loongson's documentation mentions the numbers
+                // 0xEDB88320 for IEEE802.3 and 0x82F63B78 for Castagnoli,
+                // which is because their docs put the least significant bit
+                // first.
+                let (bit_size, polynomial): (u32, u128) = match unprefixed_name {
+                    "crc.w.b.w" => (8, 0x104C11DB7),
+                    "crc.w.h.w" => (16, 0x104C11DB7),
+                    "crc.w.w.w" => (32, 0x104C11DB7),
+                    "crc.w.d.w" => (64, 0x104C11DB7),
+                    "crcc.w.b.w" => (8, 0x11EDC6F41),
+                    "crcc.w.h.w" => (16, 0x11EDC6F41),
+                    "crcc.w.w.w" => (32, 0x11EDC6F41),
+                    "crcc.w.d.w" => (64, 0x11EDC6F41),
+                    _ => unreachable!(),
+                };
+
+                let [data, crc] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
+                let data = this.read_scalar(data)?;
+                let crc = this.read_scalar(crc)?;
+
+                // The CRC accumulator is always i32. The data argument is i32 for
+                // b/h/w variants and i64 for the d variant, per the LLVM intrinsic
+                // definitions.
+                // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsLoongArch.td
+                // If the higher bits are non-zero, `compute_crc32` will panic. We should probably
+                // raise a proper error instead, but outside stdarch nobody can trigger this anyway.
+                let crc = crc.to_u32()?;
+                let data = if bit_size == 64 { data.to_u64()? } else { u64::from(data.to_u32()?) };
+
+                let result = compute_crc32(crc, data, bit_size, polynomial);
+                this.write_scalar(Scalar::from_u32(result), dest)?;
+            }
+            _ => return interp_ok(EmulateItemResult::NotSupported),
+        }
+        interp_ok(EmulateItemResult::NeedsReturn)
+    }
+}
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 551f7b2..d84e83d 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -4,6 +4,7 @@
 mod alloc;
 mod backtrace;
 mod files;
+mod loongarch;
 mod math;
 #[cfg(all(feature = "native-lib", unix))]
 pub mod native_lib;
diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs
index 5259ca2..999750a 100644
--- a/src/tools/miri/src/shims/unix/android/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs
@@ -3,11 +3,11 @@
 use rustc_span::Symbol;
 use rustc_target::callconv::FnAbi;
 
-use crate::shims::unix::android::thread::prctl;
 use crate::shims::unix::env::EvalContextExt as _;
 use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
 use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
 use crate::shims::unix::linux_like::syscall::syscall;
+use crate::shims::unix::linux_like::thread::prctl;
 use crate::shims::unix::*;
 use crate::*;
 
@@ -27,18 +27,6 @@ fn emulate_foreign_item_inner(
         let this = self.eval_context_mut();
         match link_name.as_str() {
             // File related shims
-            "stat" => {
-                // FIXME: This does not have a direct test (#3179).
-                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
-                let result = this.stat(path, buf)?;
-                this.write_scalar(result, dest)?;
-            }
-            "lstat" => {
-                // FIXME: This does not have a direct test (#3179).
-                let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
-                let result = this.lstat(path, buf)?;
-                this.write_scalar(result, dest)?;
-            }
             "pread64" => {
                 // FIXME: This does not have a direct test (#3179).
                 let [fd, buf, count, offset] = this.check_shim_sig(
diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs
index 1f2a74b..09c6507 100644
--- a/src/tools/miri/src/shims/unix/android/mod.rs
+++ b/src/tools/miri/src/shims/unix/android/mod.rs
@@ -1,2 +1 @@
 pub mod foreign_items;
-pub mod thread;
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 1b387d6..c2ae650 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -342,7 +342,10 @@ fn emulate_foreign_item_inner(
             }
             "flock" => {
                 // Currently this function does not exist on all Unixes, e.g. on Solaris.
-                this.check_target_os(&[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos], link_name)?;
+                this.check_target_os(
+                    &[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos],
+                    link_name,
+                )?;
 
                 let [fd, op] = this.check_shim_sig(
                     shim_sig!(extern "C" fn(i32, i32) -> i32),
@@ -393,6 +396,16 @@ fn emulate_foreign_item_inner(
                 let result = this.symlink(target, linkpath)?;
                 this.write_scalar(result, dest)?;
             }
+            "linkat" => {
+                let [oldfd, oldpath, newfd, newpath, flags] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *const _, i32, *const _, i32) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                let result = this.linkat(oldfd, oldpath, newfd, newpath, flags)?;
+                this.write_scalar(result, dest)?;
+            }
             "fstat" => {
                 let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
                 let result = this.fstat(fd, buf)?;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index d221dc5..659125f 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -64,6 +64,10 @@ fn pread<'tcx>(
         finish: DynMachineCallback<'tcx, Result<usize, IoError>>,
     ) -> InterpResult<'tcx> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
+        if !self.readable {
+            return finish.call(ecx, Err(LibcError("EBADF")));
+        }
+
         let mut bytes = vec![0; len];
         // Emulates pread using seek + read + seek to restore cursor position.
         // Correctness of this emulation relies on sequential nature of Miri execution.
@@ -101,6 +105,10 @@ fn pwrite<'tcx>(
         finish: DynMachineCallback<'tcx, Result<usize, IoError>>,
     ) -> InterpResult<'tcx> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
+        if !self.writable {
+            return finish.call(ecx, Err(LibcError("EBADF")));
+        }
+
         // Emulates pwrite using seek + write + seek to restore cursor position.
         // Correctness of this emulation relies on sequential nature of Miri execution.
         // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`.
@@ -387,6 +395,7 @@ fn open(
             throw_unsup_format!("access mode flags on this target are unsupported");
         }
         let mut writable = true;
+        let mut readable = true;
 
         // Now we check the access mode
         let access_mode = flag & 0b11;
@@ -396,6 +405,7 @@ fn open(
             writable = false;
             options.read(true);
         } else if access_mode == o_wronly {
+            readable = false;
             options.write(true);
         } else if access_mode == o_rdwr {
             options.read(true).write(true);
@@ -495,7 +505,7 @@ fn open(
 
         let fd = options
             .open(path)
-            .map(|file| this.machine.fds.insert_new(FileHandle { file, writable }));
+            .map(|file| this.machine.fds.insert_new(FileHandle { file, writable, readable }));
 
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?))
     }
@@ -584,6 +594,59 @@ fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
     }
 
+    fn linkat(
+        &mut self,
+        oldfd_op: &OpTy<'tcx>,
+        oldpath_op: &OpTy<'tcx>,
+        newfd_op: &OpTy<'tcx>,
+        newpath_op: &OpTy<'tcx>,
+        flags_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
+        let this = self.eval_context_mut();
+
+        // Load all arguments
+        let flags = this.read_scalar(flags_op)?.to_i32()?;
+        let oldfd = this.read_scalar(oldfd_op)?.to_i32()?;
+        let newfd = this.read_scalar(newfd_op)?.to_i32()?;
+        let oldpath_ptr = this.read_pointer(oldpath_op)?;
+        let newpath_ptr = this.read_pointer(newpath_op)?;
+
+        // Relevant libc constants
+        let at_fdcwd = this.eval_libc_i32("AT_FDCWD");
+
+        // Reject if isolation is enabled.
+        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+            this.reject_in_isolation("`linkat`", reject_with)?;
+            return this.set_errno_and_return_neg1_i32(ErrorKind::PermissionDenied);
+        }
+
+        // Read flags - only support 0.
+        if flags != 0 {
+            throw_unsup_format!("unsupported linkat flags {:#x}", flags);
+        }
+
+        // Resolve oldpath
+        if oldfd != at_fdcwd {
+            throw_unsup_format!("linkat with `olddirfd` not equal to `AT_FDCWD` is not supported");
+        }
+        if oldpath_ptr == Pointer::null() {
+            return this.set_errno_and_return_neg1_i32(LibcError("EFAULT"));
+        }
+        let oldpath = this.read_path_from_c_str(oldpath_ptr)?.into_owned();
+
+        // Resolve newpath
+        if newfd != at_fdcwd {
+            throw_unsup_format!("linkat with `newdirfd` not equal to `AT_FDCWD` is not supported");
+        }
+        if newpath_ptr == Pointer::null() {
+            return this.set_errno_and_return_neg1_i32(LibcError("EFAULT"));
+        }
+        let newpath = this.read_path_from_c_str(newpath_ptr)?.into_owned();
+
+        let result = fs::hard_link(&oldpath, &newpath).map(|()| 0);
+        interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
+    }
+
     fn stat(&mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
@@ -892,12 +955,12 @@ fn fchmod(&mut self, fd_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'
             // The docs don't talk about what happens for non-regular files...
             throw_unsup_format!("`fchmod` is only supported on regular files")
         };
-
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`fchmod`", reject_with)?;
-            return this.set_errno_and_return_neg1_i32(LibcError("EACCES"));
+        if !file.writable && !file.readable {
+            // Apparently, `fchmod` on a read-only file is fine. But let's not allow it on a
+            // path-only file.
+            return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
         }
+        assert!(this.machine.communicate(), "isolation should have prevented even opening a file");
 
         let permissions = this.host_permissions_from_mode(mode.try_into().unwrap())?;
         if let Err(err) = file.file.set_permissions(permissions) {
@@ -1253,33 +1316,25 @@ fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
     fn ftruncate64(&mut self, fd_num: i32, length: i128) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`ftruncate64`", reject_with)?;
-            // Set error code as "EBADF" (bad fd)
-            return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
-        }
-
         let Some(fd) = this.machine.fds.get(fd_num) else {
             return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
         };
-
         let Some(file) = fd.downcast::<FileHandle>() else {
             // The docs say that EINVAL is returned when the FD "does not reference a regular file
             // or a POSIX shared memory object" (and we don't support shmem objects).
-            return interp_ok(this.eval_libc("EINVAL"));
+            return this.set_errno_and_return_neg1_i32(LibcError("EINVAL"));
         };
+        if !file.writable {
+            // man page says "EBADF or EINVAL", Linux seems to use EINVAL.
+            return this.set_errno_and_return_neg1_i32(LibcError("EINVAL"));
+        }
+        assert!(this.machine.communicate(), "isolation should have prevented even opening a file");
 
-        if file.writable {
-            if let Ok(length) = length.try_into() {
-                let result = file.file.set_len(length);
-                let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
-                interp_ok(Scalar::from_i32(result))
-            } else {
-                this.set_errno_and_return_neg1_i32(LibcError("EINVAL"))
-            }
+        if let Ok(length) = length.try_into() {
+            let result = file.file.set_len(length);
+            let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
+            interp_ok(Scalar::from_i32(result))
         } else {
-            // The file is not writable
             this.set_errno_and_return_neg1_i32(LibcError("EINVAL"))
         }
     }
@@ -1352,13 +1407,6 @@ fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
 
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`fsync`", reject_with)?;
-            // Set error code as "EBADF" (bad fd)
-            return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
-        }
-
         self.ffullsync_fd(fd)
     }
 
@@ -1371,6 +1419,8 @@ fn ffullsync_fd(&mut self, fd_num: i32) -> InterpResult<'tcx, Scalar> {
         let file = fd.downcast::<FileHandle>().ok_or_else(|| {
             err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
         })?;
+        assert!(this.machine.communicate(), "isolation should have prevented even opening a file");
+
         let io_result = maybe_sync_file(&file.file, file.writable, File::sync_all);
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
     }
@@ -1380,13 +1430,6 @@ fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
 
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`fdatasync`", reject_with)?;
-            // Set error code as "EBADF" (bad fd)
-            return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
-        }
-
         let Some(fd) = this.machine.fds.get(fd) else {
             return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
         };
@@ -1394,6 +1437,8 @@ fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let file = fd.downcast::<FileHandle>().ok_or_else(|| {
             err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors")
         })?;
+        assert!(this.machine.communicate(), "isolation should have prevented even opening a file");
+
         let io_result = maybe_sync_file(&file.file, file.writable, File::sync_data);
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
     }
@@ -1422,13 +1467,6 @@ fn sync_file_range(
             return this.set_errno_and_return_neg1_i32(LibcError("EINVAL"));
         }
 
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`sync_file_range`", reject_with)?;
-            // Set error code as "EBADF" (bad fd)
-            return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
-        }
-
         let Some(fd) = this.machine.fds.get(fd) else {
             return this.set_errno_and_return_neg1_i32(LibcError("EBADF"));
         };
@@ -1436,6 +1474,8 @@ fn sync_file_range(
         let file = fd.downcast::<FileHandle>().ok_or_else(|| {
             err_unsup_format!("`sync_data_range` is only supported on file-backed file descriptors")
         })?;
+        assert!(this.machine.communicate(), "isolation should have prevented even opening a file");
+
         let io_result = maybe_sync_file(&file.file, file.writable, File::sync_data);
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
     }
@@ -1661,7 +1701,11 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
             let file = fopts.open(bytes_to_os_str(template_bytes)?);
             match file {
                 Ok(f) => {
-                    let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true });
+                    let fd = this.machine.fds.insert_new(FileHandle {
+                        file: f,
+                        writable: true,
+                        readable: true,
+                    });
                     return interp_ok(Scalar::from_i32(fd));
                 }
                 Err(e) =>
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index e42bf90..caea737 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -8,6 +8,7 @@
 use self::shims::unix::linux_like::syscall::syscall;
 use crate::machine::{SIGRTMAX, SIGRTMIN};
 use crate::shims::unix::foreign_items::EvalContextExt as _;
+use crate::shims::unix::linux_like::thread::prctl;
 use crate::shims::unix::*;
 use crate::*;
 
@@ -197,6 +198,7 @@ fn emulate_foreign_item_inner(
                 let result = this.unix_gettid(link_name.as_str())?;
                 this.write_scalar(result, dest)?;
             }
+            "prctl" => prctl(this, link_name, abi, args, dest)?,
 
             // Dynamically invoked syscalls
             "syscall" => {
diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs
index 3ecc2c1..cf409db 100644
--- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs
@@ -1,7 +1,6 @@
 use std::cell::RefCell;
-use std::collections::{BTreeMap, BTreeSet, VecDeque};
+use std::collections::{BTreeMap, VecDeque};
 use std::io;
-use std::ops::Bound;
 use std::time::Duration;
 
 use rustc_abi::FieldIdx;
@@ -23,7 +22,9 @@ pub struct Epoll {
     interest_list: RefCell<BTreeMap<EpollEventKey, EpollEventInterest>>,
     /// The subset of interests that is currently considered "ready". Stored separately so we
     /// can access it more efficiently.
-    ready_set: RefCell<BTreeSet<EpollEventKey>>,
+    /// This is implemented as a queue so that for level-triggered epoll, all events eventually
+    /// get returned from `epoll_wait`. The queue does not contain any duplicates.
+    ready_events: RefCell<VecDeque<EpollEventKey>>,
     /// The queue of threads blocked on this epoll instance.
     queue: RefCell<VecDeque<ThreadId>>,
 }
@@ -46,6 +47,9 @@ pub struct EpollEventInterest {
     relevant_events: u32,
     /// The currently active events for this file descriptor.
     active_events: u32,
+    /// Boolean whether this is an edge-triggered interest.
+    /// When [`false`] it's a level-triggered interest instead.
+    is_edge_triggered: bool,
     /// The vector clock for wakeups.
     clock: VClock,
     /// User-defined data associated with this interest.
@@ -203,12 +207,8 @@ pub fn remove_epolls(&mut self, id: FdId) {
                     .extract_if(range_for_id(id), |_, _| true)
                     // Consume the iterator.
                     .for_each(drop);
-                epoll
-                    .ready_set
-                    .borrow_mut()
-                    .extract_if(range_for_id(id), |_| true)
-                    // Consume the iterator.
-                    .for_each(drop);
+                // Remove the ready events for this file description.
+                epoll.ready_events.borrow_mut().retain(|(fd_id, _)| fd_id != &id);
             }
         }
     }
@@ -303,6 +303,13 @@ fn epoll_ctl(
                 this.read_scalar(&this.project_field(&event, FieldIdx::ZERO)?)?.to_u32()?;
             let data = this.read_scalar(&this.project_field(&event, FieldIdx::ONE)?)?.to_u64()?;
 
+            let is_edge_triggered = if events & epollet == epollet {
+                events &= !epollet;
+                true
+            } else {
+                false
+            };
+
             // Unset the flag we support to discover if any unsupported flags are used.
             let mut flags = events;
             // epoll_wait(2) will always wait for epollhup and epollerr; it is not
@@ -311,12 +318,6 @@ fn epoll_ctl(
             events |= epollhup;
             events |= epollerr;
 
-            if events & epollet != epollet {
-                // We only support edge-triggered notification for now.
-                throw_unsup_format!("epoll_ctl: epollet flag must be included.");
-            } else {
-                flags &= !epollet;
-            }
             if flags & epollin == epollin {
                 flags &= !epollin;
             }
@@ -350,6 +351,7 @@ fn epoll_ctl(
                 }
                 let new_interest = EpollEventInterest {
                     relevant_events: events,
+                    is_edge_triggered,
                     data,
                     active_events: 0,
                     clock: VClock::default(),
@@ -364,6 +366,7 @@ fn epoll_ctl(
                     return this.set_errno_and_return_neg1_i32(LibcError("ENOENT"));
                 };
                 interest.relevant_events = events;
+                interest.is_edge_triggered = is_edge_triggered;
                 interest.data = data;
             }
 
@@ -391,7 +394,11 @@ fn epoll_ctl(
                 // We did not have interest in this.
                 return this.set_errno_and_return_neg1_i32(LibcError("ENOENT"));
             };
-            epfd.ready_set.borrow_mut().remove(&epoll_key);
+            // Remove the ready event for this key, should one exist.
+            let mut ready_events = epfd.ready_events.borrow_mut();
+            if let Some(idx) = ready_events.iter().position(|k| k == &epoll_key) {
+                ready_events.remove(idx);
+            }
             // If this was the last interest in this FD, remove us from the global list
             // of who is interested in this FD.
             if interest_list.range(range_for_id(id)).next().is_none() {
@@ -469,7 +476,7 @@ fn epoll_wait(
             return this.set_errno_and_return_neg1(LibcError("EBADF"), dest);
         };
 
-        if timeout == 0 || !epfd.ready_set.borrow().is_empty() {
+        if timeout == 0 || !epfd.ready_events.borrow().is_empty() {
             // If the timeout is 0 or there is a ready event, we can return immediately.
             return_ready_list(&epfd, dest, &event, this)?;
         } else {
@@ -590,18 +597,29 @@ fn update_readiness<'tcx>(
         &mut dyn FnMut(EpollEventKey, &mut EpollEventInterest) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx>,
 ) -> InterpResult<'tcx> {
-    let mut ready_set = epoll.ready_set.borrow_mut();
+    let mut ready_events = epoll.ready_events.borrow_mut();
     for_each_interest(&mut |key, interest| {
         // Update the ready events tracked in this interest.
         let new_readiness = interest.relevant_events & active_events;
         let prev_readiness = std::mem::replace(&mut interest.active_events, new_readiness);
         if new_readiness == 0 {
             // Un-trigger this, there's nothing left to report here.
-            ready_set.remove(&key);
+            if let Some(idx) = ready_events.iter().position(|k| k == &key) {
+                ready_events.remove(idx);
+            }
         } else if force_edge || new_readiness != prev_readiness & new_readiness {
-            // Either we force an "edge" to be detected, or there's a bit set in `new`
-            // that was not set in `prev`. In both cases, this is ready now.
-            ready_set.insert(key);
+            // Either we force an "edge" to be detected or there's a bit set in `new_readiness`
+            // that was not set in `prev_readiness`. In both cases, this is ready now.
+
+            // We need to ensure that this event is not already part of the
+            // `ready_events` queue before enqueueing:
+            // <https://github.com/torvalds/linux/blob/HEAD/fs/eventpoll.c#L1292-L1296>
+            if !ready_events.contains(&key) {
+                ready_events.push_back(key);
+            }
+
+            // No matter whether this is newly ready or just re-triggered,
+            // the `epoll_wait` fetching this event should sync with the current thread.
             ecx.release_clock(|clock| {
                 interest.clock.join(clock);
             })?;
@@ -609,12 +627,12 @@ fn update_readiness<'tcx>(
         interp_ok(())
     })?;
     // While there are events ready to be delivered, wake up a thread to receive them.
-    while !ready_set.is_empty()
+    while !ready_events.is_empty()
         && let Some(thread_id) = epoll.queue.borrow_mut().pop_front()
     {
-        drop(ready_set); // release the "lock" so the unblocked thread can have it
+        drop(ready_events); // release the "lock" so the unblocked thread can have it
         ecx.unblock_thread(thread_id, BlockReason::Epoll { epfd: epoll.clone() })?;
-        ready_set = epoll.ready_set.borrow_mut();
+        ready_events = epoll.ready_events.borrow_mut();
     }
 
     interp_ok(())
@@ -629,7 +647,7 @@ fn return_ready_list<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
 ) -> InterpResult<'tcx, i32> {
     let mut interest_list = epfd.interest_list.borrow_mut();
-    let mut ready_set = epfd.ready_set.borrow_mut();
+    let mut ready_events = epfd.ready_events.borrow_mut();
     let mut num_of_events: i32 = 0;
     let mut array_iter = ecx.project_array_fields(events)?;
 
@@ -644,27 +662,29 @@ fn return_ready_list<'tcx>(
         }
     }
 
-    // While there is a slot to store another event, and an event to store, deliver that event.
-    // We can't use an iterator over `ready_set` as we want to remove elements as we go,
-    // so we track the most recently delivered event to find the next one. We track it as a lower
-    // bound that we can pass to `BTreeSet::range`.
-    let mut event_lower_bound = Bound::Unbounded;
-    while let Some(slot) = array_iter.next(ecx)?
-        && let Some(&key) = ready_set.range((event_lower_bound, Bound::Unbounded)).next()
+    // We will fill at most the first `ready_events_len` slots of the array.
+    // Bounding the iterator this way ensures that we can re-add events
+    // to the end of the queue during the loop without having them show up in the array.
+    let ready_events_len = u64::try_from(ready_events.len()).unwrap();
+    while let Some((idx, slot)) = array_iter.next(ecx)?
+        && idx < ready_events_len
+        && let Some(key) = ready_events.pop_front()
     {
         let interest = interest_list.get_mut(&key).expect("non-existent event in ready set");
         // Deliver event to caller.
         ecx.write_int_fields_named(
             &[("events", interest.active_events.into()), ("u64", interest.data.into())],
-            &slot.1,
+            &slot,
         )?;
         num_of_events = num_of_events.strict_add(1);
         // Synchronize receiving thread with the event of interest.
         ecx.acquire_clock(&interest.clock)?;
-        // This was an edge-triggered event, so remove it from the ready set.
-        ready_set.remove(&key);
-        // Go find the next event.
-        event_lower_bound = Bound::Excluded(key);
+        if !interest.is_edge_triggered {
+            // This is a level-triggered interest, so we need to re-add the event
+            // at the end of the ready queue:
+            // <https://github.com/torvalds/linux/blob/HEAD/fs/eventpoll.c#L1835-L1847>
+            ready_events.push_back(key);
+        }
     }
     ecx.write_int(num_of_events, dest)?;
     interp_ok(num_of_events)
diff --git a/src/tools/miri/src/shims/unix/linux_like/mod.rs b/src/tools/miri/src/shims/unix/linux_like/mod.rs
index 1a22539..5d419b9 100644
--- a/src/tools/miri/src/shims/unix/linux_like/mod.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/mod.rs
@@ -2,3 +2,4 @@
 pub mod eventfd;
 pub mod sync;
 pub mod syscall;
+pub mod thread;
diff --git a/src/tools/miri/src/shims/unix/android/thread.rs b/src/tools/miri/src/shims/unix/linux_like/thread.rs
similarity index 92%
rename from src/tools/miri/src/shims/unix/android/thread.rs
rename to src/tools/miri/src/shims/unix/linux_like/thread.rs
index 4e7b21d..da76af5 100644
--- a/src/tools/miri/src/shims/unix/android/thread.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/thread.rs
@@ -18,9 +18,8 @@ pub fn prctl<'tcx>(
 ) -> InterpResult<'tcx> {
     let ([op], varargs) = ecx.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
 
-    // FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch.
-    let pr_set_name = 15;
-    let pr_get_name = 16;
+    let pr_set_name = ecx.eval_libc_i32("PR_SET_NAME");
+    let pr_get_name = ecx.eval_libc_i32("PR_GET_NAME");
 
     let res = match ecx.read_scalar(op)?.to_i32()? {
         op if op == pr_set_name => {
diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs
index a6efc36..de0ad7f 100644
--- a/src/tools/miri/src/shims/windows/fs.rs
+++ b/src/tools/miri/src/shims/windows/fs.rs
@@ -1,72 +1,16 @@
-use std::fs::{Metadata, OpenOptions};
+use std::fs::{self, Dir};
 use std::io;
 use std::io::SeekFrom;
-use std::path::PathBuf;
 use std::time::SystemTime;
 
 use bitflags::bitflags;
 use rustc_abi::Size;
 use rustc_target::spec::Os;
 
-use crate::shims::files::{FdId, FileDescription, FileHandle};
+use crate::shims::files::{DirHandle, FileHandle};
 use crate::shims::windows::handle::{EvalContextExt as _, Handle};
 use crate::*;
 
-#[derive(Debug)]
-pub struct DirHandle {
-    pub(crate) path: PathBuf,
-}
-
-impl FileDescription for DirHandle {
-    fn name(&self) -> &'static str {
-        "directory"
-    }
-
-    fn metadata<'tcx>(
-        &self,
-    ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> {
-        interp_ok(Either::Left(self.path.metadata()))
-    }
-
-    fn destroy<'tcx>(
-        self,
-        _self_id: FdId,
-        _communicate_allowed: bool,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx, io::Result<()>> {
-        interp_ok(Ok(()))
-    }
-}
-
-/// Windows supports handles without any read/write/delete permissions - these handles can get
-/// metadata, but little else. We represent that by storing the metadata from the time the handle
-/// was opened.
-#[derive(Debug)]
-pub struct MetadataHandle {
-    pub(crate) meta: Metadata,
-}
-
-impl FileDescription for MetadataHandle {
-    fn name(&self) -> &'static str {
-        "metadata-only"
-    }
-
-    fn metadata<'tcx>(
-        &self,
-    ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> {
-        interp_ok(Either::Left(Ok(self.meta.clone())))
-    }
-
-    fn destroy<'tcx>(
-        self,
-        _self_id: FdId,
-        _communicate_allowed: bool,
-        _ecx: &mut MiriInterpCx<'tcx>,
-    ) -> InterpResult<'tcx, io::Result<()>> {
-        interp_ok(Ok(()))
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq)]
 enum CreationDisposition {
     CreateAlways,
@@ -213,8 +157,10 @@ fn CreateFileW(
             throw_unsup_format!("CreateFileW: Template files are not supported");
         }
 
-        // We need to know if the file is a directory to correctly open directory handles.
-        // This is racy, but currently the stdlib doesn't appear to offer a better solution.
+        // We need to know if the file is a directory to correctly open directory handles. This is
+        // racy, but currently the stdlib doesn't appear to offer a better solution. We do later
+        // verify that our guess was correct so worst-case, Miri ICEs here.
+        // FIXME: retry in a loop if we get an error indicating we got the wrong file type?
         let is_dir = file_name.is_dir();
 
         // BACKUP_SEMANTICS is how Windows calls the act of opening a directory handle.
@@ -226,7 +172,7 @@ fn CreateFileW(
         let desired_read = desired_access & generic_read != 0;
         let desired_write = desired_access & generic_write != 0;
 
-        let mut options = OpenOptions::new();
+        let mut options = fs::OpenOptions::new();
         if desired_read {
             desired_access &= !generic_read;
             options.read(true);
@@ -261,17 +207,19 @@ fn CreateFileW(
 
         let handle = if is_dir {
             // Open this as a directory.
-            let fd_num = this.machine.fds.insert_new(DirHandle { path: file_name });
-            Ok(Handle::File(fd_num))
-        } else if creation_disposition == OpenExisting && !(desired_read || desired_write) {
-            // Windows supports handles with no permissions. These allow things such as reading
-            // metadata, but not file content.
-            file_name.metadata().map(|meta| {
-                let fd_num = this.machine.fds.insert_new(MetadataHandle { meta });
+            // FIXME: shouldn't we check `creation_disposition` here?
+            Dir::open(&file_name).map(|dir| {
+                #[cfg(not(bootstrap))]
+                assert!(
+                    dir.metadata().unwrap().is_dir(),
+                    "we tried to open a directory and got a file"
+                );
+                let fd_num = this.machine.fds.insert_new(DirHandle { dir, path: file_name });
                 Handle::File(fd_num)
             })
         } else {
-            // Open this as a standard file.
+            // Open this as a standard file. We already set the `read`/`write` flags above,
+            // but we still need to represent the `creation_disposition`.
             match creation_disposition {
                 CreateAlways | OpenAlways => {
                     options.create(true);
@@ -288,15 +236,33 @@ fn CreateFileW(
                         options.append(true);
                     }
                 }
-                OpenExisting => {} // Default options
+                OpenExisting => {
+                    if !desired_read && !desired_write {
+                        // Windows supports handles with no permissions. These allow things such as
+                        // reading metadata, but not file content. This is used by `Path::metadata`.
+                        // `std` does not support this. To ensure we behave correctly as often as
+                        // possible, we open the file for reading and live with the fact that this
+                        // might incorrectly return `PermissionDenied`.
+                        // FIXME: We could probably use `OpenOptionsExt`? On a Unix host,
+                        // `O_PATH` apparently can open files for metadata use only.
+                        options.read(true);
+                    }
+                }
                 TruncateExisting => {
                     options.truncate(true);
                 }
             }
 
             options.open(file_name).map(|file| {
-                let fd_num =
-                    this.machine.fds.insert_new(FileHandle { file, writable: desired_write });
+                assert!(
+                    !file.metadata().unwrap().is_dir(),
+                    "we tried to open a file and got a directory"
+                );
+                let fd_num = this.machine.fds.insert_new(FileHandle {
+                    file,
+                    writable: desired_write,
+                    readable: desired_read,
+                });
                 Handle::File(fd_num)
             })
         };
diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
index 336f39e..eecf6ab 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
+++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs
@@ -6,33 +6,13 @@
 // ensure deterministic schedule
 //@compile-flags: -Zmiri-deterministic-concurrency
 
-use std::convert::TryInto;
 use std::thread;
 use std::thread::spawn;
 
 #[path = "../../utils/libc.rs"]
 mod libc_utils;
-
-#[track_caller]
-fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) {
-    let epoll_event = libc::epoll_event { events: 0, u64: 0 };
-    let mut array: [libc::epoll_event; N] = [epoll_event; N];
-    let maxsize = N;
-    let array_ptr = array.as_mut_ptr();
-    let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) };
-    if res < 0 {
-        panic!("epoll_wait failed: {}", std::io::Error::last_os_error());
-    }
-    assert_eq!(
-        res,
-        expected_notifications.len().try_into().unwrap(),
-        "got wrong number of notifications"
-    );
-    let got_notifications =
-        unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) };
-    let got_notifications = got_notifications.iter().map(|e| (e.events, e.u64)).collect::<Vec<_>>();
-    assert_eq!(got_notifications, expected_notifications, "got wrong notifications");
-}
+use libc_utils::epoll::*;
+use libc_utils::*;
 
 fn main() {
     // Create an epoll instance.
@@ -41,27 +21,17 @@ fn main() {
 
     // Create two socketpair instances.
     let mut fds_a = [-1, -1];
-    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_a.as_mut_ptr()) };
-    assert_eq!(res, 0);
-
+    unsafe {
+        errno_check(libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_a.as_mut_ptr()))
+    };
     let mut fds_b = [-1, -1];
-    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_b.as_mut_ptr()) };
-    assert_eq!(res, 0);
+    unsafe {
+        errno_check(libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_b.as_mut_ptr()))
+    };
 
     // Register both pipe read ends.
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLET) as _,
-        u64: u64::try_from(fds_a[1]).unwrap(),
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_a[1], &mut ev) };
-    assert_eq!(res, 0);
-
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLET) as _,
-        u64: u64::try_from(fds_b[1]).unwrap(),
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_b[1], &mut ev) };
-    assert_eq!(res, 0);
+    epoll_ctl_add(epfd, fds_a[1], EPOLLIN | EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds_b[1], EPOLLIN | EPOLLET).unwrap();
 
     static mut VAL_ONE: u8 = 40; // This one will be read soundly.
     static mut VAL_TWO: u8 = 50; // This one will be read unsoundly.
@@ -78,9 +48,7 @@ fn main() {
     thread::yield_now();
 
     // With room for one event: check result from epoll_wait.
-    let expected_event = u32::try_from(libc::EPOLLIN).unwrap();
-    let expected_value = u64::try_from(fds_a[1]).unwrap();
-    check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_partial(epfd, &[Ev { events: EPOLLIN, data: fds_a[1] }], 1, -1);
 
     // Since we only received one event, we have synchronized with
     // the write to VAL_ONE but not with the one to VAL_TWO.
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
index 16ac2d6..3eb7912 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
+++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs
@@ -2,42 +2,11 @@
 //@only-target: linux android illumos
 //@error-in-other-file: deadlock
 
-use std::convert::TryInto;
 use std::thread;
 
 #[path = "../../utils/libc.rs"]
 mod libc_utils;
-
-// Using `as` cast since `EPOLLET` wraps around
-const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _;
-
-#[track_caller]
-fn check_epoll_wait<const N: usize>(
-    epfd: i32,
-    expected_notifications: &[(u32, u64)],
-    timeout: i32,
-) {
-    let epoll_event = libc::epoll_event { events: 0, u64: 0 };
-    let mut array: [libc::epoll_event; N] = [epoll_event; N];
-    let maxsize = N;
-    let array_ptr = array.as_mut_ptr();
-    let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), timeout) };
-    if res < 0 {
-        panic!("epoll_wait failed: {}", std::io::Error::last_os_error());
-    }
-    assert_eq!(
-        res,
-        expected_notifications.len().try_into().unwrap(),
-        "got wrong number of notifications"
-    );
-    let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) };
-    for (return_event, expected_event) in slice.iter().zip(expected_notifications.iter()) {
-        let event = return_event.events;
-        let data = return_event.u64;
-        assert_eq!(event, expected_event.0, "got wrong events");
-        assert_eq!(data, expected_event.1, "got wrong data");
-    }
-}
+use libc_utils::epoll::*;
 
 // Test if only one thread is unblocked if multiple threads blocked on same epfd.
 // Expected execution:
@@ -57,23 +26,30 @@ fn main() {
     let fd2 = unsafe { libc::dup(fd1) };
 
     // Register both with epoll.
-    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd1 as u64 };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd1, &mut ev) };
-    assert_eq!(res, 0);
-    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd2 as u64 };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd2, &mut ev) };
-    assert_eq!(res, 0);
+    epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fd2, EPOLLIN | EPOLLOUT | EPOLLET).unwrap();
 
     // Consume the initial events.
-    let expected = [(libc::EPOLLOUT as u32, fd1 as u64), (libc::EPOLLOUT as u32, fd2 as u64)];
-    check_epoll_wait::<8>(epfd, &expected, -1);
+    check_epoll_wait(
+        epfd,
+        &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }],
+        -1,
+    );
 
     let thread1 = thread::spawn(move || {
-        check_epoll_wait::<2>(epfd, &expected, -1);
+        check_epoll_wait(
+            epfd,
+            &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }],
+            -1,
+        );
     });
     let thread2 = thread::spawn(move || {
-        check_epoll_wait::<2>(epfd, &expected, -1);
-        //~^ERROR: deadlocked
+        //~vERROR: deadlocked
+        check_epoll_wait(
+            epfd,
+            &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }],
+            -1,
+        );
     });
     // Yield so the threads are both blocked.
     thread::yield_now();
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
index 4f0f9da..191e9d5 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr
@@ -18,8 +18,12 @@
 error: the evaluated program deadlocked
   --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC
    |
-LL |         check_epoll_wait::<TAG>(epfd, &expected, -1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ thread got stuck here
+LL | /         check_epoll_wait(
+LL | |             epfd,
+LL | |             &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }],
+LL | |             -1,
+LL | |         );
+   | |_________^ thread got stuck here
    |
    = note: this is on thread `unnamed-ID`
 note: the current function got called indirectly due to this code
@@ -27,8 +31,11 @@
    |
 LL |       let thread2 = thread::spawn(move || {
    |  ___________________^
-LL | |         check_epoll_wait::<TAG>(epfd, &expected, -1);
 LL | |
+LL | |         check_epoll_wait(
+LL | |             epfd,
+...  |
+LL | |         );
 LL | |     });
    | |______^
 
diff --git a/src/tools/miri/tests/fail-dep/libc/socket-connect-after-failed-connection.rs b/src/tools/miri/tests/fail-dep/libc/socket-connect-after-failed-connection.rs
index babd2d8..2ab5d54 100644
--- a/src/tools/miri/tests/fail-dep/libc/socket-connect-after-failed-connection.rs
+++ b/src/tools/miri/tests/fail-dep/libc/socket-connect-after-failed-connection.rs
@@ -41,7 +41,7 @@ fn main() {
     epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap();
 
     // Wait until the socket has an error.
-    check_epoll_wait::<8>(
+    check_epoll_wait(
         epfd,
         &[Ev { events: libc::EPOLLERR | EPOLLOUT | EPOLLHUP, data: client_sockfd }],
         -1,
diff --git a/src/tools/miri/tests/fail/async-shared-mutable.rs b/src/tools/miri/tests/fail/async-shared-mutable.rs
index 62780e7..f1667f5 100644
--- a/src/tools/miri/tests/fail/async-shared-mutable.rs
+++ b/src/tools/miri/tests/fail/async-shared-mutable.rs
@@ -3,7 +3,7 @@
 //! `UnsafePinned` must include the effects of `UnsafeCell`.
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-//@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[OFFSET]"
+//@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[RANGE]"
 
 use core::future::Future;
 use core::pin::{Pin, pin};
diff --git a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr
index 7cedb24..bdd004d 100644
--- a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr
+++ b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr
@@ -1,12 +1,12 @@
-error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[OFFSET], but that tag does not exist in the borrow stack for this location
+error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[RANGE], but that tag does not exist in the borrow stack for this location
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL |             *x = 1;
-   |             ^^^^^^ this error occurs as part of an access at ALLOC[OFFSET]
+   |             ^^^^^^ this error occurs as part of an access at ALLOC[RANGE]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [OFFSET]
+help: <TAG> was created by a Unique retag at offsets [RANGE]
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL | /         core::future::poll_fn(move |_| {
@@ -15,7 +15,7 @@
 LL | |         })
 LL | |         .await
    | |______________^
-help: <TAG> was later invalidated at offsets [OFFSET] by a SharedReadOnly retag
+help: <TAG> was later invalidated at offsets [RANGE] by a SharedReadOnly retag
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL |     let _: Pin<&_> = f.as_ref(); // Or: `f.as_mut().into_ref()`.
diff --git a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr
index fb68161..f9e7508 100644
--- a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr
+++ b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: write access through <TAG> at ALLOC[OFFSET] is forbidden
+error: Undefined Behavior: write access through <TAG> at ALLOC[RANGE] is forbidden
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL |             *x = 1;
@@ -16,13 +16,13 @@
 LL | |         })
 LL | |         .await
    | |______________^
-help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [OFFSET]
+help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [RANGE]
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL |             *x = 1;
    |             ^^^^^^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
-help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [OFFSET]
+help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [RANGE]
   --> tests/fail/async-shared-mutable.rs:LL:CC
    |
 LL |     let _: Pin<&_> = f.as_ref(); // Or: `f.as_mut().into_ref()`.
diff --git a/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.rs
new file mode 100644
index 0000000..93626a3
--- /dev/null
+++ b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.rs
@@ -0,0 +1,131 @@
+//! Test related to <https://github.com/rust-lang/miri/issues/3341>:
+//! `Box` with custom allocators are still `noalias`, leading to UB.
+
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+//@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[RANGE]"
+#![feature(allocator_api)]
+
+use std::alloc::{AllocError, Allocator, Layout};
+use std::cell::{Cell, UnsafeCell};
+use std::mem;
+use std::ptr::{self, NonNull, addr_of};
+use std::thread::{self, ThreadId};
+
+const BIN_SIZE: usize = 8;
+
+// A bin represents a collection of blocks of a specific layout.
+#[repr(align(128))]
+struct MyBin {
+    top: Cell<usize>,
+    thread_id: ThreadId,
+    memory: UnsafeCell<[usize; BIN_SIZE]>,
+}
+
+impl MyBin {
+    fn pop(&self) -> Option<NonNull<u8>> {
+        let top = self.top.get();
+        if top == BIN_SIZE {
+            return None;
+        }
+        // Cast the *entire* thing to a raw pointer to not restrict its provenance.
+        let bin = self as *const MyBin;
+        let base_ptr = UnsafeCell::raw_get(unsafe { addr_of!((*bin).memory) }).cast::<usize>();
+        let ptr = unsafe { NonNull::new_unchecked(base_ptr.add(top)) };
+        self.top.set(top + 1);
+        Some(ptr.cast())
+    }
+
+    // Pretends to not be a throwaway allocation method like this. A more realistic
+    // substitute is using intrusive linked lists, which requires access to the
+    // metadata of this bin as well.
+    unsafe fn push(&self, ptr: NonNull<u8>) {
+        // For now just check that this really is in this bin.
+        let start = self.memory.get().addr();
+        let end = start + BIN_SIZE * mem::size_of::<usize>();
+        let addr = ptr.addr().get();
+        assert!((start..end).contains(&addr));
+
+        // We can't update `top` as this may not be the last bin, but we can pretend to do so
+        // such that the aliasing model checks things.
+        // We access this via raw pointers so that the error span is in this file.
+        let top_ptr = (&raw const self.top) as *mut usize;
+        let top = top_ptr.read();
+        //~[tree]^ERROR: /read access .* is forbidden/
+        top_ptr.write(top);
+    }
+}
+
+// A collection of bins.
+struct MyAllocator {
+    thread_id: ThreadId,
+    // Pretends to be some complex collection of bins, such as an array of linked lists.
+    bins: Box<[MyBin; 1]>,
+}
+
+impl MyAllocator {
+    fn new() -> Self {
+        let thread_id = thread::current().id();
+        MyAllocator {
+            thread_id,
+            bins: Box::new(
+                [MyBin { top: Cell::new(0), thread_id, memory: UnsafeCell::default() }; 1],
+            ),
+        }
+    }
+
+    // Pretends to be expensive finding a suitable bin for the layout.
+    fn find_bin(&self, layout: Layout) -> Option<&MyBin> {
+        if layout == Layout::new::<usize>() { Some(&self.bins[0]) } else { None }
+    }
+}
+
+unsafe impl Allocator for MyAllocator {
+    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+        // Expensive bin search.
+        let bin = self.find_bin(layout).ok_or(AllocError)?;
+        let ptr = bin.pop().ok_or(AllocError)?;
+        Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
+    }
+
+    unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
+        // Make sure accesses via `self` don't disturb anything.
+        let _val = self.bins[0].top.get();
+        // Since manually finding the corresponding bin of `ptr` is very expensive,
+        // doing pointer arithmetics is preferred.
+        // But this means we access `top` via `ptr` rather than `self`!
+        // That is fundamentally the source of the aliasing trouble in this example.
+        let their_bin = ptr.as_ptr().map_addr(|addr| addr & !127).cast::<MyBin>();
+        let thread_id = ptr::read(ptr::addr_of!((*their_bin).thread_id));
+        //~[stack]^ERROR: tag does not exist in the borrow stack
+        if self.thread_id == thread_id {
+            unsafe { (*their_bin).push(ptr) };
+        } else {
+            todo!("Deallocating from another thread");
+        }
+        // Make sure we can also still access this via `self` after the rest is done.
+        let _val = self.bins[0].top.get();
+    }
+}
+
+// Make sure to involve `Box` in allocating these,
+// as that's where `noalias` may come from.
+fn v1<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
+    (Box::new_in([t], a) as Box<[T], A>).into_vec()
+}
+fn v2<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
+    let v = v1(t, a);
+    // There was a bug in `into_boxed_slice` that caused aliasing issues,
+    // so round-trip through that as well.
+    v.into_boxed_slice().into_vec()
+}
+
+fn main() {
+    assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works
+    let my_alloc = MyAllocator::new();
+    let a = v1(1usize, &my_alloc);
+    let b = v2(2usize, &my_alloc);
+    assert_eq!(a[0] + 1, b[0]);
+    assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0]));
+    drop((a, b));
+}
diff --git a/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.stack.stderr
new file mode 100644
index 0000000..12fb116
--- /dev/null
+++ b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.stack.stderr
@@ -0,0 +1,37 @@
+error: Undefined Behavior: attempting a read access using <TAG> at ALLOC[RANGE], but that tag does not exist in the borrow stack for this location
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |         let thread_id = ptr::read(ptr::addr_of!((*their_bin).thread_id));
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of an access at ALLOC[RANGE]
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created by a Unique retag at offsets [RANGE]
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |     (Box::new_in([t], a) as Box<[T], A>).into_vec()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: stack backtrace:
+           0: <MyAllocator as std::alloc::Allocator>::deallocate
+               at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+           1: <&MyAllocator as std::alloc::Allocator>::deallocate
+               at RUSTLIB/core/src/alloc/mod.rs:LL:CC
+           2: alloc::raw_vec::RawVecInner::<&MyAllocator>::deallocate
+               at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC
+           3: <alloc::raw_vec::RawVec<usize, &MyAllocator> as std::ops::Drop>::drop
+               at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC
+           4: std::ptr::drop_glue::<alloc::raw_vec::RawVec<usize, &MyAllocator>> - shim(Some(alloc::raw_vec::RawVec<usize, &MyAllocator>))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           5: std::ptr::drop_glue::<std::vec::Vec<usize, &MyAllocator>> - shim(Some(std::vec::Vec<usize, &MyAllocator>))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           6: std::ptr::drop_glue::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> - shim(Some((std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           7: std::mem::drop::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)>
+               at RUSTLIB/core/src/mem/mod.rs:LL:CC
+           8: main
+               at tests/fail/both_borrows/box-custom-alloc-aliasing.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/both_borrows/box-custom-alloc-aliasing.tree.stderr b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.tree.stderr
new file mode 100644
index 0000000..44b7c2c
--- /dev/null
+++ b/src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.tree.stderr
@@ -0,0 +1,52 @@
+error: Undefined Behavior: read access through <TAG> at ALLOC[RANGE] is forbidden
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |         let top = top_ptr.read();
+   |                   ^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
+   = help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
+   = help: the conflicting tag <TAG> has state Disabled which forbids this child read access
+help: the accessed tag <TAG> was created here
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |     unsafe fn push(&self, ptr: NonNull<u8>) {
+   |                    ^^^^^
+help: the conflicting tag <TAG> was created here, in the initial state Reserved
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |     (Box::new_in([t], a) as Box<[T], A>).into_vec()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [RANGE]
+  --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+   |
+LL |         self.top.set(top + 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+   = help: this transition corresponds to a loss of read and write permissions
+   = note: stack backtrace:
+           0: MyBin::push
+               at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+           1: <MyAllocator as std::alloc::Allocator>::deallocate
+               at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC
+           2: <&MyAllocator as std::alloc::Allocator>::deallocate
+               at RUSTLIB/core/src/alloc/mod.rs:LL:CC
+           3: alloc::raw_vec::RawVecInner::<&MyAllocator>::deallocate
+               at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC
+           4: <alloc::raw_vec::RawVec<usize, &MyAllocator> as std::ops::Drop>::drop
+               at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC
+           5: std::ptr::drop_glue::<alloc::raw_vec::RawVec<usize, &MyAllocator>> - shim(Some(alloc::raw_vec::RawVec<usize, &MyAllocator>))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           6: std::ptr::drop_glue::<std::vec::Vec<usize, &MyAllocator>> - shim(Some(std::vec::Vec<usize, &MyAllocator>))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           7: std::ptr::drop_glue::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> - shim(Some((std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)))
+               at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+           8: std::mem::drop::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)>
+               at RUSTLIB/core/src/mem/mod.rs:LL:CC
+           9: main
+               at tests/fail/both_borrows/box-custom-alloc-aliasing.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/c-variadic-ignored-argument.rs b/src/tools/miri/tests/fail/c-variadic-ignored-argument.rs
new file mode 100644
index 0000000..77dab90
--- /dev/null
+++ b/src/tools/miri/tests/fail/c-variadic-ignored-argument.rs
@@ -0,0 +1,13 @@
+#![feature(c_variadic)]
+
+// While 1-ZST are currently ignored on most ABIs, we don't guarantee that, and it's UB to
+// rely on it.
+
+fn main() {
+    unsafe extern "C" fn variadic(mut ap: ...) {
+        ap.next_arg::<i32>();
+        ap.next_arg::<i32>(); //~ERROR: requested `i32` is incompatible with next argument of type `()`
+    }
+
+    unsafe { variadic(0i32, (), 1i32) }
+}
diff --git a/src/tools/miri/tests/fail/c-variadic-ignored-argument.stderr b/src/tools/miri/tests/fail/c-variadic-ignored-argument.stderr
new file mode 100644
index 0000000..6c12916
--- /dev/null
+++ b/src/tools/miri/tests/fail/c-variadic-ignored-argument.stderr
@@ -0,0 +1,18 @@
+error: Undefined Behavior: va_arg type mismatch: requested `i32` is incompatible with next argument of type `()`
+  --> tests/fail/c-variadic-ignored-argument.rs:LL:CC
+   |
+LL |         ap.next_arg::<i32>();
+   |         ^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = 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: stack backtrace:
+           0: main::variadic
+               at tests/fail/c-variadic-ignored-argument.rs:LL:CC
+           1: main
+               at tests/fail/c-variadic-ignored-argument.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/data_race/dangling_thread_async_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
index fbb2c01..4e0268f 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
@@ -25,7 +25,7 @@ fn main() {
 
     // Detach the thread and sleep until it terminates
     mem::drop(join);
-    sleep(Duration::from_millis(200));
+    sleep(Duration::from_millis(100));
 
     // Spawn and immediately join a thread
     // to execute the join code-path
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
index 7431bc5..1c0a1cd 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
@@ -25,7 +25,7 @@ fn main() {
 
     // Detach the thread and sleep until it terminates
     mem::drop(join);
-    sleep(Duration::from_millis(200));
+    sleep(Duration::from_millis(100));
 
     // Spawn and immediately join a thread
     // to execute the join code-path
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
index 76c26da..688824c 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
@@ -34,7 +34,7 @@ fn main() {
 
                 pointer.store(&mut stack_var as *mut _, Ordering::Release);
 
-                sleep(Duration::from_millis(200));
+                sleep(Duration::from_millis(100));
 
                 // Now `stack_var` gets deallocated.
             } //~ ERROR: Data race detected between (1) non-atomic read on thread `unnamed-2` and (2) deallocation on thread `unnamed-1`
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
index bdc2510..4500e5e 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
@@ -34,7 +34,7 @@ fn main() {
 
                 pointer.store(&mut stack_var as *mut _, Ordering::Release);
 
-                sleep(Duration::from_millis(200));
+                sleep(Duration::from_millis(100));
 
                 // Now `stack_var` gets deallocated.
             } //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) deallocation on thread `unnamed-1`
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
index 4555a82..035952b 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
@@ -39,7 +39,7 @@ fn main() {
 
             pointer.store(&mut stack_var as *mut _, Ordering::Release);
 
-            sleep(Duration::from_millis(200));
+            sleep(Duration::from_millis(100));
 
             stack_var //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) non-atomic read on thread `unnamed-1`
         });
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.rs b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
index 5016617..f5c4ed3 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
@@ -31,7 +31,7 @@ fn main() {
             let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
-            sleep(Duration::from_millis(200));
+            sleep(Duration::from_millis(100));
             SYNC.store(3, Ordering::Relaxed);
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
index b92d17b..843cf1f 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
@@ -39,7 +39,7 @@ fn main() {
 
             pointer.store(&mut stack_var as *mut _, Ordering::Release);
 
-            sleep(Duration::from_millis(200));
+            sleep(Duration::from_millis(100));
 
             stack_var = 1usize; //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) non-atomic write on thread `unnamed-1`
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs
new file mode 100644
index 0000000..064b5a5
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs
@@ -0,0 +1,19 @@
+#![feature(fn_traits, unboxed_closures)]
+
+use std::mem::transmute;
+
+#[repr(align(4))]
+struct Zst;
+
+fn foo<F: FnOnce()>(_: F) {
+    // Calls the given F FnOnce, but passing an over-aligned ZST instead of the closure / function item
+    let f = unsafe { transmute::<extern "rust-call" fn(F, ()), fn(Zst)>(F::call_once) };
+    f(Zst)
+}
+
+fn main() {
+    foo(move || {
+        //~^ERROR: /calling a function whose parameter #1 has type .* passing argument of type Zst/
+        println!("non-capturing closure");
+    });
+}
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.stderr
new file mode 100644
index 0000000..56f56e6
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_closure_non_capturing.stderr
@@ -0,0 +1,26 @@
+error: Undefined Behavior: calling a function whose parameter #1 has type {closure@tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs:LL:CC} passing argument of type Zst
+  --> tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs:LL:CC
+   |
+LL |       foo(move || {
+   |  _________^
+LL | |
+LL | |         println!("non-capturing closure");
+LL | |     });
+   | |_____^ Undefined Behavior occurred here
+   |
+   = 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
+   = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
+   = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::{closure#0}
+               at tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs:LL:CC
+           1: foo::<{closure@tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs:LL:CC}>
+               at tests/fail/function_pointers/abi_mismatch_closure_non_capturing.rs:LL:CC
+           2: main
+               at tests/fail/function_pointers/abi_mismatch_closure_non_capturing.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/validity/fn_arg_never_type.rs b/src/tools/miri/tests/fail/validity/fn_arg_never_type.rs
new file mode 100644
index 0000000..a6ffb32
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/fn_arg_never_type.rs
@@ -0,0 +1,13 @@
+use std::mem::transmute;
+
+enum Never {}
+
+fn foo(x: Never) { //~ERROR: invalid value of type Never
+    let ptr = &raw const x;
+    println!("{ptr:p}");
+}
+
+fn main() {
+    let f = unsafe { transmute::<fn(Never), fn(())>(foo) };
+    f(());
+}
diff --git a/src/tools/miri/tests/fail/validity/fn_arg_never_type.stderr b/src/tools/miri/tests/fail/validity/fn_arg_never_type.stderr
new file mode 100644
index 0000000..2995492
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/fn_arg_never_type.stderr
@@ -0,0 +1,18 @@
+error: Undefined Behavior: constructing invalid value of type Never: encountered a value of zero-variant enum `Never`
+  --> tests/fail/validity/fn_arg_never_type.rs:LL:CC
+   |
+LL | fn foo(x: Never) {
+   |        ^ Undefined Behavior occurred here
+   |
+   = 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: stack backtrace:
+           0: foo
+               at tests/fail/validity/fn_arg_never_type.rs:LL:CC
+           1: main
+               at tests/fail/validity/fn_arg_never_type.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/pass-dep/concurrency/apple-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/apple-futex.rs
index a28f08c..0205159 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/apple-futex.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/apple-futex.rs
@@ -62,7 +62,7 @@ fn wait_timeout() {
 
     let futex: i32 = 123;
 
-    // Wait for 200ms, with nobody waking us up early.
+    // Wait for 100ms, with nobody waking us up early.
     unsafe {
         assert_eq!(
             libc::os_sync_wait_on_address_with_timeout(
@@ -71,14 +71,14 @@ fn wait_timeout() {
                 size_of::<i32>(),
                 libc::OS_SYNC_WAIT_ON_ADDRESS_NONE,
                 libc::OS_CLOCK_MACH_ABSOLUTE_TIME,
-                200_000_000,
+                100_000_000,
             ),
             -1,
         );
         assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
     }
 
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
 }
 
 fn wait_absolute_timeout() {
@@ -88,15 +88,15 @@ fn wait_absolute_timeout() {
     #[allow(deprecated)]
     let mut deadline = unsafe { libc::mach_absolute_time() };
 
-    // Add 200ms.
+    // Add 100ms.
     // What we should be doing here is call `mach_timebase_info` to determine the
     // unit used for `deadline`, but we know what Miri returns for that function:
     // the unit is nanoseconds.
-    deadline += 200_000_000;
+    deadline += 100_000_000;
 
     let futex: i32 = 123;
 
-    // Wait for 200ms from now, with nobody waking us up early.
+    // Wait for 100ms from now, with nobody waking us up early.
     unsafe {
         assert_eq!(
             libc::os_sync_wait_on_address_with_deadline(
@@ -112,16 +112,14 @@ fn wait_absolute_timeout() {
         assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
     }
 
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
 }
 
 fn wait_wake() {
-    let start = Instant::now();
-
     static mut FUTEX: i32 = 0;
 
     let t = thread::spawn(move || {
-        thread::sleep(Duration::from_millis(200));
+        thread::sleep(Duration::from_millis(100));
         unsafe {
             assert_eq!(
                 libc::os_sync_wake_by_address_any(
@@ -134,6 +132,8 @@ fn wait_wake() {
         }
     });
 
+    let start = Instant::now();
+
     unsafe {
         assert_eq!(
             libc::os_sync_wait_on_address(
@@ -146,9 +146,7 @@ fn wait_wake() {
         );
     }
 
-    // When running this in stress-gc mode, things can take quite long.
-    // So the timeout is 3000 ms.
-    assert!((200..3000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
     t.join().unwrap();
 }
 
diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
index 19d86f0..5b7a2b7 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
@@ -78,7 +78,7 @@ fn wait_timeout() {
 
     let futex: i32 = 123;
 
-    // Wait for 200ms, with nobody waking us up early.
+    // Wait for 100ms, with nobody waking us up early.
     unsafe {
         assert_eq!(
             libc::syscall(
@@ -86,17 +86,19 @@ fn wait_timeout() {
                 addr_of!(futex),
                 libc::FUTEX_WAIT,
                 123,
-                &libc::timespec { tv_sec: 0, tv_nsec: 200_000_000 },
+                &libc::timespec { tv_sec: 0, tv_nsec: 100_000_000 },
             ),
             -1,
         );
         assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
     }
 
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
 }
 
 fn wait_absolute_timeout() {
+    static mut FUTEX: i32 = 123;
+
     let start = Instant::now();
 
     // Get the current monotonic timestamp as timespec.
@@ -106,21 +108,19 @@ fn wait_absolute_timeout() {
         now.assume_init()
     };
 
-    // Add 200ms.
-    timeout.tv_nsec += 200_000_000;
+    // Add 100ms.
+    timeout.tv_nsec += 100_000_000;
     if timeout.tv_nsec > 1_000_000_000 {
         timeout.tv_nsec -= 1_000_000_000;
         timeout.tv_sec += 1;
     }
 
-    let futex: i32 = 123;
-
-    // Wait for 200ms from now, with nobody waking us up early.
+    // Wait for 100ms from now, with nobody waking us up early.
     unsafe {
         assert_eq!(
             libc::syscall(
                 libc::SYS_futex,
-                addr_of!(futex),
+                addr_of!(FUTEX),
                 libc::FUTEX_WAIT_BITSET,
                 123,
                 &timeout,
@@ -132,16 +132,14 @@ fn wait_absolute_timeout() {
         assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
     }
 
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
 }
 
 fn wait_wake() {
-    let start = Instant::now();
-
     static mut FUTEX: i32 = 0;
 
     let t = thread::spawn(move || {
-        thread::sleep(Duration::from_millis(200));
+        thread::sleep(Duration::from_millis(100));
         unsafe {
             assert_eq!(
                 libc::syscall(
@@ -155,6 +153,8 @@ fn wait_wake() {
         }
     });
 
+    let start = Instant::now();
+
     unsafe {
         assert_eq!(
             libc::syscall(
@@ -168,19 +168,15 @@ fn wait_wake() {
         );
     }
 
-    // When running this in stress-gc mode, things can take quite long.
-    // So the timeout is 3000 ms.
-    assert!((200..3000).contains(&start.elapsed().as_millis()));
+    assert!((100..1000).contains(&start.elapsed().as_millis()));
     t.join().unwrap();
 }
 
 fn wait_wake_bitset() {
-    let start = Instant::now();
-
     static mut FUTEX: i32 = 0;
 
     let t = thread::spawn(move || {
-        thread::sleep(Duration::from_millis(200));
+        thread::sleep(Duration::from_millis(100));
         unsafe {
             assert_eq!(
                 libc::syscall(
@@ -195,7 +191,7 @@ fn wait_wake_bitset() {
                 0, // Didn't match any thread.
             );
         }
-        thread::sleep(Duration::from_millis(200));
+        thread::sleep(Duration::from_millis(100));
         unsafe {
             assert_eq!(
                 libc::syscall(
@@ -212,6 +208,8 @@ fn wait_wake_bitset() {
         }
     });
 
+    let start = Instant::now();
+
     unsafe {
         assert_eq!(
             libc::syscall(
@@ -227,7 +225,7 @@ fn wait_wake_bitset() {
         );
     }
 
-    assert!((400..1000).contains(&start.elapsed().as_millis()));
+    assert!((200..1000).contains(&start.elapsed().as_millis()));
     t.join().unwrap();
 }
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
index 8865c60..f9794d7 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs
@@ -1,6 +1,7 @@
 //@only-target: linux android illumos
 // test_epoll_block_then_unblock and test_epoll_race depend on a deterministic schedule.
 //@compile-flags: -Zmiri-deterministic-concurrency
+//@revisions: edge_triggered level_triggered
 
 use std::convert::TryInto;
 use std::thread;
@@ -10,6 +11,10 @@
 use libc_utils::epoll::*;
 use libc_utils::*;
 
+/// When the `edge_triggered` revision is active, this is EPOLLET, otherwise
+/// it's zero which means we perform level-triggered epolls.
+const EPOLLET_OR_ZERO: libc::c_int = if cfg!(edge_triggered) { EPOLLET } else { 0 };
+
 // This is a set of testcases for blocking epoll.
 
 fn main() {
@@ -21,7 +26,9 @@ fn main() {
     multiple_events_wake_multiple_threads();
 }
 
-// This test allows epoll_wait to block, then unblock without notification.
+// This test allows edge-triggered epoll_wait to block and then unblock
+// without notification because the timeout expired.
+// The level-triggered epoll_wait should not block.
 fn test_epoll_block_without_notification() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
@@ -31,16 +38,24 @@ fn test_epoll_block_without_notification() {
     let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap();
 
     // Register eventfd with epoll.
-    epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // epoll_wait to clear notification.
-    check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fd }], 0);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fd }], -1);
 
-    // This epoll wait blocks, and timeout without notification.
-    check_epoll_wait::<1>(epfd, &[], 5);
+    if cfg!(edge_triggered) {
+        // This epoll wait blocks, and timeout without notification.
+        check_epoll_wait(epfd, &[], 5);
+    } else {
+        // In level-triggered mode we should receive the same events
+        // as before without timing out.
+        check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fd }], -1);
+    }
 }
 
-// This test triggers notification and unblocks the epoll_wait before timeout.
+// This test triggers notification and unblocks the edge-triggered epoll_wait
+// before the timeout exceeds.
+// The level-triggered epoll_wait should not block.
 fn test_epoll_block_then_unblock() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
@@ -50,21 +65,33 @@ fn test_epoll_block_then_unblock() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register one side of the socketpair with epoll.
-    epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // epoll_wait to clear notification.
-    check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fds[0] }], 0);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1);
 
-    // epoll_wait before triggering notification so it will block then get unblocked before timeout.
     let thread1 = thread::spawn(move || {
         thread::yield_now();
+        // Due to deterministic concurrency, we'll only get here when the other thread blocks.
         write_all(fds[1], b"abcde").unwrap();
     });
-    check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[0] }], 10);
+
+    if cfg!(edge_triggered) {
+        // Edge-triggered epoll will block until the write succeeds and the buffer
+        // becomes readable. This is because we already read the writable edge
+        // before so at the time of calling `epoll_wait` there is no active readiness.
+        check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }], 10);
+    } else {
+        // Level-triggered epoll won't wait for the write to succeed because
+        // _some_ readiness is already set (in this case the EPOLLOUT).
+        check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1);
+    }
+
     thread1.join().unwrap();
 }
 
-// This test triggers a notification after epoll_wait times out.
+// This test triggers a notification after epoll_wait times out in edge-triggered mode.
+// In level-triggered the epoll_wait should not time out.
 fn test_notification_after_timeout() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
@@ -74,19 +101,26 @@ fn test_notification_after_timeout() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register one side of the socketpair with epoll.
-    epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // epoll_wait to clear notification.
-    check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fds[0] }], 0);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1);
 
-    // epoll_wait timeouts without notification.
-    check_epoll_wait::<1>(epfd, &[], 10);
+    if cfg!(edge_triggered) {
+        // Edge-triggered epoll wait times out without notification because
+        // we just processed the edge.
+        check_epoll_wait(epfd, &[], 10);
+    } else {
+        // Level-triggered epoll just returns the same events as before
+        // without blocking.
+        check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1);
+    }
 
     // Trigger epoll notification after timeout.
     write_all(fds[1], b"abcde").unwrap();
 
     // Check the result of the notification.
-    check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[0] }], 10);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }], 10);
 }
 
 // This test shows a data race before epoll had vector clocks added.
@@ -99,7 +133,7 @@ fn test_epoll_race() {
     let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap();
 
     // Register eventfd with the epoll instance.
-    epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLET_OR_ZERO).unwrap();
 
     static mut VAL: u8 = 0;
     let thread1 = thread::spawn(move || {
@@ -110,7 +144,7 @@ fn test_epoll_race() {
     });
     thread::yield_now();
     // epoll_wait for EPOLLIN.
-    check_epoll_wait::<8>(epfd, &[Ev { events: libc::EPOLLIN, data: fd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: fd }], -1);
     // Read from the static mut variable.
     assert_eq!(unsafe { VAL }, 1);
     thread1.join().unwrap();
@@ -131,18 +165,14 @@ fn wakeup_on_new_interest() {
 
     // Block a thread on the epoll instance.
     let t = std::thread::spawn(move || {
-        check_epoll_wait::<8>(
-            epfd,
-            &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[1] }],
-            -1,
-        );
+        check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }], -1);
     });
     // Ensure the thread is blocked.
     std::thread::yield_now();
 
-    // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP
-    epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP)
-        .unwrap();
+    // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET if we're in the
+    // `edge_triggered` revision).
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap();
 
     // This should wake up the thread.
     t.join().unwrap();
@@ -161,13 +191,12 @@ fn multiple_events_wake_multiple_threads() {
     let fd2 = errno_result(unsafe { libc::dup(fd1) }).unwrap();
 
     // Register both with epoll.
-    epoll_ctl_add(epfd, fd1, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    epoll_ctl_add(epfd, fd2, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, fd2, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Consume the initial events.
-    let expected =
-        [Ev { events: libc::EPOLLOUT, data: fd1 }, Ev { events: libc::EPOLLOUT, data: fd2 }];
-    check_epoll_wait::<8>(epfd, &expected, -1);
+    let expected = [Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }];
+    check_epoll_wait(epfd, &expected, -1);
 
     // Block two threads on the epoll, both wanting to get just one event.
     let t1 = thread::spawn(move || {
@@ -191,6 +220,7 @@ fn multiple_events_wake_multiple_threads() {
     // Both threads should have been woken up so that both events can be consumed.
     let e1 = t1.join().unwrap();
     let e2 = t2.join().unwrap();
-    // Ensure that across the two threads we got both events.
+
+    // In both modes we should get both events across the two threads.
     assert!(expected == [e1, e2] || expected == [e2, e1]);
 }
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
index e8f54bf..c1d6f91 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
@@ -1,12 +1,15 @@
 //@only-target: linux android illumos
-
-use std::convert::TryInto;
+//@revisions: edge_triggered level_triggered
 
 #[path = "../../utils/libc.rs"]
 mod libc_utils;
 use libc_utils::epoll::*;
 use libc_utils::*;
 
+/// When the `edge_triggered` revision is active, this is EPOLLET, otherwise
+/// it's zero which means we perform level-triggered epolls.
+const EPOLLET_OR_ZERO: libc::c_int = if cfg!(edge_triggered) { EPOLLET } else { 0 };
+
 fn main() {
     test_epoll_socketpair();
     test_epoll_socketpair_both_sides();
@@ -27,27 +30,13 @@ fn main() {
     test_ready_list_fetching_logic();
     test_epoll_ctl_epfd_equal_fd();
     test_epoll_ctl_notification();
+    test_epoll_mixed_modes();
+    test_epoll_registered_mode_switch();
     test_issue_3858();
     test_issue_4374();
     test_issue_4374_reads();
 }
 
-#[track_caller]
-fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) {
-    let epoll_event = libc::epoll_event { events: 0, u64: 0 };
-    let mut array: [libc::epoll_event; N] = [epoll_event; N];
-    let maxsize = N;
-    let array_ptr = array.as_mut_ptr();
-    let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) };
-    if res < 0 {
-        panic!("epoll_wait failed: {}", std::io::Error::last_os_error());
-    }
-    let got_notifications =
-        unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) };
-    let got_notifications = got_notifications.iter().map(|e| (e.events, e.u64)).collect::<Vec<_>>();
-    assert_eq!(got_notifications, expected_notifications, "got wrong notifications");
-}
-
 fn test_epoll_socketpair() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
@@ -59,14 +48,22 @@ fn test_epoll_socketpair() {
     // Write to fds[0]
     write_all(fds[0], b"abcde").unwrap();
 
-    // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP
-    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP).unwrap();
+    // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET if we're
+    // in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap();
 
     // Check result from epoll_wait.
-    check_epoll_wait_noblock::<8>(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]);
+    check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]);
 
-    // Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing.
-    check_epoll_wait_noblock::<8>(epfd, &[]);
+    if cfg!(edge_triggered) {
+        // Check that this is indeed using "ET" (edge-trigger) semantics: a second wait
+        // should return nothing.
+        check_epoll_wait_noblock(epfd, &[]);
+    } else {
+        // Check that this is indeed using "LT" (level-trigger) semantics: a second wait
+        // should return the same readiness.
+        check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]);
+    }
 
     // Write some more to fds[0].
     write_all(fds[0], b"abcde").unwrap();
@@ -74,14 +71,14 @@ fn test_epoll_socketpair() {
     // This did not change the readiness of fds[1], so we should get no event.
     // However, Linux seems to always deliver spurious events to the peer on each write,
     // so we match that.
-    check_epoll_wait_noblock::<8>(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]);
+    check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]);
 
     // Close the peer socketpair.
     errno_check(unsafe { libc::close(fds[0]) });
 
     // Check result from epoll_wait. We expect to get a read, write, HUP notification from the close
     // since closing an FD always unblocks reads and writes on its peer.
-    check_epoll_wait_noblock::<8>(
+    check_epoll_wait_noblock(
         epfd,
         &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP }],
     );
@@ -98,17 +95,19 @@ fn test_epoll_ctl_mod() {
     let mut fds = [-1, -1];
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
-    // Register fds[1] with EPOLLIN|EPOLLET, and data of "0".
-    epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], Ev { events: EPOLLIN | EPOLLET, data: 0 }).unwrap();
+    // Register fds[1] with EPOLLIN (and EPOLLET if we're in the `edge_triggered` revision), and data of "0".
+    epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], Ev { events: EPOLLIN | EPOLLET_OR_ZERO, data: 0 })
+        .unwrap();
 
     // Check result from epoll_wait. No notification would be returned.
-    check_epoll_wait_noblock::<8>(epfd, &[]);
+    check_epoll_wait_noblock(epfd, &[]);
 
     // Use EPOLL_CTL_MOD to change to EPOLLOUT flag and data.
-    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 1 }).unwrap();
+    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 1 })
+        .unwrap();
 
     // Check result from epoll_wait. EPOLLOUT notification and new data is expected.
-    check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 1 }]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 1 }]);
 
     // Write to fds[1] and read from fds[0] to make the notification ready again
     // (relying on there always being an event when the buffer gets emptied).
@@ -116,16 +115,18 @@ fn test_epoll_ctl_mod() {
     read_exact_array::<3>(fds[0]).unwrap();
 
     // Now that the event is already ready, change the "data" value.
-    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 2 }).unwrap();
+    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 2 })
+        .unwrap();
 
     // Receive event, with latest data value.
-    check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 2 }]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 2 }]);
 
     // Do another update that changes nothing.
-    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 2 }).unwrap();
+    epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 2 })
+        .unwrap();
 
     // This re-triggers the event, even if it's the same flags as before.
-    check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 2 }]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 2 }]);
 }
 
 fn test_epoll_ctl_del() {
@@ -139,18 +140,18 @@ fn test_epoll_ctl_del() {
     // Write to fds[0]
     libc_utils::write_all(fds[0], b"abcde").unwrap();
 
-    // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET
+    // Register fds[1] with EPOLLIN|EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision).
     let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as u32,
+        events: (EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO) as u32,
         u64: u64::try_from(fds[1]).unwrap(),
     };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_eq!(res, 0);
 
     // Test EPOLL_CTL_DEL.
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_DEL, fds[1], &mut ev) };
+    let res = unsafe { libc::epoll_ctl(epfd, EPOLL_CTL_DEL, fds[1], &mut ev) };
     assert_eq!(res, 0);
-    check_epoll_wait::<8>(epfd, &[]);
+    check_epoll_wait_noblock(epfd, &[]);
 }
 
 // This test is for one fd registered under two different epoll instance.
@@ -168,15 +169,14 @@ fn test_two_epoll_instance() {
     // Write to the socketpair.
     libc_utils::write_all(fds[0], b"abcde").unwrap();
 
-    // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET.
-    epoll_ctl_add(epfd1, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    epoll_ctl_add(epfd2, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    // Register one side of the socketpair with EPOLLIN | EPOLLOUT (and EPOLLET
+    // if we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd1, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd2, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Notification should be received from both instance of epoll.
-    let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
-    let expected_value = u64::try_from(fds[1]).unwrap();
-    check_epoll_wait::<8>(epfd1, &[(expected_event, expected_value)]);
-    check_epoll_wait::<8>(epfd2, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd1, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }]);
+    check_epoll_wait_noblock(epfd2, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }]);
 }
 
 // This test is for two same file description registered under the same epoll instance through dup.
@@ -194,24 +194,19 @@ fn test_two_same_fd_in_same_epoll_instance() {
     assert_ne!(newfd, -1);
 
     // Register both fd to the same epoll instance.
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(),
-        u64: 5u64,
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
-    assert_eq!(res, 0);
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) };
-    assert_eq!(res, 0);
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, newfd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Write to the socketpair.
     libc_utils::write_all(fds[0], b"abcde").unwrap();
 
     // Two notification should be received.
-    let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
-    let expected_value = 5u64;
-    check_epoll_wait::<8>(
+    check_epoll_wait_noblock(
         epfd,
-        &[(expected_event, expected_value), (expected_event, expected_value)],
+        &[
+            Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] },
+            Ev { events: EPOLLIN | EPOLLOUT, data: newfd },
+        ],
     );
 }
 
@@ -226,20 +221,19 @@ fn test_epoll_eventfd() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
 
-    // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered`
+    // revision).
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Check result from epoll_wait.
-    let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
-    let expected_value = u64::try_from(fd).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]);
 
     // Write 0 to the eventfd.
     libc_utils::write_all(fd, &0_u64.to_ne_bytes()).unwrap();
 
     // This does not change the status, so we should get no event.
     // However, Linux performs a spurious wakeup.
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]);
 
     // Read from the eventfd.
     libc_utils::read_exact_array::<8>(fd).unwrap();
@@ -247,15 +241,13 @@ fn test_epoll_eventfd() {
     // This consumes the event, so the read status is gone. However, deactivation
     // does not trigger an event.
     // Still, we see a spurious wakeup.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]);
 
     // Write the maximum possible value.
     libc_utils::write_all(fd, &(u64::MAX - 1).to_ne_bytes()).unwrap();
 
     // This reactivates reads, therefore triggering an event. Writing is no longer possible.
-    let expected_event = u32::try_from(libc::EPOLLIN).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN, data: fd }]);
 }
 
 // When read/write happened on one side of the socketpair, only the other side will be notified.
@@ -268,8 +260,8 @@ fn test_epoll_socketpair_both_sides() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register both fd to the same epoll instance.
-    epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Write to fds[1].
     // (We do the write after the register here, unlike in `test_epoll_socketpair`, to ensure
@@ -277,23 +269,28 @@ fn test_epoll_socketpair_both_sides() {
     libc_utils::write_all(fds[1], b"abcde").unwrap();
 
     // Two notification should be received.
-    let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
-    let expected_value0 = fds[0] as u64;
-    let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value1 = fds[1] as u64;
-    check_epoll_wait::<8>(
+    check_epoll_wait_noblock(
         epfd,
-        &[(expected_event0, expected_value0), (expected_event1, expected_value1)],
+        &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }],
     );
 
     // Read from fds[0].
     let buf = libc_utils::read_exact_array::<5>(fds[0]).unwrap();
     assert_eq!(buf, *b"abcde");
 
-    // The state of fds[1] does not change (was writable, is writable).
-    // However, we force a spurious wakeup as the read buffer just got emptied.
-    // fds[0] lost its readability, but becoming less active is not considered an "edge".
-    check_epoll_wait::<8>(epfd, &[(expected_event1, expected_value1)]);
+    if cfg!(edge_triggered) {
+        // The state of fds[1] does not change (was writable, is writable).
+        // However, we force a spurious wakeup as the read buffer just got emptied.
+        // fds[0] lost its readability, but becoming less active is not considered an "edge".
+        check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }])
+    } else {
+        // With level-triggered epoll, only the readable readiness for fds[0] should
+        // no longer be reported. The rest stays the same.
+        check_epoll_wait_noblock(
+            epfd,
+            &[Ev { events: EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }],
+        );
+    }
 }
 
 // When file description is fully closed, epoll_wait should not provide any notification for
@@ -306,8 +303,8 @@ fn test_closed_fd() {
     let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
     let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap();
 
-    // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Write to the eventfd instance.
     libc_utils::write_all(fd, &1_u64.to_ne_bytes()).unwrap();
@@ -316,7 +313,7 @@ fn test_closed_fd() {
     errno_check(unsafe { libc::close(fd) });
 
     // No notification should be provided because the file description is closed.
-    check_epoll_wait::<8>(epfd, &[]);
+    check_epoll_wait_noblock(epfd, &[]);
 }
 
 // When a certain file descriptor registered with epoll is closed, but the underlying file description
@@ -336,16 +333,14 @@ fn test_not_fully_closed_fd() {
     // Dup the fd.
     let newfd = errno_result(unsafe { libc::dup(fd) }).unwrap();
 
-    // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Close the original fd that being used to register with epoll.
     errno_check(unsafe { libc::close(fd) });
 
     // Notification should still be provided because the file description is not closed.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = fd as u64;
-    check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]);
 
     // Write to the eventfd instance to produce notification.
     libc_utils::write_all(newfd, &1_u64.to_ne_bytes()).unwrap();
@@ -354,7 +349,7 @@ fn test_not_fully_closed_fd() {
     errno_check(unsafe { libc::close(newfd) });
 
     // No notification should be provided.
-    check_epoll_wait::<1>(epfd, &[]);
+    check_epoll_wait_noblock(epfd, &[]);
 }
 
 // Each time a notification is provided, it should reflect the file description's readiness
@@ -370,13 +365,8 @@ fn test_event_overwrite() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
 
-    // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(),
-        u64: u64::try_from(fd).unwrap(),
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
-    assert_eq!(res, 0);
+    // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Read from the eventfd instance.
     let mut buf: [u8; 8] = [0; 8];
@@ -384,9 +374,7 @@ fn test_event_overwrite() {
     assert_eq!(res, 8);
 
     // Check result from epoll_wait.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = u64::try_from(fd).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]);
 }
 
 // An epoll notification will be provided for every succesful read in a socketpair.
@@ -400,53 +388,58 @@ fn test_socketpair_read() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register both fd to the same epoll instance.
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(),
-        u64: fds[0] as u64,
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
-    assert_eq!(res, 0);
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(),
-        u64: fds[1] as u64,
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
-    assert_eq!(res, 0);
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Write a bunch of data bytes to fds[1].
     let data = [42u8; 1024];
     libc_utils::write_all(fds[1], &data).unwrap();
 
     // Two notification should be received.
-    let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
-    let expected_value0 = fds[0] as u64;
-    let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value1 = fds[1] as u64;
-    check_epoll_wait::<8>(
+    check_epoll_wait_noblock(
         epfd,
-        &[(expected_event0, expected_value0), (expected_event1, expected_value1)],
+        &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }],
     );
 
     // Read some of the data from fds[0].
     let mut buf = [0; 512];
     libc_utils::read_exact(fds[0], &mut buf).unwrap();
-
-    // fds[1] did not change, it is still writable, so we get no event.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = fds[1] as u64;
-    check_epoll_wait::<8>(epfd, &[]);
+    if cfg!(edge_triggered) {
+        // fds[1] did not change, it is still writable, so we get no event
+        // in edge-triggered mode.
+        check_epoll_wait_noblock(epfd, &[]);
+    } else {
+        // In level-triggered mode we expect the same events as before because
+        // we didn't read everything in the buffer.
+        check_epoll_wait_noblock(
+            epfd,
+            &[
+                Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] },
+                Ev { events: EPOLLOUT, data: fds[1] },
+            ],
+        );
+    }
 
     // Read until the buffer is empty.
     let rest = data.len() - buf.len();
     libc_utils::read_exact(fds[0], &mut buf[..rest]).unwrap();
 
-    // Now we get a notification that fds[1] can be written. This is spurious since it
-    // could already be written before, but Linux seems to always emit a notification for
-    // the writer when a read empties the buffer.
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    if cfg!(edge_triggered) {
+        // Now we get a notification that fds[1] can be written. This is spurious since it
+        // could already be written before, but Linux seems to always emit a notification for
+        // the writer when a read empties the buffer.
+        check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]);
+    } else {
+        // In level-triggered mode we expect the same events as before just without
+        // the readable readiness of fds[0] because we now read everything.
+        check_epoll_wait_noblock(
+            epfd,
+            &[Ev { events: EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }],
+        );
+    }
 }
 
-// This is to test whether flag that we don't register won't trigger notification.
+// This is to test whether a flag that we don't register won't trigger notification.
 fn test_no_notification_for_unregister_flag() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
@@ -455,22 +448,15 @@ fn test_no_notification_for_unregister_flag() {
     let mut fds = [-1, -1];
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
-    // Register fds[0] with EPOLLOUT|EPOLLET.
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(),
-        u64: u64::try_from(fds[0]).unwrap(),
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
-    assert_eq!(res, 0);
+    // Register fds[0] with EPOLLOUT (and EPOLLET when we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fds[0], EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Write to fds[1].
     libc_utils::write_all(fds[1], b"abcde").unwrap();
 
     // Check result from epoll_wait. Since we didn't register EPOLLIN flag, the notification won't
     // contain EPOLLIN even though fds[0] is now readable.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = u64::try_from(fds[0]).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }]);
 }
 
 fn test_epoll_wait_maxevent_zero() {
@@ -500,17 +486,15 @@ fn test_socketpair_epollerr() {
     // EPOLLERR will be triggered if we close peer fd that still has data in its read buffer.
     errno_check(unsafe { libc::close(fds[1]) });
 
-    // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP
-    epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP)
-        .unwrap();
+    // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET when we're in the
+    // `edge_triggered` revision).
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap();
 
     // Check result from epoll_wait.
-    let expected_event = u32::try_from(
-        libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP | libc::EPOLLRDHUP | libc::EPOLLERR,
-    )
-    .unwrap();
-    let expected_value = u64::try_from(fds[0]).unwrap();
-    check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(
+        epfd,
+        &[Ev { events: EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP | EPOLLERR, data: fds[0] }],
+    );
 }
 
 // This is a test for https://github.com/rust-lang/miri/issues/3812,
@@ -524,18 +508,24 @@ fn test_epoll_lost_events() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register both fd to the same epoll instance.
-    epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Two notification should be received. But we only provide buffer for one event.
-    let expected_event0 = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value0 = fds[0] as u64;
-    check_epoll_wait::<1>(epfd, &[(expected_event0, expected_value0)]);
+    check_epoll_wait_partial(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], 1, 0);
 
-    // Previous event should be returned for the second epoll_wait.
-    let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value1 = fds[1] as u64;
-    check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]);
+    if cfg!(edge_triggered) {
+        // Previous event should be returned for the second epoll_wait but because we're
+        // edge-triggered the first event should no longer be returned.
+        check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]);
+    } else {
+        // Both events should be returned in level-triggered mode when
+        // we provide a big enough buffer.
+        check_epoll_wait_noblock(
+            epfd,
+            &[Ev { events: EPOLLOUT, data: fds[1] }, Ev { events: EPOLLOUT, data: fds[0] }],
+        );
+    }
 }
 
 // This is testing if closing an fd that is already in ready list will cause an empty entry in
@@ -551,16 +541,14 @@ fn test_ready_list_fetching_logic() {
     let fd1 = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap();
 
     // Register both fd to the same epoll instance. At this point, both of them are on the ready list.
-    epoll_ctl_add(epfd, fd0, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    epoll_ctl_add(epfd, fd1, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fd0, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Close fd0 so the first entry in the ready list will be empty.
     errno_check(unsafe { libc::close(fd0) });
 
     // Notification for fd1 should be returned.
-    let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value1 = fd1 as u64;
-    check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]);
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd1 }]);
 }
 
 // In epoll_ctl, if the value of epfd equals to fd, EFAULT should be returned.
@@ -570,7 +558,7 @@ fn test_epoll_ctl_epfd_equal_fd() {
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
 
     let array_ptr = std::ptr::without_provenance_mut::<libc::epoll_event>(0x100);
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, epfd, array_ptr) };
+    let res = unsafe { libc::epoll_ctl(epfd, EPOLL_CTL_ADD, epfd, array_ptr) };
     let e = std::io::Error::last_os_error();
     assert_eq!(e.raw_os_error(), Some(libc::EFAULT));
     assert_eq!(res, -1);
@@ -578,7 +566,7 @@ fn test_epoll_ctl_epfd_equal_fd() {
 
 // We previously used check_and_update_readiness the moment a file description is registered in an
 // epoll instance. But this has an unfortunate side effect of returning notification to another
-// epfd that shouldn't receive notification.
+// epfd that shouldn't receive a notification in edge-triggered mode.
 fn test_epoll_ctl_notification() {
     // Create an epoll instance.
     let epfd0 = unsafe { libc::epoll_create1(0) };
@@ -589,24 +577,87 @@ fn test_epoll_ctl_notification() {
     errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
 
     // Register one side of the socketpair with epoll.
-    epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // epoll_wait to clear notification for epfd0.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = fds[0] as u64;
-    check_epoll_wait::<1>(epfd0, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]);
 
     // Create another epoll instance.
     let epfd1 = unsafe { libc::epoll_create1(0) };
     assert_ne!(epfd1, -1);
 
     // Register the same file description for epfd1.
-    epoll_ctl_add(epfd1, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
-    check_epoll_wait::<1>(epfd1, &[(expected_event, expected_value)]);
+    epoll_ctl_add(epfd1, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
+    check_epoll_wait_noblock(epfd1, &[Ev { events: EPOLLOUT, data: fds[0] }]);
 
-    // Previously this epoll_wait will receive a notification, but we shouldn't return notification
-    // for this epfd, because there is no I/O event between the two epoll_wait.
-    check_epoll_wait::<1>(epfd0, &[]);
+    if cfg!(edge_triggered) {
+        // Previously this epoll_wait will receive a notification, but we shouldn't return notification
+        // for this epfd, because there is no I/O event between the two epoll_wait.
+        check_epoll_wait_noblock(epfd0, &[]);
+    } else {
+        // We should still get the same events in level-triggered mode.
+        check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]);
+    }
+}
+
+/// Test storing a level-triggered and an edge-triggered file descriptor
+/// in the same epoll instance and calling `epoll_wait` multiple times.
+fn test_epoll_mixed_modes() {
+    // Create an epoll instance.
+    let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
+
+    // Create a socketpair instance.
+    let mut fds = [-1, -1];
+    errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) });
+
+    // Register both fd to the same epoll instance.
+    // `fds[0]` is added in edge-triggered mode whilst `fds[1]` is added in level-triggered mode.
+    epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET).unwrap();
+    epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | 0).unwrap();
+
+    // Write to `fds[1]`.
+    libc_utils::write_all(fds[1], b"abcde").unwrap();
+
+    // Two events should be received.
+    check_epoll_wait_noblock(
+        epfd,
+        &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }],
+    );
+
+    // If we call epoll_wait again immediately, only the level-triggered interests should be received again.
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]);
+}
+
+/// Test first registering a file descriptor in edge-triggered mode,
+/// then consuming it's readiness and then changing it to level-triggered
+/// mode.
+fn test_epoll_registered_mode_switch() {
+    // Create an eventfd instance.
+    let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
+    let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap();
+
+    // Write 1 to the eventfd instance.
+    libc_utils::write_all(fd, &1_u64.to_ne_bytes()).unwrap();
+
+    // Create an epoll instance.
+    let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
+
+    // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET.
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET).unwrap();
+
+    // Check result from `epoll_wait`.
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]);
+
+    // Because `fd` is registered in edge-triggered mode, the next `epoll_wait` shouldn't
+    // return any events.
+    check_epoll_wait_noblock(epfd, &[]);
+
+    // Update the registration for `fd` to switch to level-triggered mode.
+    epoll_ctl(epfd, EPOLL_CTL_MOD, fd, Ev { events: EPOLLIN | EPOLLOUT, data: fd }).unwrap();
+
+    // Because `fd` is now registered in level-triggered mode, we should see
+    // the same events as from the first `epoll_wait`.
+    check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]);
 }
 
 // Test for ICE caused by weak epoll interest upgrade succeed, but the attempt to retrieve
@@ -623,13 +674,8 @@ fn test_issue_3858() {
     // Create an epoll instance.
     let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap();
 
-    // Register eventfd with EPOLLIN | EPOLLET.
-    let mut ev = libc::epoll_event {
-        events: (libc::EPOLLIN | libc::EPOLLET).cast_unsigned(),
-        u64: u64::try_from(fd).unwrap(),
-    };
-    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
-    assert_eq!(res, 0);
+    // Register eventfd with EPOLLIN (and EPOLLET if we're in the `edge_triggered` revision).
+    epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLET_OR_ZERO).unwrap();
 
     // Dup the epoll instance.
     let newfd = unsafe { libc::dup(epfd) };
@@ -655,7 +701,7 @@ fn test_issue_4374() {
     assert_eq!(unsafe { libc::fcntl(fds[1], libc::F_SETFL, libc::O_NONBLOCK) }, 0);
 
     // Register fds[0] with epoll while it is writable (but not readable).
-    epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Fill up fds[0] so that it is not writable any more.
     let zeros = [0u8; 512];
@@ -668,7 +714,7 @@ fn test_issue_4374() {
     }
 
     // This should have canceled the previous readiness, so now we get nothing.
-    check_epoll_wait::<1>(epfd0, &[]);
+    check_epoll_wait_noblock(epfd0, &[]);
 }
 
 /// Same as above, but for becoming un-readable.
@@ -687,13 +733,11 @@ fn test_issue_4374_reads() {
     libc_utils::write_all(fds[1], b"abcde").unwrap();
 
     // Register fds[0] with epoll while it is readable.
-    epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap();
+    epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap();
 
     // Read fds[0] so it is no longer readable.
     libc_utils::read_exact_array::<5>(fds[0]).unwrap();
 
     // We should now still see a notification, but only about it being writable.
-    let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
-    let expected_value = fds[0] as u64;
-    check_epoll_wait::<1>(epfd0, &[(expected_event, expected_value)]);
+    check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]);
 }
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
index 21e77ff..6745836 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
@@ -2,6 +2,10 @@
 //@ignore-target: solaris # Does not have flock
 //@compile-flags: -Zmiri-disable-isolation
 
+//@revisions: windows_host unix_host
+//@[unix_host] ignore-host: windows
+//@[windows_host] only-host: windows
+
 use std::fs::File;
 use std::os::fd::AsRawFd;
 
@@ -17,12 +21,12 @@ fn main() {
 
     let files: Vec<File> = (0..3).map(|_| File::open(&path).unwrap()).collect();
 
-    // Test that we can apply many shared locks
+    // Test that we can apply many shared locks.
     for file in files.iter() {
         errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_SH) });
     }
 
-    // Test that shared lock prevents exclusive lock
+    // Test that shared lock prevents exclusive lock.
     {
         let fd = files[0].as_raw_fd();
         let err =
@@ -30,18 +34,18 @@ fn main() {
         assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
     }
 
-    // Unlock shared lock
+    // Unlock shared lock.
     for file in files.iter() {
         errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_UN) });
     }
 
-    // Take exclusive lock
+    // Take exclusive lock.
     {
         let fd = files[0].as_raw_fd();
         errno_check(unsafe { libc::flock(fd, libc::LOCK_EX) });
     }
 
-    // Test that shared lock prevents exclusive and shared locks
+    // Test that exclusive lock prevents exclusive and shared locks.
     {
         let fd = files[1].as_raw_fd();
         let err =
@@ -54,9 +58,39 @@ fn main() {
         assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
     }
 
-    // Unlock exclusive lock
+    // Unlock exclusive lock.
     {
         let fd = files[0].as_raw_fd();
         errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) });
+        // Redundant unlock also works.
+        // FIXME(#miri/5074): except on Windows hosts...
+        if !cfg!(windows_host) {
+            errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) });
+        }
+    }
+
+    // Test behavior when we acquire multiple locks on the same FD.
+    // FIXME(#miri/5074): this does not behave correctly on Windows hosts.
+    if !cfg!(windows_host) {
+        let fd1 = files[1].as_raw_fd();
+        let fd2 = files[2].as_raw_fd();
+
+        errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) });
+        // This converts the exclusive lock to a shared lock.
+        errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) });
+        // Now the other fd can have the shared lock as well.
+        errno_check(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) });
+
+        // Reset.
+        errno_check(unsafe { libc::flock(fd1, libc::LOCK_UN) });
+        errno_check(unsafe { libc::flock(fd2, libc::LOCK_UN) });
+
+        // Getting first a shared lock and then upgrading to exclusive should also work.
+        errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) });
+        errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) });
+        // This is truly exclusive: fd2 is locked out.
+        let err =
+            errno_result(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) }).unwrap_err();
+        assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
     }
 }
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
index 9cc8685..d1dbcd1 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
@@ -2,7 +2,7 @@
 //@compile-flags: -Zmiri-disable-isolation
 
 use std::ffi::{CStr, CString, OsString};
-use std::fs::{File, canonicalize, create_dir, remove_dir, remove_file};
+use std::fs::{self, File, canonicalize, create_dir, remove_dir, remove_file};
 use std::io::{Error, ErrorKind, Write};
 use std::os::unix::ffi::OsStrExt;
 use std::os::unix::io::AsRawFd;
@@ -28,6 +28,7 @@ fn main() {
     test_file_open_unix_allow_two_args();
     test_file_open_unix_needs_three_args();
     test_file_open_unix_extra_third_arg();
+    test_file_open_dir();
     #[cfg(target_os = "linux")]
     test_o_tmpfile_flag();
     test_posix_mkstemp();
@@ -68,11 +69,12 @@ fn main() {
     #[cfg(not(target_os = "solaris"))]
     test_pwritev();
     test_pwrite();
+    test_linkat();
 }
 
 #[cfg(target_os = "linux")]
 #[track_caller]
-fn assert_statx_matches_metadata(stx: &libc::statx, meta: &std::fs::Metadata, expected_size: u64) {
+fn assert_statx_matches_metadata(stx: &libc::statx, meta: &fs::Metadata, expected_size: u64) {
     use std::os::unix::fs::MetadataExt;
     let mask = stx.stx_mask;
 
@@ -152,7 +154,7 @@ fn test_statx_on_file_path() {
         assert_eq!(ret, 0, "statx failed: {}", std::io::Error::last_os_error());
 
         let stx = stx.assume_init();
-        let meta = std::fs::metadata(&path).unwrap();
+        let meta = fs::metadata(&path).unwrap();
         assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64);
     }
 
@@ -211,21 +213,46 @@ fn test_file_open_unix_allow_two_args() {
     let path = utils::prepare_with_content("test_file_open_unix_allow_two_args.txt", &[]);
     let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap();
 
-    let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) };
+    let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap();
 }
 
 fn test_file_open_unix_needs_three_args() {
     let path = utils::prepare_with_content("test_file_open_unix_needs_three_args.txt", &[]);
     let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap();
 
-    let _fd = unsafe { libc::open(name.as_ptr(), libc::O_CREAT, 0o666) };
+    let _fd =
+        errno_result(unsafe { libc::open(name.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o666) })
+            .unwrap();
 }
 
 fn test_file_open_unix_extra_third_arg() {
     let path = utils::prepare_with_content("test_file_open_unix_extra_third_arg.txt", &[]);
     let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap();
 
-    let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) };
+    let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap();
+}
+
+fn test_file_open_dir() {
+    let dir_path = utils::prepare_dir("miri_test_fs_dir");
+    create_dir(&dir_path).unwrap();
+    let dir_name = CString::new(dir_path.into_os_string().into_encoded_bytes()).unwrap();
+
+    // Opening it for read-write fails. The error code differs between Unix and Windows hosts.
+    let err = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDWR) }).unwrap_err();
+    assert!(
+        [libc::EISDIR, libc::EPERM].contains(&err.raw_os_error().unwrap()),
+        "unexpected errno: {err}"
+    );
+
+    // Opening it for reading succeeds, but then reading fails.
+    // FIXME: currently does not behave as expected on Windows hosts.
+    // See <https://github.com/rust-lang/miri/issues/5084>.
+    // let fd = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDONLY) }).unwrap();
+    // let mut buf = [0u8; 4];
+    // let err =
+    //     errno_result(unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) }).unwrap_err();
+    // assert_eq!(err.raw_os_error().unwrap(), libc::EISDIR, "unexpected errno: {err}");
+    // libc_utils::errno_check(unsafe { libc::close(fd) });
 }
 
 fn test_dup_stdout_stderr() {
@@ -1147,3 +1174,32 @@ fn test_pwrite() {
     // The write should start at the provided byte offset.
     assert_eq!(&write_buffer[0..bytes_written], &read_buffer[OFFSET..(bytes_written + OFFSET)]);
 }
+
+fn test_linkat() {
+    let source = utils::prepare_with_content("miri_test_libc_linkat_source.txt", b"hello");
+    let link = utils::prepare("miri_test_libc_linkat_link.txt");
+
+    let c_source = CString::new(source.as_os_str().as_bytes()).expect("CString::new failed");
+    let c_link = CString::new(link.as_os_str().as_bytes()).expect("CString::new failed");
+
+    // Call linkat
+    unsafe {
+        libc_utils::errno_check(libc::linkat(
+            libc::AT_FDCWD,
+            c_source.as_ptr(),
+            libc::AT_FDCWD,
+            c_link.as_ptr(),
+            0,
+        ));
+    }
+
+    // Verify that the hard link works:
+    // Modifications to one are visible through the other.
+    fs::write(&source, b"hello world").unwrap();
+    let contents = fs::read(&link).unwrap();
+    assert_eq!(contents, b"hello world");
+
+    // Cleanup
+    remove_file(&source).unwrap();
+    remove_file(&link).unwrap();
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs
index e615f1d..80b92e6 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs
@@ -61,7 +61,7 @@ fn test_connect_nonblock() {
     epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | EPOLLERR).unwrap();
 
     // Wait until we are done connecting.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
 
     // There should be no error during async connection.
     let errno =
@@ -95,7 +95,7 @@ fn test_accept_nonblock() {
         epoll_ctl_add(epfd, server_sockfd, EPOLLIN | EPOLLET | EPOLLERR).unwrap();
 
         // Wait until we get a readable event on the server socket.
-        check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: server_sockfd }], -1);
+        check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: server_sockfd }], -1);
 
         // Accepting should now be possible.
         net::accept_ipv4(server_sockfd).unwrap();
@@ -149,7 +149,7 @@ fn test_connect_nonblock_err() {
     epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap();
 
     // Wait until the socket has an error.
-    check_epoll_wait::<8>(
+    check_epoll_wait(
         epfd,
         &[Ev { events: libc::EPOLLERR | EPOLLOUT | EPOLLHUP, data: client_sockfd }],
         -1,
@@ -229,7 +229,7 @@ fn test_recv_nonblock() {
             Ok(received) => bytes_received += received as usize,
             Err(err) if err.kind() == ErrorKind::WouldBlock => {
                 // Use epoll to block until there's data available again.
-                check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
+                check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
             }
             Err(err) => panic!("unexpected error whilst receiving: {err}"),
         }
@@ -339,7 +339,7 @@ fn test_send_nonblock() {
     });
 
     // Wait until the socket is again writable.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
 
     let fill_buf = [1u8; 100];
     // We should be able to write again without blocking because we just received
@@ -371,7 +371,7 @@ fn test_shutdown_read_write() {
     unsafe { libc::shutdown(client_sockfd, libc::SHUT_RDWR) };
 
     // Ensure that the "read end closed", "write end closed", and "readable" readiness are set.
-    check_epoll_wait::<8>(
+    check_epoll_wait(
         epfd,
         &[Ev { events: EPOLLRDHUP | EPOLLHUP | EPOLLIN, data: client_sockfd }],
         -1,
@@ -399,7 +399,7 @@ fn test_shutdown_read() {
     unsafe { libc::shutdown(client_sockfd, libc::SHUT_RD) };
 
     // Ensure that the "read end closed" readiness is set.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1);
 
     server_thread.join().unwrap();
 }
@@ -425,7 +425,7 @@ fn test_shutdown_write() {
 
     // Ensure that the "read end closed" readiness is set when
     // the write end of the peer is closed.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1);
 
     server_thread.join().unwrap();
 }
@@ -460,7 +460,7 @@ fn test_readiness_after_short_read() {
     epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLIN).unwrap();
 
     // Wait until the socket becomes readable.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
 
     let mut buffer = [0u8; 1024];
 
@@ -499,7 +499,7 @@ fn test_readiness_after_short_read() {
 
     // Wait until the client socket becomes readable again.
     // If this blocks indefinitely, Miri lost track of the proper status of this socket.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1);
 
     // Now we can read the 2nd chunk of data.
     unsafe {
@@ -583,7 +583,7 @@ fn test_readiness_after_short_write() {
     epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLOUT).unwrap();
 
     // Wait until the socket becomes writable.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
 
     // We now want to fill the write buffer of the socket by repeatedly writing
     // `buffer` into it. The last write should then be a short write.
@@ -630,7 +630,7 @@ fn test_readiness_after_short_write() {
 
     // Wait until the socket becomes writable again.
     // If this blocks indefinitely, Miri lost track of the proper status of this socket.
-    check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
+    check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1);
 
     // We should again be able to write into the socket.
     libc_utils::write_all(client_sockfd, &buffer).unwrap();
diff --git a/src/tools/miri/tests/pass-dep/libc/prctl-threadname.rs b/src/tools/miri/tests/pass-dep/libc/prctl-threadname.rs
index 87ae375..88315fd 100644
--- a/src/tools/miri/tests/pass-dep/libc/prctl-threadname.rs
+++ b/src/tools/miri/tests/pass-dep/libc/prctl-threadname.rs
@@ -1,4 +1,4 @@
-//@only-target: android  # Miri supports prctl for Android only
+//@only-target: linux android  # Linux-specific API
 use std::ffi::{CStr, CString};
 use std::thread;
 
diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs
index 6ac71b5..cf7ea4c 100644
--- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs
+++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs
@@ -1,5 +1,5 @@
 //@ignore-target: windows # No pthreads on Windows
-//@ignore-target: android # No pthread_{get,set}_name on Android
+//@ignore-target: android # No pthread_{get,set}name_np on Android
 use std::ffi::{CStr, CString};
 use std::thread;
 
diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
index 06ddda2..6b33658 100644
--- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
+++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
@@ -1,10 +1,10 @@
 //! Regression test for <https://github.com/rust-lang/miri/issues/3341>:
 //! If `Box` has a local allocator, then it can't be `noalias` as the allocator
 //! may want to access allocator state based on the data pointer.
+//! Ensure that the `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness` flag makes us
+//! accept such code.
 
-//@revisions: stack tree tree_implicit_writes
-//@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes
-//@[tree]compile-flags: -Zmiri-tree-borrows
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-relax-custom-allocator-uniqueness -Zmiri-tree-borrows-implicit-writes
 #![feature(allocator_api)]
 
 use std::alloc::{AllocError, Allocator, Layout};
@@ -46,6 +46,13 @@ unsafe fn push(&self, ptr: NonNull<u8>) {
         let end = start + BIN_SIZE * mem::size_of::<usize>();
         let addr = ptr.addr().get();
         assert!((start..end).contains(&addr));
+
+        // We can't update `top` as this may not be the last bin, but we can pretend to do so
+        // such that the aliasing model checks things.
+        // We access this via raw pointers so that the error span is in this file.
+        let top_ptr = (&raw const self.top) as *mut usize;
+        let top = top_ptr.read();
+        top_ptr.write(top);
     }
 }
 
diff --git a/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs b/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs
deleted file mode 100644
index fe09a03..0000000
--- a/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ ignore-target: windows # does not ignore ZST arguments
-//@ ignore-target: powerpc # does not ignore ZST arguments
-//@ ignore-target: s390x # does not ignore ZST arguments
-//@ ignore-target: sparc # does not ignore ZST arguments
-#![feature(c_variadic)]
-
-// Some platforms ignore ZSTs, meaning that the argument is not passed, even though it is part
-// of the callee's ABI. Test that this doesn't trip any asserts.
-//
-// NOTE: this  test only succeeds when the `()` argument uses `Passmode::Ignore`. For some targets,
-// notably msvc, such arguments are not ignored, which would cause UB when attempting to read the
-// second `i32` argument while the next item in the variable argument list is `()`.
-
-fn main() {
-    unsafe extern "C" fn variadic(mut ap: ...) {
-        ap.next_arg::<i32>();
-        ap.next_arg::<i32>();
-    }
-
-    unsafe { variadic(0i32, (), 1i32) }
-}
diff --git a/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs b/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
index 35145fe9..27efffe 100644
--- a/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
+++ b/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
@@ -5,8 +5,8 @@
 fn main() {
     let start = Instant::now();
 
-    thread::park_timeout(Duration::from_millis(200));
+    thread::park_timeout(Duration::from_millis(100));
 
-    // Thanks to deterministic execution, this will wait *exactly* 200ms, plus the time for the surrounding code.
-    assert!((200..210).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis());
+    // Thanks to deterministic execution, this will wait *exactly* 100ms, plus the time for the surrounding code.
+    assert!((100..110).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis());
 }
diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
index 37795da..94cb569 100644
--- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs
+++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
@@ -151,4 +151,9 @@ fn main() {
     let rc = Rc::new(0);
     let rc_ptr: *mut i32 = unsafe { mem::transmute_copy(&rc) };
     test_abi_compat(rc, rc_ptr);
+
+    // Non-capturing closures are special because we rely on them being `PassMode::Ignore`.
+    // Make sure that does not break newtype wrapping for them.
+    let non_capturing_closure = || {};
+    test_abi_compat(non_capturing_closure.clone(), Wrapper(non_capturing_closure));
 }
diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs
new file mode 100644
index 0000000..1345924
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs
@@ -0,0 +1,45 @@
+// We're testing aarch64 AES target specific features.
+//@only-target: aarch64
+//@compile-flags: -C target-feature=+neon,+aes
+
+use std::arch::aarch64::*;
+use std::arch::is_aarch64_feature_detected;
+
+fn main() {
+    assert!(is_aarch64_feature_detected!("neon"));
+    assert!(is_aarch64_feature_detected!("aes"));
+
+    unsafe {
+        test_vmull_p64();
+        test_vmull_high_p64();
+    }
+}
+
+#[target_feature(enable = "neon,aes")]
+unsafe fn test_vmull_p64() {
+    assert_eq!(vmull_p64(0, 0), 0);
+    assert_eq!(vmull_p64(0, 0xffffffffffffffff), 0);
+    assert_eq!(vmull_p64(1, 1), 1);
+    assert_eq!(vmull_p64(1, 0x8000000000000000), 0x8000000000000000);
+
+    assert_eq!(vmull_p64(0b11, 0b11), 0b101);
+
+    // Check with the same inputs that are used in the x86_64 pclmulqdq test.
+    assert_eq!(
+        vmull_p64(0x7fffffffffffffff, 0xdd358416f52ecd34),
+        (2704901987789626761u128 << 64) | 13036940098130298092u128,
+    );
+}
+
+#[target_feature(enable = "neon,aes")]
+unsafe fn test_vmull_high_p64() {
+    // The lower (first) element is ignored.
+    let a = vcombine_p64(vcreate_p64(123), vcreate_p64(0b11));
+    let b = vcombine_p64(vcreate_p64(456), vcreate_p64(0b11));
+    assert_eq!(vmull_high_p64(a, b), 0b101);
+
+    // Check with the same inputs that are used in the x86_64 pclmulqdq test.
+    let a = vcombine_p64(vcreate_p64(0), vcreate_p64(0x7fffffffffffffff));
+    let b = vcombine_p64(vcreate_p64(0), vcreate_p64(0xdd358416f52ecd34));
+    assert_eq!(vmull_high_p64(a, b), (2704901987789626761u128 << 64) | 13036940098130298092u128);
+}
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 0b0999e..cb1088f 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -38,11 +38,14 @@ fn main() {
     if cfg!(not(windows)) {
         test_directory();
         test_canonicalize();
-        #[cfg(unix)]
-        test_pread_pwrite();
         #[cfg(not(target_os = "solaris"))]
         test_flock();
+        #[cfg(not(target_os = "android"))]
+        test_hard_link();
+
         test_readv_writev();
+        #[cfg(unix)]
+        test_pread_pwrite();
         #[cfg(all(unix, not(any(target_os = "solaris", target_os = "android"))))]
         test_preadv_pwritev();
     }
@@ -221,9 +224,10 @@ fn test_file_set_len() {
     let file = OpenOptions::new().read(true).open(&path).unwrap();
     // Due to https://github.com/rust-lang/miri/issues/4457, we have to assume the failure could
     // be either of the Windows or Unix kind, no matter which platform we're on.
+    let err = file.set_len(14).unwrap_err();
     assert!(
-        [ErrorKind::PermissionDenied, ErrorKind::InvalidInput]
-            .contains(&file.set_len(14).unwrap_err().kind())
+        [ErrorKind::PermissionDenied, ErrorKind::InvalidInput].contains(&err.kind()),
+        "unexpected error: {err}"
     );
 
     remove_file(&path).unwrap();
@@ -415,20 +419,21 @@ fn test_flock() {
     let file1 = OpenOptions::new().read(true).write(true).open(&path).unwrap();
     let file2 = OpenOptions::new().read(true).write(true).open(&path).unwrap();
 
-    // Test that we can apply many shared locks
+    // Test that we can apply many shared locks.
     file1.lock_shared().unwrap();
     file2.lock_shared().unwrap();
-    // Test that shared lock prevents exclusive lock
+    // Test that shared lock prevents exclusive lock.
     assert!(matches!(file1.try_lock().unwrap_err(), fs::TryLockError::WouldBlock));
-    // Unlock shared lock
+    // Unlock both files.
     file1.unlock().unwrap();
     file2.unlock().unwrap();
-    // Take exclusive lock
+
+    // Take exclusive lock.
     file1.lock().unwrap();
-    // Test that shared lock prevents exclusive and shared locks
+    // Test that shared lock prevents exclusive and shared locks.
     assert!(matches!(file2.try_lock().unwrap_err(), fs::TryLockError::WouldBlock));
     assert!(matches!(file2.try_lock_shared().unwrap_err(), fs::TryLockError::WouldBlock));
-    // Unlock exclusive lock
+    // Unlock exclusive lock.
     file1.unlock().unwrap();
 }
 
@@ -510,3 +515,34 @@ fn test_preadv_pwritev() {
     f.read_exact(&mut written_bytes).unwrap();
     assert_eq!(written_bytes.as_slice(), &write_buffer[0..bytes_written]);
 }
+
+// std uses `libc::link` on Android which we do not support.
+#[cfg(not(target_os = "android"))]
+fn test_hard_link() {
+    let source = utils::prepare_with_content("miri_test_fs_hard_link_source.txt", b"hello");
+    let link = utils::prepare("miri_test_fs_hard_link_link.txt");
+
+    fs::hard_link(&source, &link).unwrap();
+
+    // Verify that the hard link works:
+    // Modifications to one are visible through the other.
+    fs::write(&source, b"hello world").unwrap();
+    let contents = fs::read(&link).unwrap();
+    assert_eq!(contents, b"hello world");
+
+    // Only on Unix: verify both files have same inode
+    #[cfg(unix)]
+    {
+        use std::os::unix::fs::MetadataExt;
+        let source_meta = std::fs::metadata(&source).unwrap();
+        let link_meta = std::fs::metadata(&link).unwrap();
+        assert_eq!(source_meta.ino(), link_meta.ino());
+    }
+
+    // Test error: link already exists
+    assert_eq!(ErrorKind::AlreadyExists, fs::hard_link(&source, &link).unwrap_err().kind());
+
+    // Cleanup after test
+    remove_file(&source).unwrap();
+    remove_file(&link).unwrap();
+}
diff --git a/src/tools/miri/tests/pass/shims/loongarch/intrinsics-loongarch64-crc.rs b/src/tools/miri/tests/pass/shims/loongarch/intrinsics-loongarch64-crc.rs
new file mode 100644
index 0000000..cc96653
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/loongarch/intrinsics-loongarch64-crc.rs
@@ -0,0 +1,54 @@
+// We're testing loongarch64-specific intrinsics
+//@only-target: loongarch64
+#![feature(stdarch_loongarch)]
+
+use std::arch::loongarch64::*;
+
+fn main() {
+    test_crc_ieee();
+    test_crc_castagnoli();
+}
+
+fn test_crc_ieee() {
+    // crc.w.b.w: 8-bit input
+    assert_eq!(crc_w_b_w(0x01, 0x00000000), 0x77073096);
+    assert_eq!(crc_w_b_w(0x61, 0xffffffff_u32 as i32), 0x174841bc);
+    assert_eq!(crc_w_b_w(0x2a, 0x2aa1e72b), 0x772d9171);
+
+    // crc.w.h.w: 16-bit input
+    assert_eq!(crc_w_h_w(0x0001, 0x00000000), 0x191b3141);
+    assert_eq!(crc_w_h_w(0x1234, 0xffffffff_u32 as i32), 0xf6b56fbf_u32 as i32);
+    assert_eq!(crc_w_h_w(0x022b, 0x8ecec3b5_u32 as i32), 0x03a1db7c);
+
+    // crc.w.w.w: 32-bit input
+    assert_eq!(crc_w_w_w(0x00000001, 0x00000000), 0xb8bc6765_u32 as i32);
+    assert_eq!(crc_w_w_w(0x12345678, 0xffffffff_u32 as i32), 0x5092782d);
+    assert_eq!(crc_w_w_w(0x00845fed, 0xae2912c8_u32 as i32), 0xc5690dd4_u32 as i32);
+
+    // crc.w.d.w: 64-bit input
+    assert_eq!(crc_w_d_w(0x0000000000000001, 0x00000000), 0xccaa009e_u32 as i32);
+    assert_eq!(crc_w_d_w(0x123456789abcdef0, 0xffffffff_u32 as i32), 0xe6ddf8b5_u32 as i32);
+    assert_eq!(crc_w_d_w(0xc0febeefdadafefe_u64 as i64, 0x0badeafe), 0x61a45fba);
+}
+
+fn test_crc_castagnoli() {
+    // crcc.w.b.w: 8-bit input
+    assert_eq!(crcc_w_b_w(0x01, 0x00000000), 0xf26b8303_u32 as i32);
+    assert_eq!(crcc_w_b_w(0x61, 0xffffffff_u32 as i32), 0x3e2fbccf);
+    assert_eq!(crcc_w_b_w(0x2a, 0x2aa1e72b), 0xf24122e4_u32 as i32);
+
+    // crcc.w.h.w: 16-bit input
+    assert_eq!(crcc_w_h_w(0x0001, 0x00000000), 0x13a29877);
+    assert_eq!(crcc_w_h_w(0x1234, 0xffffffff_u32 as i32), 0xf13f4cea_u32 as i32);
+    assert_eq!(crcc_w_h_w(0x022b, 0x8ecec3b5_u32 as i32), 0x013bb2fb);
+
+    // crcc.w.w.w: 32-bit input
+    assert_eq!(crcc_w_w_w(0x00000001, 0x00000000), 0xdd45aab8_u32 as i32);
+    assert_eq!(crcc_w_w_w(0x12345678, 0xffffffff_u32 as i32), 0x4dece20c);
+    assert_eq!(crcc_w_w_w(0x00845fed, 0xae2912c8_u32 as i32), 0xffae2ed1_u32 as i32);
+
+    // crcc.w.d.w: 64-bit input
+    assert_eq!(crcc_w_d_w(0x0000000000000001, 0x00000000), 0x493c7d27);
+    assert_eq!(crcc_w_d_w(0x123456789abcdef0, 0xffffffff_u32 as i32), 0xd95b664b_u32 as i32);
+    assert_eq!(crcc_w_d_w(0xc0febeefdadafefe_u64 as i64, 0x0badeafe), 0x5b44f54f);
+}
diff --git a/src/tools/miri/tests/utils/libc.rs b/src/tools/miri/tests/utils/libc.rs
index da331a3..f46e6aa 100644
--- a/src/tools/miri/tests/utils/libc.rs
+++ b/src/tools/miri/tests/utils/libc.rs
@@ -164,24 +164,37 @@ pub fn epoll_ctl_add(epfd: c_int, fd: c_int, events: c_int) -> io::Result<()> {
         epoll_ctl(epfd, EPOLL_CTL_ADD, fd, Ev { events, data: fd })
     }
 
+    /// Call `epoll_wait` on `epfd` with the provided `timeout`.
+    /// It fetches at most `max_events` events from `epfd` and
+    /// ensures that the returned events match the `expected` events.
     #[track_caller]
-    pub fn check_epoll_wait<const N: usize>(epfd: i32, expected: &[Ev], timeout: i32) {
-        let mut array: [libc::epoll_event; N] = [libc::epoll_event { events: 0, u64: 0 }; N];
+    pub fn check_epoll_wait_partial(epfd: i32, expected: &[Ev], max_events: usize, timeout: i32) {
+        let mut events = vec![libc::epoll_event { events: 0, u64: 0 }; max_events];
         let num = errno_result(unsafe {
-            libc::epoll_wait(epfd, array.as_mut_ptr(), N.try_into().unwrap(), timeout)
+            libc::epoll_wait(epfd, events.as_mut_ptr(), i32::try_from(max_events).unwrap(), timeout)
         })
         .expect("epoll_wait returned an error");
-        let got = &mut array[..num.try_into().unwrap()];
-        let got = got
+        let got = events
             .iter()
+            .take(num as usize)
             .map(|e| Ev { events: e.events.cast_signed(), data: e.u64.try_into().unwrap() })
             .collect::<Vec<_>>();
-        assert_eq!(got, expected, "got wrong notifications");
+        assert_eq!(got, expected, "got wrong ready events");
     }
 
+    /// Call `epoll_wait` on `epfd` with the provided `timeout` and ensure
+    /// that the set of *all* ready events matches `expected`.
     #[track_caller]
-    pub fn check_epoll_wait_noblock<const N: usize>(epfd: i32, expected: &[Ev]) {
-        check_epoll_wait::<N>(epfd, expected, 0);
+    pub fn check_epoll_wait(epfd: i32, expected: &[Ev], timeout: i32) {
+        // We set `max_events` to `expected.len() + 1` to ensure that there are no additional ready
+        // events besides those which are contained in `expected`.
+        check_epoll_wait_partial(epfd, &expected, expected.len() + 1, timeout);
+    }
+
+    /// This does the same as [`check_epoll_wait`] just without blocking (zero `timeout`).
+    #[track_caller]
+    pub fn check_epoll_wait_noblock(epfd: i32, expected: &[Ev]) {
+        check_epoll_wait(epfd, expected, 0);
     }
 
     /// Query the current epoll readiness of a file descriptor.
diff --git a/src/tools/nix-dev-shell/shell.nix b/src/tools/nix-dev-shell/shell.nix
index 6ca8a7c..199b63e 100644
--- a/src/tools/nix-dev-shell/shell.nix
+++ b/src/tools/nix-dev-shell/shell.nix
@@ -2,7 +2,7 @@
   pkgs ? import <nixpkgs> { },
 }:
 let
-  inherit (pkgs.lib) lists attrsets;
+  inherit (pkgs.lib) lists attrsets makeLibraryPath;
 
   x = pkgs.callPackage ./x { };
   inherit (x.passthru) cacert env;
@@ -25,6 +25,6 @@
     RUSTC_ICE = 0;
     SSL_CERT_FILE = cacert;
     # cargo seems to dlopen libcurl, so we need it in the ld library path
-    LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath [pkgs.stdenv.cc.cc.lib pkgs.curl]}";
+    LD_LIBRARY_PATH = "${makeLibraryPath [pkgs.stdenv.cc.cc.lib pkgs.curl]}";
   };
 }
diff --git a/src/tools/nix-dev-shell/x/default.nix b/src/tools/nix-dev-shell/x/default.nix
index 9573ddd..9151580 100644
--- a/src/tools/nix-dev-shell/x/default.nix
+++ b/src/tools/nix-dev-shell/x/default.nix
@@ -1,5 +1,4 @@
 {
-  pkgs,
   lib,
   stdenv,
   rustc,
@@ -16,7 +15,6 @@
   # LLVM Deps
   ninja,
   cmake,
-  glibc,
 }:
 stdenv.mkDerivation (self: {
   strictDeps = true;
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2b12e65..ef08286 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -133,6 +133,12 @@ pub(crate) struct WorkspaceInfo<'a> {
         submodules: &[],
     },
     WorkspaceInfo {
+        path: "library/stdarch",
+        exceptions: EXCEPTIONS_STDARCH,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
         path: "compiler/rustc_codegen_cranelift",
         exceptions: EXCEPTIONS_CRANELIFT,
         crates_and_deps: Some((
@@ -254,6 +260,8 @@ pub(crate) struct WorkspaceInfo<'a> {
     // tidy-alphabetical-end
 ];
 
+const EXCEPTIONS_STDARCH: ExceptionList = &[];
+
 const EXCEPTIONS_CRANELIFT: ExceptionList = &[];
 
 const EXCEPTIONS_GCC: ExceptionList = &[
diff --git a/tests/assembly-llvm/c-variadic/xtensa.rs b/tests/assembly-llvm/c-variadic/xtensa.rs
new file mode 100644
index 0000000..f775dcc
--- /dev/null
+++ b/tests/assembly-llvm/c-variadic/xtensa.rs
@@ -0,0 +1,140 @@
+//@ add-minicore
+//@ assembly-output: emit-asm
+//@ min-llvm-version: 22
+//
+//@ revisions: XTENSA
+//@ [XTENSA] compile-flags: -Copt-level=3 --target xtensa-esp32-none-elf
+//@ [XTENSA] needs-llvm-components: xtensa
+#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs)]
+#![no_core]
+#![crate_type = "lib"]
+
+// Check that the assembly that rustc generates matches what GCC emits.
+
+extern crate minicore;
+use minicore::*;
+
+pub unsafe trait VaArgSafe {}
+
+unsafe impl VaArgSafe for i32 {}
+unsafe impl VaArgSafe for i64 {}
+unsafe impl VaArgSafe for f64 {}
+unsafe impl<T> VaArgSafe for *const T {}
+
+#[repr(C)]
+struct VaListInner {
+    va_stk: *const c_void,
+    va_reg: *const c_void,
+    va_ndx: i32,
+}
+
+#[repr(transparent)]
+#[lang = "va_list"]
+pub struct VaList<'a> {
+    inner: VaListInner,
+    _marker: PhantomData<&'a mut ()>,
+}
+
+#[rustc_intrinsic]
+#[rustc_nounwind]
+pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
+    // CHECK-LABEL: read_f64
+    //
+    // XTENSA: l32i a8, a2, 8
+    // XTENSA-NEXT: addi a8, a8, 7
+    // XTENSA-NEXT: movi a9, -8
+    // XTENSA-NEXT: and a8, a8, a9
+    // XTENSA-NEXT: addi a10, a8, 8
+    // XTENSA-NEXT: movi a9, 32
+    // XTENSA-NEXT: maxu a9, a8, a9
+    // XTENSA-NEXT: movi a11, 25
+    // XTENSA-NEXT: or a12, a10, a10
+    // XTENSA-NEXT: bltu a10, a11, .LBB0_2
+    // XTENSA-NEXT: addi a12, a9, 8
+    // XTENSA-NEXT: .LBB0_2:
+    // XTENSA-NEXT: s32i a12, a2, 8
+    // XTENSA-NEXT: bltu a10, a11, .LBB0_4
+    // XTENSA-NEXT: l32i a8, a2, 0
+    // XTENSA-NEXT: add a8, a8, a9
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: l32i a3, a8, 4
+    // XTENSA-NEXT: retw.n
+    // XTENSA-NEXT: .LBB0_4:
+    // XTENSA-NEXT: l32i a9, a2, 4
+    // XTENSA-NEXT: add a8, a9, a8
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: l32i a3, a8, 4
+    // XTENSA-NEXT: retw.n
+    va_arg(ap)
+}
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
+    // CHECK-LABEL: read_i32
+    //
+    // XTENSA: l32i a8, a2, 8
+    // XTENSA-NEXT: addi a8, a8, 3
+    // XTENSA-NEXT: movi a9, -4
+    // XTENSA-NEXT: and a8, a8, a9
+    // XTENSA-NEXT: addi a10, a8, 4
+    // XTENSA-NEXT: movi a9, 32
+    // XTENSA-NEXT: maxu a9, a8, a9
+    // XTENSA-NEXT: movi a11, 25
+    // XTENSA-NEXT: or a12, a10, a10
+    // XTENSA-NEXT: bltu a10, a11, .LBB1_2
+    // XTENSA-NEXT: addi a12, a9, 4
+    // XTENSA-NEXT: .LBB1_2:
+    // XTENSA-NEXT: s32i a12, a2, 8
+    // XTENSA-NEXT: bltu a10, a11, .LBB1_4
+    // XTENSA-NEXT: l32i a8, a2, 0
+    // XTENSA-NEXT: add a8, a8, a9
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: retw.n
+    // XTENSA-NEXT: .LBB1_4:
+    // XTENSA-NEXT: l32i a9, a2, 4
+    // XTENSA-NEXT: add a8, a9, a8
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: retw.n
+    va_arg(ap)
+}
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
+    // CHECK-LABEL: read_i64
+    //
+    // XTENSA: l32i a8, a2, 8
+    // XTENSA-NEXT: addi a8, a8, 7
+    // XTENSA-NEXT: movi a9, -8
+    // XTENSA-NEXT: and a8, a8, a9
+    // XTENSA-NEXT: addi a10, a8, 8
+    // XTENSA-NEXT: movi a9, 32
+    // XTENSA-NEXT: maxu a9, a8, a9
+    // XTENSA-NEXT: movi a11, 25
+    // XTENSA-NEXT: or a12, a10, a10
+    // XTENSA-NEXT: bltu a10, a11, .LBB2_2
+    // XTENSA-NEXT: addi a12, a9, 8
+    // XTENSA-NEXT: .LBB2_2:
+    // XTENSA-NEXT: s32i a12, a2, 8
+    // XTENSA-NEXT: bltu a10, a11, .LBB2_4
+    // XTENSA-NEXT: l32i a8, a2, 0
+    // XTENSA-NEXT: add a8, a8, a9
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: l32i a3, a8, 4
+    // XTENSA-NEXT: retw.n
+    // XTENSA-NEXT: .LBB2_4:
+    // XTENSA-NEXT: l32i a9, a2, 4
+    // XTENSA-NEXT: add a8, a9, a8
+    // XTENSA-NEXT: l32i a2, a8, 0
+    // XTENSA-NEXT: l32i a3, a8, 4
+    // XTENSA-NEXT: retw.n
+    va_arg(ap)
+}
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
+    // XTENSA: read_ptr = read_i32
+    va_arg(ap)
+}
diff --git a/tests/assembly-llvm/debuginfo-for-profiling.rs b/tests/assembly-llvm/debuginfo-for-profiling.rs
new file mode 100644
index 0000000..6431142
--- /dev/null
+++ b/tests/assembly-llvm/debuginfo-for-profiling.rs
@@ -0,0 +1,56 @@
+// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`:
+//  - 0 discriminators are emitted without the flag in the test below
+//  - at least 1 discriminator is emitted with the flag in the test below.
+//    Actual count depends on the target
+//
+//
+//@ add-minicore
+//@ revisions: DEFAULT-X86 DEFAULT-AARCH64 DEBUGINFO-X86 DEBUGINFO-AARCH64
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only
+//@ [DEFAULT-X86] compile-flags: --target=x86_64-unknown-linux-gnu
+//@ [DEFAULT-X86] needs-llvm-components: x86
+//@ [DEFAULT-AARCH64] compile-flags: --target=aarch64-unknown-linux-gnu
+//@ [DEFAULT-AARCH64] needs-llvm-components: aarch64
+//@ [DEBUGINFO-X86] compile-flags: -Zdebuginfo-for-profiling --target=x86_64-unknown-linux-gnu
+//@ [DEBUGINFO-X86] needs-llvm-components: x86
+//@ [DEBUGINFO-AARCH64] compile-flags: -Zdebuginfo-for-profiling --target=aarch64-unknown-linux-gnu
+//@ [DEBUGINFO-AARCH64] needs-llvm-components: aarch64
+// DEFAULT-X86-NOT: discriminator
+// DEFAULT-AARCH64-NOT: discriminator
+// DEBUGINFO-X86-COUNT-1: discriminator
+// DEBUGINFO-AARCH64-COUNT-1: discriminator
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+extern "C" {
+    fn add(_x: i32, _y: i32) -> i32;
+    fn mul(_x: i32, _y: i32) -> i32;
+    fn compute(_x: i32) -> i32;
+    fn cond() -> bool;
+}
+
+#[no_mangle]
+pub fn f(limit: i32) -> i32 {
+    unsafe {
+        let mut sum = 0;
+        let mut i = 1;
+
+        while cond() {
+            if cond() {
+                sum = add(sum, compute(i));
+            } else {
+                sum = add(sum, mul(compute(i), 2));
+            }
+            i = add(i, 1);
+        }
+
+        sum
+    }
+}
diff --git a/tests/assembly-llvm/nvptx-arch-default.rs b/tests/assembly-llvm/nvptx-arch-default.rs
index e71304e..a0c2b53 100644
--- a/tests/assembly-llvm/nvptx-arch-default.rs
+++ b/tests/assembly-llvm/nvptx-arch-default.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib
 //@ only-nvptx64
 
@@ -7,7 +7,7 @@
 //@ aux-build: breakpoint-panic-handler.rs
 extern crate breakpoint_panic_handler;
 
-// Verify default target arch with ptx-linker.
+// Verify default arch with llvm-bitcode-linker.
 // CHECK: .version 7.0
 // CHECK: .target sm_70
 // CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-emit-asm.rs b/tests/assembly-llvm/nvptx-arch-emit-asm.rs
index 9266309c..1351496 100644
--- a/tests/assembly-llvm/nvptx-arch-emit-asm.rs
+++ b/tests/assembly-llvm/nvptx-arch-emit-asm.rs
@@ -4,7 +4,7 @@
 
 #![no_std]
 
-// Verify default arch without ptx-linker involved.
+// Verify default arch without llvm-bitcode-linker involved.
 // CHECK: .version 7.0
 // CHECK: .target sm_70
 // CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-link-arg.rs b/tests/assembly-llvm/nvptx-arch-link-arg.rs
deleted file mode 100644
index 3432e61..0000000
--- a/tests/assembly-llvm/nvptx-arch-link-arg.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60
-//@ only-nvptx64
-//@ ignore-nvptx64
-
-#![no_std]
-
-//@ aux-build: breakpoint-panic-handler.rs
-extern crate breakpoint_panic_handler;
-
-// Verify target arch override via `link-arg`.
-// CHECK: .target sm_60
-// CHECK: .address_size 64
diff --git a/tests/assembly-llvm/nvptx-arch-target-cpu.rs b/tests/assembly-llvm/nvptx-arch-target-cpu.rs
index b5062f1..8e1ef9b 100644
--- a/tests/assembly-llvm/nvptx-arch-target-cpu.rs
+++ b/tests/assembly-llvm/nvptx-arch-target-cpu.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib -C target-cpu=sm_87
 //@ only-nvptx64
 
diff --git a/tests/assembly-llvm/nvptx-atomics.rs b/tests/assembly-llvm/nvptx-atomics.rs
index 52b8c86d..5895a73 100644
--- a/tests/assembly-llvm/nvptx-atomics.rs
+++ b/tests/assembly-llvm/nvptx-atomics.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib
 //@ only-nvptx64
 //@ ignore-nvptx64
diff --git a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs
index 6f5ef79..2f27988 100644
--- a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs
+++ b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86
 //@ only-nvptx64
 
diff --git a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs
index 02ec9fa..e7db310 100644
--- a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs
+++ b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86
 //@ only-nvptx64
 
diff --git a/tests/assembly-llvm/nvptx-internalizing.rs b/tests/assembly-llvm/nvptx-internalizing.rs
index 0acfd5c..b671c87 100644
--- a/tests/assembly-llvm/nvptx-internalizing.rs
+++ b/tests/assembly-llvm/nvptx-internalizing.rs
@@ -1,7 +1,6 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 #![feature(abi_ptx)]
 #![no_std]
diff --git a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
index 00f6fe9..cb88cfd 100644
--- a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
+++ b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86
 //@ only-nvptx64
 
diff --git a/tests/assembly-llvm/nvptx-linking-binary.rs b/tests/assembly-llvm/nvptx-linking-binary.rs
index 3b50b47..4ec9c4a 100644
--- a/tests/assembly-llvm/nvptx-linking-binary.rs
+++ b/tests/assembly-llvm/nvptx-linking-binary.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type bin
 //@ only-nvptx64
 //@ ignore-nvptx64
diff --git a/tests/assembly-llvm/nvptx-linking-cdylib.rs b/tests/assembly-llvm/nvptx-linking-cdylib.rs
index 9742e26..82bca1f 100644
--- a/tests/assembly-llvm/nvptx-linking-cdylib.rs
+++ b/tests/assembly-llvm/nvptx-linking-cdylib.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib
 //@ only-nvptx64
 //@ ignore-nvptx64
diff --git a/tests/assembly-llvm/nvptx-safe-naming.rs b/tests/assembly-llvm/nvptx-safe-naming.rs
index 050c3fb..69bf71b 100644
--- a/tests/assembly-llvm/nvptx-safe-naming.rs
+++ b/tests/assembly-llvm/nvptx-safe-naming.rs
@@ -1,4 +1,4 @@
-//@ assembly-output: ptx-linker
+//@ assembly-output: emit-asm
 //@ compile-flags: --crate-type cdylib
 //@ only-nvptx64
 
diff --git a/tests/codegen-llvm/bpf-allows-unaligned.rs b/tests/codegen-llvm/bpf-allows-unaligned.rs
index c7a70d5..7e95a56 100644
--- a/tests/codegen-llvm/bpf-allows-unaligned.rs
+++ b/tests/codegen-llvm/bpf-allows-unaligned.rs
@@ -5,7 +5,7 @@
 
 #[no_mangle]
 #[target_feature(enable = "allows-misaligned-mem-access")]
-// CHECK: define noundef zeroext i8 @foo(i8 noundef returned %arg) unnamed_addr #0 {
+// CHECK: define noundef zeroext i8 @foo(i8 noundef returned %arg) unnamed_addr #0
 pub unsafe fn foo(arg: u8) -> u8 {
     arg
 }
diff --git a/tests/codegen-llvm/bpf-alu32.rs b/tests/codegen-llvm/bpf-alu32.rs
index 5955bf3..13a7b65 100644
--- a/tests/codegen-llvm/bpf-alu32.rs
+++ b/tests/codegen-llvm/bpf-alu32.rs
@@ -5,7 +5,7 @@
 
 #[no_mangle]
 #[target_feature(enable = "alu32")]
-// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0 {
+// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0
 pub unsafe fn foo(arg: u8) -> u8 {
     arg
 }
diff --git a/tests/codegen-llvm/branch-protection.rs b/tests/codegen-llvm/branch-protection.rs
index ed1cb2c..11847c2 100644
--- a/tests/codegen-llvm/branch-protection.rs
+++ b/tests/codegen-llvm/branch-protection.rs
@@ -22,7 +22,7 @@
 use minicore::*;
 
 // A basic test function.
-// CHECK: @test(){{.*}} [[ATTR:#[0-9]+]] {
+// CHECK: @test(){{.*}} [[ATTR:#[0-9]+]]
 #[no_mangle]
 pub fn test() {}
 
diff --git a/tests/codegen-llvm/debuginfo-for-profiling.rs b/tests/codegen-llvm/debuginfo-for-profiling.rs
new file mode 100644
index 0000000..f7e4014
--- /dev/null
+++ b/tests/codegen-llvm/debuginfo-for-profiling.rs
@@ -0,0 +1,45 @@
+// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`:
+//  - 0 discriminators are emitted without the flag in the test below
+//  - at least 1 discriminator is emitted with the flag in the test below
+//
+//
+//@ add-minicore
+//@ revisions: DEFAULT DEBUGINFO
+//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only
+//@ [DEBUGINFO] compile-flags: -Zdebuginfo-for-profiling
+// DEFAULT-NOT: discriminator
+// DEBUGINFO-COUNT-1: discriminator
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+extern "C" {
+    fn add(_x: i32, _y: i32) -> i32;
+    fn mul(_x: i32, _y: i32) -> i32;
+    fn compute(_x: i32) -> i32;
+    fn cond() -> bool;
+}
+
+#[no_mangle]
+pub fn f(limit: i32) -> i32 {
+    unsafe {
+        let mut sum = 0;
+        let mut i = 1;
+
+        while cond() {
+            if cond() {
+                sum = add(sum, compute(i));
+            } else {
+                sum = add(sum, mul(compute(i), 2));
+            }
+            i = add(i, 1);
+        }
+
+        sum
+    }
+}
diff --git a/tests/codegen-llvm/frame-pointer-cli-control.rs b/tests/codegen-llvm/frame-pointer-cli-control.rs
index 911a5f0..79cdfc7 100644
--- a/tests/codegen-llvm/frame-pointer-cli-control.rs
+++ b/tests/codegen-llvm/frame-pointer-cli-control.rs
@@ -45,7 +45,7 @@
 
 extern crate minicore;
 
-// CHECK: i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] {
+// CHECK: i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]]
 #[no_mangle]
 pub fn peach(x: u32) -> u32 {
     x
diff --git a/tests/codegen-llvm/frame-pointer.rs b/tests/codegen-llvm/frame-pointer.rs
index 1d0dd76..a52d95a 100644
--- a/tests/codegen-llvm/frame-pointer.rs
+++ b/tests/codegen-llvm/frame-pointer.rs
@@ -18,7 +18,7 @@
 extern crate minicore;
 use minicore::*;
 
-// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] {
+// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]]
 #[no_mangle]
 pub fn peach(x: u32) -> u32 {
     x
diff --git a/tests/codegen-llvm/gpu-convergent.rs b/tests/codegen-llvm/gpu-convergent.rs
index bb9271a..376d65a 100644
--- a/tests/codegen-llvm/gpu-convergent.rs
+++ b/tests/codegen-llvm/gpu-convergent.rs
@@ -17,7 +17,7 @@
     fn ext();
 }
 
-// CHECK: define {{.*}}_kernel void @fun(i32{{.*}}) unnamed_addr #[[ATTR:[0-9]+]] {
+// CHECK: define {{.*}}_kernel void @fun(i32{{.*}}) unnamed_addr #[[ATTR:[0-9]+]]
 // CHECK: declare void @ext() unnamed_addr #[[ATTR]]
 // CHECK: attributes #[[ATTR]] = {{.*}} convergent
 #[no_mangle]
diff --git a/tests/codegen-llvm/gpu_offload/control_flow.rs b/tests/codegen-llvm/gpu_offload/control_flow.rs
index 503e9e4..605a6f0 100644
--- a/tests/codegen-llvm/gpu_offload/control_flow.rs
+++ b/tests/codegen-llvm/gpu_offload/control_flow.rs
@@ -19,7 +19,7 @@
 // CHECK-NOT define
 // CHECK: bb3
 // CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.begin, ptr null, ptr null)
-// CHECK: %10 = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args)
+// CHECK: = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args)
 // CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.end, ptr null, ptr null)
 #[unsafe(no_mangle)]
 unsafe fn main() {
@@ -30,6 +30,7 @@ unsafe fn main() {
             foo,
             [256, 1, 1],
             [32, 1, 1],
+            0,
             (A.as_ptr() as *const [f32; 6],),
         );
     }
diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs
index 8179d86..2bfaf89 100644
--- a/tests/codegen-llvm/gpu_offload/gpu_host.rs
+++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs
@@ -21,7 +21,7 @@ fn main() {
 }
 
 pub fn kernel_1(x: &mut [f32; 256], y: &[f32; 256]) {
-    core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], (x, y))
+    core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], 0, (x, y))
 }
 
 #[inline(never)]
@@ -52,8 +52,8 @@ fn main() {
 
 // CHECK-LABEL: define{{( dso_local)?}} void @main()
 // CHECK-NEXT: start:
-// CHECK-NEXT:   %0 = alloca [8 x i8], align 8
-// CHECK-NEXT:   %1 = alloca [8 x i8], align 8
+// CHECK-NEXT:   {{%[^ ]+}} = alloca [8 x i8], align 8
+// CHECK-NEXT:   {{%[^ ]+}} = alloca [8 x i8], align 8
 // CHECK-NEXT:   %y = alloca [1024 x i8], align 16
 // CHECK-NEXT:   %x = alloca [1024 x i8], align 16
 // CHECK-NEXT:   %.offload_baseptrs = alloca [2 x ptr], align 8
@@ -61,9 +61,9 @@ fn main() {
 // CHECK-NEXT:   %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8
 // CHECK:   store ptr %x, ptr %.offload_baseptrs, align 8
 // CHECK-NEXT:   store ptr %x, ptr %.offload_ptrs, align 8
-// CHECK-NEXT:   [[BPTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8
+// CHECK-NEXT:   [[BPTRS_1:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8
 // CHECK-NEXT:   store ptr %y, ptr [[BPTRS_1]], align 8
-// CHECK-NEXT:   [[PTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8
+// CHECK-NEXT:   [[PTRS_1:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8
 // CHECK-NEXT:   store ptr %y, ptr [[PTRS_1]], align 8
 // CHECK-NEXT:   call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.[[K]], ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null)
 // CHECK-NEXT:   store i32 3, ptr %kernel_args, align 8
diff --git a/tests/codegen-llvm/gpu_offload/scalar_host.rs b/tests/codegen-llvm/gpu_offload/scalar_host.rs
index d5b40fb..3470761 100644
--- a/tests/codegen-llvm/gpu_offload/scalar_host.rs
+++ b/tests/codegen-llvm/gpu_offload/scalar_host.rs
@@ -13,11 +13,11 @@
 // CHECK: define{{( dso_local)?}} void @main()
 // CHECK-NOT: define
 // CHECK: %addr = alloca i64, align 8
-// CHECK: store double 4.200000e+01, ptr %0, align 8
-// CHECK: %_0.i = load double, ptr %0, align 8
-// CHECK: store double %_0.i, ptr %addr, align 8
+// CHECK: store double 4.200000e+01, ptr [[TMP:%[^,]+]], align 8
+// CHECK: [[VAL:%[0-9]+]] = load double, ptr [[TMP]], align 8
+// CHECK: store double [[VAL]], ptr %addr, align 8
 // CHECK: %1 = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8
-// CHECK-NEXT: store double %_0.i, ptr %1, align 8
+// CHECK-NEXT: store double [[VAL]], ptr %1, align 8
 // CHECK-NEXT: %2 = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8
 // CHECK-NEXT: store ptr %addr, ptr %2, align 8
 // CHECK-NEXT: call void @__tgt_target_data_begin_mapper
@@ -27,7 +27,7 @@ fn main() {
     let mut x = 0.0;
     let k = core::hint::black_box(42.0);
 
-    core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], (&mut x, k));
+    core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], 0, (&mut x, k));
 }
 
 unsafe extern "C" {
diff --git a/tests/codegen-llvm/gpu_offload/slice_host.rs b/tests/codegen-llvm/gpu_offload/slice_host.rs
index 62f12da..d4157d2 100644
--- a/tests/codegen-llvm/gpu_offload/slice_host.rs
+++ b/tests/codegen-llvm/gpu_offload/slice_host.rs
@@ -21,13 +21,13 @@
 // CHECK:  call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %.offload_sizes, ptr {{.*}} @.offload_sizes.foo, i64 16, i1 false)
 // CHECK:       store i64 16, ptr %.offload_sizes, align 8
 // CHECK:       call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.[[ID]].1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null)
-// CHECK:       %11 = call i32 @__tgt_target_kernel(ptr nonnull @anon.[[ID]].1, i64 -1, i32 1, i32 1, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args)
+// CHECK:       call i32 @__tgt_target_kernel(ptr nonnull @anon.[[ID]].1, i64 -1, i32 1, i32 1, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args)
 // CHECK-NEXT:  call void @__tgt_target_data_end_mapper(ptr nonnull @anon.[[ID]].1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].end, ptr null, ptr null)
 
 #[unsafe(no_mangle)]
 fn main() {
     let mut x = [0.0, 0.0, 0.0, 0.0];
-    core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], ((&mut x) as &mut [f64],));
+    core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], 0, ((&mut x) as &mut [f64],));
 }
 
 unsafe extern "C" {
diff --git a/tests/codegen-llvm/hint/cold_path-target_feature.rs b/tests/codegen-llvm/hint/cold_path-target_feature.rs
new file mode 100644
index 0000000..9e06fd0
--- /dev/null
+++ b/tests/codegen-llvm/hint/cold_path-target_feature.rs
@@ -0,0 +1,56 @@
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+#![crate_type = "lib"]
+
+// This test checks that hint::cold_path still works in #[target_feature] functions.
+
+use std::hint::cold_path;
+
+#[inline(never)]
+#[no_mangle]
+pub fn path_a() {
+    println!("path a");
+}
+
+#[inline(never)]
+#[no_mangle]
+pub fn path_b() {
+    println!("path b");
+}
+
+#[no_mangle]
+pub fn test1(x: bool) {
+    if x {
+        path_a();
+    } else {
+        cold_path();
+        path_b();
+    }
+
+    // CHECK-LABEL: @test1(
+    // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]]
+    // CHECK: bb2:
+    // CHECK: path_b
+    // CHECK: bb1:
+    // CHECK: path_a
+}
+
+#[no_mangle]
+#[target_feature(enable = "sse2")]
+pub fn with_target_feature(x: bool) {
+    if x {
+        path_a();
+    } else {
+        cold_path();
+        path_b();
+    }
+
+    // CHECK-LABEL: @with_target_feature(
+    // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM]]
+    // CHECK: bb2:
+    // CHECK: path_b
+    // CHECK: bb1:
+    // CHECK: path_a
+}
+
+// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1}
diff --git a/tests/codegen-llvm/instrument-coverage/testprog.rs b/tests/codegen-llvm/instrument-coverage/testprog.rs
index ef61ede..67c49c4 100644
--- a/tests/codegen-llvm/instrument-coverage/testprog.rs
+++ b/tests/codegen-llvm/instrument-coverage/testprog.rs
@@ -101,7 +101,7 @@ fn main() {
 // CHECK-SAME:   @__llvm_prf_nm
 // CHECK-SAME:   section "llvm.metadata"
 
-// CHECK:        define internal { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+// CHECK:        define internal { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}}
 // CHECK-NEXT:   start:
 // CHECK-NOT:    define internal
 // CHECK:        atomicrmw add ptr
@@ -109,7 +109,7 @@ fn main() {
 
 // CHECK:        declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
 
-// WIN:          define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {{.*}}{
+// WIN:          define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {{.*}}
 // WIN-NEXT:     %1 = load i32, ptr @__llvm_profile_runtime
 // WIN-NEXT:     ret i32 %1
 // WIN-NEXT:     }
diff --git a/tests/codegen-llvm/link_section.rs b/tests/codegen-llvm/link_section.rs
index f196ea8..61bde68 100644
--- a/tests/codegen-llvm/link_section.rs
+++ b/tests/codegen-llvm/link_section.rs
@@ -29,7 +29,7 @@ pub enum E {
 #[link_section = "__TEST,three"]
 pub static VAR3: E = E::B(1.);
 
-// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section "__TEST,four" {
+// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section "__TEST,four"
 #[no_mangle]
 #[link_section = "__TEST,four"]
 pub fn fn1() {}
diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
index 7639ce7..5b1aa97 100644
--- a/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
+++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
@@ -7,21 +7,21 @@
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}foo
-    // CHECK-SAME:  {{.*}}![[TYPE1:[0-9]+]]
+    // CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]]
     // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized.generalized")
     f(arg)
 }
 
 pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}bar
-    // CHECK-SAME:  {{.*}}![[TYPE2:[0-9]+]]
+    // CHECK-SAME:  {{.*}}!type ![[TYPE2:[0-9]+]]
     // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized.generalized")
     f(arg1, arg2)
 }
 
 pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}baz
-    // CHECK-SAME:  {{.*}}![[TYPE3:[0-9]+]]
+    // CHECK-SAME:  {{.*}}!type ![[TYPE3:[0-9]+]]
     // CHECK:       call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized.generalized")
     f(arg1, arg2, arg3)
 }
diff --git a/tests/codegen-llvm/sanitizer/cfi/external_weak_symbols.rs b/tests/codegen-llvm/sanitizer/cfi/external_weak_symbols.rs
index 893b016..6ac95aa 100644
--- a/tests/codegen-llvm/sanitizer/cfi/external_weak_symbols.rs
+++ b/tests/codegen-llvm/sanitizer/cfi/external_weak_symbols.rs
@@ -10,7 +10,7 @@
     #[linkage = "extern_weak"]
     static FOO: Option<unsafe extern "C" fn(f64) -> ()>;
 }
-// CHECK: @_rust_extern_with_linkage_{{.*}}_FOO = internal global ptr @FOO
+// CHECK: @_rust_extern_with_linkage_{{.*}}_FOO = internal unnamed_addr global ptr @FOO
 
 fn main() {
     unsafe {
diff --git a/tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs b/tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs
index 35317b0..3df2d56 100644
--- a/tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs
+++ b/tests/codegen-llvm/some-non-zero-from-atomic-optimization.rs
@@ -72,7 +72,7 @@ pub unsafe fn some_non_zero_from_atomic_get() -> Option<NonZeroUsize> {
 ///
 /// The way we check that the LLVM IR is correct is by making sure that neither
 /// `panic` nor `unreachable` is part of the LLVM IR:
-// CHECK-LABEL: define {{.*}} i64 @some_non_zero_from_atomic_get2() {{.*}} {
+// CHECK-LABEL: define {{.*}} i64 @some_non_zero_from_atomic_get2() {{.*}}
 // CHECK-NOT: panic
 // CHECK-NOT: unreachable
 #[no_mangle]
diff --git a/tests/codegen-llvm/target-feature-negative-implication.rs b/tests/codegen-llvm/target-feature-negative-implication.rs
index a9cdca4..3765997 100644
--- a/tests/codegen-llvm/target-feature-negative-implication.rs
+++ b/tests/codegen-llvm/target-feature-negative-implication.rs
@@ -13,7 +13,7 @@
 #[no_mangle]
 pub unsafe fn banana() {
     // CHECK-LABEL: @banana()
-    // CHECK-SAME: [[BANANAATTRS:#[0-9]+]] {
+    // CHECK-SAME: [[BANANAATTRS:#[0-9]+]]
 }
 
 // CHECK: attributes [[BANANAATTRS]]
diff --git a/tests/codegen-llvm/target-feature-overrides.rs b/tests/codegen-llvm/target-feature-overrides.rs
index 2adc8ee..3bf05c7 100644
--- a/tests/codegen-llvm/target-feature-overrides.rs
+++ b/tests/codegen-llvm/target-feature-overrides.rs
@@ -23,7 +23,7 @@
 #[no_mangle]
 pub unsafe fn apple() -> u32 {
     // CHECK-LABEL: @apple()
-    // CHECK-SAME: [[APPLEATTRS:#[0-9]+]] {
+    // CHECK-SAME: [[APPLEATTRS:#[0-9]+]]
     // CHECK: {{.*}}call{{.*}}@peach
     peach()
 }
@@ -32,7 +32,7 @@ pub unsafe fn apple() -> u32 {
 #[no_mangle]
 pub unsafe fn banana() -> u32 {
     // CHECK-LABEL: @banana()
-    // CHECK-SAME: [[BANANAATTRS:#[0-9]+]] {
+    // CHECK-SAME: [[BANANAATTRS:#[0-9]+]]
     // COMPAT: {{.*}}call{{.*}}@peach
     // INCOMPAT: {{.*}}call{{.*}}@apple
     apple() // Compatible for inline in COMPAT revision and can't be inlined in INCOMPAT
diff --git a/tests/codegen-llvm/unwind-abis/aapcs-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/aapcs-unwind-abi.rs
index ecace72..279780e 100644
--- a/tests/codegen-llvm/unwind-abis/aapcs-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/aapcs-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "aapcs" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "aapcs-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/c-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/c-unwind-abi.rs
index 46c08b5..1b33128 100644
--- a/tests/codegen-llvm/unwind-abis/c-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/c-unwind-abi.rs
@@ -7,11 +7,11 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "C" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "C-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/cdecl-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/cdecl-unwind-abi.rs
index 8e643d6..6f4eafb 100644
--- a/tests/codegen-llvm/unwind-abis/cdecl-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/cdecl-unwind-abi.rs
@@ -7,11 +7,11 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "cdecl" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "cdecl-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/fastcall-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/fastcall-unwind-abi.rs
index 7df4681..51c6fd1 100644
--- a/tests/codegen-llvm/unwind-abis/fastcall-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/fastcall-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "fastcall" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "fastcall-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/stdcall-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/stdcall-unwind-abi.rs
index cc06ee1..b5fcea5 100644
--- a/tests/codegen-llvm/unwind-abis/stdcall-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/stdcall-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
 // optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "stdcall" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "stdcall-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/system-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/system-unwind-abi.rs
index 5f91024..15fce95f 100644
--- a/tests/codegen-llvm/unwind-abis/system-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/system-unwind-abi.rs
@@ -7,11 +7,11 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "system" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "system-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/sysv64-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/sysv64-unwind-abi.rs
index 69bfaf8..1293e7c 100644
--- a/tests/codegen-llvm/unwind-abis/sysv64-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/sysv64-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "sysv64" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "sysv64-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/thiscall-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/thiscall-unwind-abi.rs
index 05f6b8b..a9b6c34 100644
--- a/tests/codegen-llvm/unwind-abis/thiscall-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/thiscall-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "thiscall" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "thiscall-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/vectorcall-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/vectorcall-unwind-abi.rs
index d001a16..8cedb55 100644
--- a/tests/codegen-llvm/unwind-abis/vectorcall-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/vectorcall-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute.
 // We disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "vectorcall" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/codegen-llvm/unwind-abis/win64-unwind-abi.rs b/tests/codegen-llvm/unwind-abis/win64-unwind-abi.rs
index 257f00b..2a3ad33 100644
--- a/tests/codegen-llvm/unwind-abis/win64-unwind-abi.rs
+++ b/tests/codegen-llvm/unwind-abis/win64-unwind-abi.rs
@@ -16,11 +16,11 @@ pub trait Sized: MetaSized {}
 // `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We
 // disable optimizations above to prevent LLVM from inferring the attribute.
 
-// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
+// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0
 #[no_mangle]
 pub extern "win64" fn rust_item_that_cannot_unwind() {}
 
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
+// CHECK: @rust_item_that_can_unwind() unnamed_addr #1
 #[no_mangle]
 pub extern "win64-unwind" fn rust_item_that_can_unwind() {}
 
diff --git a/tests/crashes/139387.rs b/tests/crashes/139387.rs
deleted file mode 100644
index 133643ad..0000000
--- a/tests/crashes/139387.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: #139387
-//@ needs-rustc-debug-assertions
-
-trait A {
-    fn method() -> impl Sized;
-}
-trait B {
-    fn method(Hash: Wrap<impl Beta<U: Copy + for<'a> Epsilon<'_, SI1: Eta>>>) -> impl Sized;
-}
-
-fn ambiguous<T: A + B>()
-where
-    T::method(..): Send,
-{
-}
diff --git a/tests/debuginfo/associated-types.rs b/tests/debuginfo/associated-types.rs
index 5944cc1..f61e76c 100644
--- a/tests/debuginfo/associated-types.rs
+++ b/tests/debuginfo/associated-types.rs
@@ -39,7 +39,7 @@
 //@ lldb-command:run
 
 //@ lldb-command:v arg
-//@ lldb-check:[...] { b = -1 b1 = 0 }
+//@ lldb-check:[...] {b:-1, b1:0}
 //@ lldb-command:continue
 
 //@ lldb-command:v inferred
diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs
index f81c5cf..cb9cb22 100644
--- a/tests/debuginfo/basic-stepping.rs
+++ b/tests/debuginfo/basic-stepping.rs
@@ -58,10 +58,10 @@
 //@ lldb-command: settings set stop-line-count-after 0
 
 //@ lldb-command: run
-// In `breakpoint_callback()` in `./src/etc/lldb_batchmode.py` we do
+// In `breakpoint_callback()` in `./src/etc/lldb_batchmode/runner.py` we do
 // `SetSelectedFrame()`, which causes LLDB to show the current line and one line
 // before (since we changed `stop-line-count-before`). Note that
-// `normalize_whitespace()` in `lldb_batchmode.py` removes the newlines of the
+// `normalize_whitespace()` in `lldb_batchmode/runner.py` removes the newlines of the
 // output. So the current line and the line before actually ends up on the same
 // output line. That's fine.
 //@ lldb-check:   [...]let mut c = 27;[...]
diff --git a/tests/debuginfo/borrowed-struct.rs b/tests/debuginfo/borrowed-struct.rs
index fccca09..0326fb6 100644
--- a/tests/debuginfo/borrowed-struct.rs
+++ b/tests/debuginfo/borrowed-struct.rs
@@ -33,7 +33,7 @@
 //@ lldb-command:run
 
 //@ lldb-command:v *stack_val_ref
-//@ lldb-check:[...] { x = 10 y = 23.5 }
+//@ lldb-check:[...] {x:10, y:23.5}
 
 //@ lldb-command:v *stack_val_interior_ref_1
 //@ lldb-check:[...] 10
@@ -42,10 +42,10 @@
 //@ lldb-check:[...] 23.5
 
 //@ lldb-command:v *ref_to_unnamed
-//@ lldb-check:[...] { x = 11 y = 24.5 }
+//@ lldb-check:[...] {x:11, y:24.5}
 
 //@ lldb-command:v *unique_val_ref
-//@ lldb-check:[...] { x = 13 y = 26.5 }
+//@ lldb-check:[...] {x:13, y:26.5}
 
 //@ lldb-command:v *unique_val_interior_ref_1
 //@ lldb-check:[...] 13
diff --git a/tests/debuginfo/boxed-struct.rs b/tests/debuginfo/boxed-struct.rs
index 4990a18..0389717 100644
--- a/tests/debuginfo/boxed-struct.rs
+++ b/tests/debuginfo/boxed-struct.rs
@@ -18,10 +18,10 @@
 //@ lldb-command:run
 
 //@ lldb-command:v *boxed_with_padding
-//@ lldb-check:[...] { x = 99 y = 999 z = 9999 w = 99999 }
+//@ lldb-check:[...] {x:99, y:999, z:9999, w:99999}
 
 //@ lldb-command:v *boxed_with_dtor
-//@ lldb-check:[...] { x = 77 y = 777 z = 7777 w = 77777 }
+//@ lldb-check:[...] {x:77, y:777, z:7777, w:77777}
 
 #![allow(unused_variables)]
 
diff --git a/tests/debuginfo/by-value-self-argument-in-trait-impl.rs b/tests/debuginfo/by-value-self-argument-in-trait-impl.rs
index 42874f9..9b616ba 100644
--- a/tests/debuginfo/by-value-self-argument-in-trait-impl.rs
+++ b/tests/debuginfo/by-value-self-argument-in-trait-impl.rs
@@ -28,7 +28,7 @@
 //@ lldb-command:continue
 
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 2222 y = 3333 }
+//@ lldb-check:[...] {x:2222, y:3333}
 //@ lldb-command:continue
 
 //@ lldb-command:v self
diff --git a/tests/debuginfo/c-style-enum-in-composite.rs b/tests/debuginfo/c-style-enum-in-composite.rs
index 2362eee..6839c07 100644
--- a/tests/debuginfo/c-style-enum-in-composite.rs
+++ b/tests/debuginfo/c-style-enum-in-composite.rs
@@ -41,13 +41,13 @@
 //@ lldb-check:[...] (OneThousand, MountainView, OneMillion, Vienna)
 
 //@ lldb-command:v padded_struct
-//@ lldb-check:[...] { a = 3 b = OneMillion c = 4 d = Toronto e = 5 }
+//@ lldb-check:[...] {a:3, b:OneMillion, c:4, d:Toronto, e:5}
 
 //@ lldb-command:v packed_struct
-//@ lldb-check:[...] { a = 6 b = OneHundred c = 7 d = Vienna e = 8 }
+//@ lldb-check:[...] {a:6, b:OneHundred, c:7, d:Vienna, e:8}
 
 //@ lldb-command:v non_padded_struct
-//@ lldb-check:[...] { a = OneMillion b = MountainView c = OneThousand d = Toronto }
+//@ lldb-check:[...] {a:OneMillion, b:MountainView, c:OneThousand, d:Toronto}
 
 //@ lldb-command:v struct_with_drop
 //@ lldb-check:[...] ({a:OneHundred, b:Vienna}, 9)
diff --git a/tests/debuginfo/captured-fields-1.rs b/tests/debuginfo/captured-fields-1.rs
index 8165133..2d8872a 100644
--- a/tests/debuginfo/captured-fields-1.rs
+++ b/tests/debuginfo/captured-fields-1.rs
@@ -1,6 +1,7 @@
 //@ compile-flags:-g
 //@ edition:2021
 //@ ignore-backends: gcc
+//@ min-lldb-version: 2100
 // === GDB TESTS ===================================================================================
 
 //@ gdb-command:run
@@ -27,22 +28,22 @@
 
 //@ lldb-command:run
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#0}) test = { _ref__my_ref__my_field1 = 0x[...] }
+//@ lldb-check:(captured_fields_1::main::{closure_env#0}) test = {_ref__my_ref__my_field1:0x[...]}
 //@ lldb-command:continue
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#1}) test = { _ref__my_ref__my_field2 = 0x[...] }
+//@ lldb-check:(captured_fields_1::main::{closure_env#1}) test = {_ref__my_ref__my_field2:0x[...]}
 //@ lldb-command:continue
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#2}) test = { _ref__my_ref = 0x[...] }
+//@ lldb-check:(captured_fields_1::main::{closure_env#2}) test = {_ref__my_ref:0x[...]}
 //@ lldb-command:continue
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#3}) test = { my_ref = 0x[...] }
+//@ lldb-check:(captured_fields_1::main::{closure_env#3}) test = {my_ref:{my_field1:11, my_field2:22}}
 //@ lldb-command:continue
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#4}) test = { my_var__my_field2 = 22 }
+//@ lldb-check:(captured_fields_1::main::{closure_env#4}) test = {my_var__my_field2:22}
 //@ lldb-command:continue
 //@ lldb-command:v test
-//@ lldb-check:(captured_fields_1::main::{closure_env#5}) test = { my_var = { my_field1 = 11 my_field2 = 22 } }
+//@ lldb-check:(captured_fields_1::main::{closure_env#5}) test = {my_var:{my_field1:11, my_field2:22}}
 //@ lldb-command:continue
 
 #![allow(unused)]
diff --git a/tests/debuginfo/destructured-fn-argument.rs b/tests/debuginfo/destructured-fn-argument.rs
index def1d15..c61f024 100644
--- a/tests/debuginfo/destructured-fn-argument.rs
+++ b/tests/debuginfo/destructured-fn-argument.rs
@@ -178,7 +178,7 @@
 //@ lldb-command:v h
 //@ lldb-check:[...] 8
 //@ lldb-command:v i
-//@ lldb-check:[...] { a = 9 b = 10 }
+//@ lldb-check:[...] {a:9, b:10}
 //@ lldb-command:v j
 //@ lldb-check:[...] 11
 //@ lldb-command:continue
@@ -204,7 +204,7 @@
 //@ lldb-command:v q
 //@ lldb-check:[...] 20
 //@ lldb-command:v r
-//@ lldb-check:[...] { a = 21 b = 22 }
+//@ lldb-check:[...] {a:21, b:22}
 //@ lldb-command:continue
 
 //@ lldb-command:v s
diff --git a/tests/debuginfo/destructured-for-loop-variable.rs b/tests/debuginfo/destructured-for-loop-variable.rs
index 5febb9e..7e5420f 100644
--- a/tests/debuginfo/destructured-for-loop-variable.rs
+++ b/tests/debuginfo/destructured-for-loop-variable.rs
@@ -134,7 +134,7 @@
 //@ lldb-command:continue
 
 //@ lldb-command:v simple_struct_ident
-//@ lldb-check:[...] { x = 3537 y = 35437.5 z = true }
+//@ lldb-check:[...] {x:3537, y:35437.5, z:true}
 //@ lldb-command:continue
 
 //@ lldb-command:v simple_tuple_ident
diff --git a/tests/debuginfo/destructured-local.rs b/tests/debuginfo/destructured-local.rs
index 0f7667a..07f3554 100644
--- a/tests/debuginfo/destructured-local.rs
+++ b/tests/debuginfo/destructured-local.rs
@@ -141,7 +141,7 @@
 //@ lldb-command:v h
 //@ lldb-check:[...] 8
 //@ lldb-command:v i
-//@ lldb-check:[...] { a = 9 b = 10 }
+//@ lldb-check:[...] {a:9, b:10}
 //@ lldb-command:v j
 //@ lldb-check:[...] 11
 
@@ -163,7 +163,7 @@
 //@ lldb-command:v q
 //@ lldb-check:[...] 20
 //@ lldb-command:v r
-//@ lldb-check:[...] { a = 21 b = 22 }
+//@ lldb-check:[...] {a:21, b:22}
 
 //@ lldb-command:v s
 //@ lldb-check:[...] 24
diff --git a/tests/debuginfo/evec-in-struct.rs b/tests/debuginfo/evec-in-struct.rs
index bbcad48..44e7d35 100644
--- a/tests/debuginfo/evec-in-struct.rs
+++ b/tests/debuginfo/evec-in-struct.rs
@@ -26,18 +26,18 @@
 //@ lldb-command:run
 
 //@ lldb-command:v no_padding1
-//@ lldb-check:[...] { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } }
+//@ lldb-check:[...] {x:(0, 1, 2), y:-3, z:(4.5, 5.5)}
 //@ lldb-command:v no_padding2
-//@ lldb-check:[...] { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } }
+//@ lldb-check:[...] {x:(6, 7, 8), y:((9, 10), (11, 12))}
 
 //@ lldb-command:v struct_internal_padding
-//@ lldb-check:[...] { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } }
+//@ lldb-check:[...] {x:(13, 14), y:(15, 16)}
 
 //@ lldb-command:v single_vec
-//@ lldb-check:[...] { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } }
+//@ lldb-check:[...] {x:(17, 18, 19, 20, 21)}
 
 //@ lldb-command:v struct_padded_at_end
-//@ lldb-check:[...] { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } }
+//@ lldb-check:[...] {x:(22, 23), y:(24, 25)}
 
 #![allow(unused_variables)]
 
diff --git a/tests/debuginfo/generic-function.rs b/tests/debuginfo/generic-function.rs
index 4e66021..4bfee08 100644
--- a/tests/debuginfo/generic-function.rs
+++ b/tests/debuginfo/generic-function.rs
@@ -43,7 +43,7 @@
 //@ lldb-command:v *t0
 //@ lldb-check:[...] 5
 //@ lldb-command:v *t1
-//@ lldb-check:[...] { a = 6 b = 7.5 }
+//@ lldb-check:[...] {a:6, b:7.5}
 //@ lldb-command:continue
 
 #[derive(Clone)]
diff --git a/tests/debuginfo/generic-method-on-generic-struct.rs b/tests/debuginfo/generic-method-on-generic-struct.rs
index 6ec2151..1b3bdb9 100644
--- a/tests/debuginfo/generic-method-on-generic-struct.rs
+++ b/tests/debuginfo/generic-method-on-generic-struct.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = (8888, -8888) }
+//@ lldb-check:[...] {x:(8888, -8888)}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = (8888, -8888) }
+//@ lldb-check:[...] {x:(8888, -8888)}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 1234.5 }
+//@ lldb-check:[...] {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 1234.5 }
+//@ lldb-check:[...] {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 1234.5 }
+//@ lldb-check:[...] {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/generic-struct.rs b/tests/debuginfo/generic-struct.rs
index e6e56e2..945a0cd 100644
--- a/tests/debuginfo/generic-struct.rs
+++ b/tests/debuginfo/generic-struct.rs
@@ -20,14 +20,14 @@
 //@ lldb-command:run
 
 //@ lldb-command:v int_int
-//@ lldb-check:[...]AGenericStruct<int, int>) int_int = { key = 0 value = 1 }
+//@ lldb-check:[...]AGenericStruct<int, int>) int_int = {key:0, value:1}
 //@ lldb-command:v int_float
-//@ lldb-check:[...]AGenericStruct<int, double>) int_float = { key = 2 value = 3.5 }
+//@ lldb-check:[...]AGenericStruct<int, double>) int_float = {key:2, value:3.5}
 //@ lldb-command:v float_int
-//@ lldb-check:[...]AGenericStruct<double, int>) float_int = { key = 4.5 value = 5 }
+//@ lldb-check:[...]AGenericStruct<double, int>) float_int = {key:4.5, value:5}
 
 //@ lldb-command:v float_int_float
-//@ lldb-check:[...]AGenericStruct<double, generic_struct::AGenericStruct<int, double> >) float_int_float = { key = 6.5 value = { key = 7 value = 8.5 } }
+//@ lldb-check:[...]AGenericStruct<double, generic_struct::AGenericStruct<int, double> >) float_int_float = {key:6.5, value:{key:7, value:8.5}}
 
 // === CDB TESTS ===================================================================================
 
diff --git a/tests/debuginfo/issue-22656.rs b/tests/debuginfo/issue-22656.rs
index 54c381b..c552132 100644
--- a/tests/debuginfo/issue-22656.rs
+++ b/tests/debuginfo/issue-22656.rs
@@ -13,7 +13,7 @@
 //@ lldb-command:v v
 //@ lldb-check:[...] size=3 { [0] = 1 [1] = 2 [2] = 3 }
 //@ lldb-command:v zs
-//@ lldb-check:[...] { x = y = 123 z = w = 456 }
+//@ lldb-check:[...] {x:{}, y:123, z:{}, w:456}
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/tests/debuginfo/method-on-generic-struct.rs b/tests/debuginfo/method-on-generic-struct.rs
index 6194cd5..f154e46 100644
--- a/tests/debuginfo/method-on-generic-struct.rs
+++ b/tests/debuginfo/method-on-generic-struct.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...]Struct<(u32, i32)>) *self = { x = (8888, -8888) }
+//@ lldb-check:[...]Struct<(u32, i32)>) *self = {x:(8888, -8888)}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...]Struct<(u32, i32)>) self = { x = (8888, -8888) }
+//@ lldb-check:[...]Struct<(u32, i32)>) self = {x:(8888, -8888)}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...]Struct<double>) *self = { x = 1234.5 }
+//@ lldb-check:[...]Struct<double>) *self = {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...]Struct<double>) self = { x = 1234.5 }
+//@ lldb-check:[...]Struct<double>) self = {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...]Struct<double>) *self = { x = 1234.5 }
+//@ lldb-check:[...]Struct<double>) *self = {x:1234.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/method-on-struct.rs b/tests/debuginfo/method-on-struct.rs
index 5a4c275..73e7401 100644
--- a/tests/debuginfo/method-on-struct.rs
+++ b/tests/debuginfo/method-on-struct.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/method-on-trait.rs b/tests/debuginfo/method-on-trait.rs
index 673d25a..41a9d48 100644
--- a/tests/debuginfo/method-on-trait.rs
+++ b/tests/debuginfo/method-on-trait.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/method-on-tuple-struct.rs b/tests/debuginfo/method-on-tuple-struct.rs
index 03c00d6..3f9bda67 100644
--- a/tests/debuginfo/method-on-tuple-struct.rs
+++ b/tests/debuginfo/method-on-tuple-struct.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { 0 = 100 1 = -100.5 }
+//@ lldb-check:[...] {0:100, 1:-100.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { 0 = 100 1 = -100.5 }
+//@ lldb-check:[...] {0:100, 1:-100.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { 0 = 200 1 = -200.5 }
+//@ lldb-check:[...] {0:200, 1:-200.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { 0 = 200 1 = -200.5 }
+//@ lldb-check:[...] {0:200, 1:-200.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { 0 = 200 1 = -200.5 }
+//@ lldb-check:[...] {0:200, 1:-200.5}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs
index 31b439b..468c655 100644
--- a/tests/debuginfo/numeric-types.rs
+++ b/tests/debuginfo/numeric-types.rs
@@ -197,40 +197,41 @@
 // === LLDB TESTS ==================================================================================
 
 //@ lldb-command:run
-
-//@ lldb-command:v/d nz_i8
-//@ lldb-check:[...] 11 { 0 = { 0 = 11 } }
+//@ lldb-command:type format add -f u "unsigned char"
+//@ lldb-command:type format add -f d "char" "signed char"
+//@ lldb-command:v nz_i8
+//@ lldb-check:[...] 11 { 0 = {0:11} }
 
 //@ lldb-command:v nz_i16
-//@ lldb-check:[...] 22 { 0 = { 0 = 22 } }
+//@ lldb-check:[...] 22 { 0 = {0:22} }
 
 //@ lldb-command:v nz_i32
-//@ lldb-check:[...] 33 { 0 = { 0 = 33 } }
+//@ lldb-check:[...] 33 { 0 = {0:33} }
 
 //@ lldb-command:v nz_i64
-//@ lldb-check:[...] 44 { 0 = { 0 = 44 } }
+//@ lldb-check:[...] 44 { 0 = {0:44} }
 
 //@ lldb-command:v nz_i128
-//@ lldb-check:[...] 55 { 0 = { 0 = 55 } }
+//@ lldb-check:[...] 55 { 0 = {0:55} }
 
 // FIXME(#156886): "error: Invalid type: Cannot determine size"
 //(DISABLED) @ lldb-command:v nz_isize
 //(DISABLED) @ lldb-check:[...] 66 { 0 = { 0 = 66 } }
 
-//@ lldb-command:v/d nz_u8
-//@ lldb-check:[...] 77 { 0 = { 0 = 77 } }
+//@ lldb-command:v nz_u8
+//@ lldb-check:[...] 77 { 0 = {0:77} }
 
 //@ lldb-command:v nz_u16
-//@ lldb-check:[...] 88 { 0 = { 0 = 88 } }
+//@ lldb-check:[...] 88 { 0 = {0:88} }
 
 //@ lldb-command:v nz_u32
-//@ lldb-check:[...] 99 { 0 = { 0 = 99 } }
+//@ lldb-check:[...] 99 { 0 = {0:99} }
 
 //@ lldb-command:v nz_u64
-//@ lldb-check:[...] 100 { 0 = { 0 = 100 } }
+//@ lldb-check:[...] 100 { 0 = {0:100} }
 
 //@ lldb-command:v nz_u128
-//@ lldb-check:[...] 111 { 0 = { 0 = 111 } }
+//@ lldb-check:[...] 111 { 0 = {0:111} }
 
 // FIXME(#156886): "error: Invalid type: Cannot determine size"
 //(DISABLED) @ lldb-command:v nz_usize
diff --git a/tests/debuginfo/packed-struct-with-destructor.rs b/tests/debuginfo/packed-struct-with-destructor.rs
index ec656f7..59fc3d3 100644
--- a/tests/debuginfo/packed-struct-with-destructor.rs
+++ b/tests/debuginfo/packed-struct-with-destructor.rs
@@ -37,28 +37,28 @@
 //@ lldb-command:run
 
 //@ lldb-command:v packed
-//@ lldb-check:[...] { x = 123 y = 234 z = 345 }
+//@ lldb-check:[...] {x:123, y:234, z:345}
 
 //@ lldb-command:v packedInPacked
-//@ lldb-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
+//@ lldb-check:[...] {a:1111, b:{x:2222, y:3333, z:4444}, c:5555, d:{x:6666, y:7777, z:8888}}
 
 //@ lldb-command:v packedInUnpacked
-//@ lldb-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
+//@ lldb-check:[...] {a:-1111, b:{x:-2222, y:-3333, z:-4444}, c:-5555, d:{x:-6666, y:-7777, z:-8888}}
 
 //@ lldb-command:v unpackedInPacked
-//@ lldb-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 }
+//@ lldb-check:[...] {a:987, b:{x:876, y:765, z:654}, c:{x:543, y:432, z:321}, d:210}
 
 //@ lldb-command:v packedInPackedWithDrop
-//@ lldb-check:[...] { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } }
+//@ lldb-check:[...] {a:11, b:{x:22, y:33, z:44}, c:55, d:{x:66, y:77, z:88}}
 
 //@ lldb-command:v packedInUnpackedWithDrop
-//@ lldb-check:[...] { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } }
+//@ lldb-check:[...] {a:-11, b:{x:-22, y:-33, z:-44}, c:-55, d:{x:-66, y:-77, z:-88}}
 
 //@ lldb-command:v unpackedInPackedWithDrop
-//@ lldb-check:[...] { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 }
+//@ lldb-check:[...] {a:98, b:{x:87, y:76, z:65}, c:{x:54, y:43, z:32}, d:21}
 
 //@ lldb-command:v deeplyNested
-//@ lldb-check:[...] { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } }
+//@ lldb-check:[...] {a:{a:1, b:{x:2, y:3, z:4}, c:5, d:{x:6, y:7, z:8}}, b:{a:9, b:{x:10, y:11, z:12}, c:{x:13, y:14, z:15}, d:16}, c:{a:17, b:{x:18, y:19, z:20}, c:21, d:{x:22, y:23, z:24}}, d:{a:25, b:{x:26, y:27, z:28}, c:29, d:{x:30, y:31, z:32}}, e:{a:33, b:{x:34, y:35, z:36}, c:{x:37, y:38, z:39}, d:40}, f:{a:41, b:{x:42, y:43, z:44}, c:45, d:{x:46, y:47, z:48}}}
 
 
 #![allow(unused_variables)]
diff --git a/tests/debuginfo/packed-struct.rs b/tests/debuginfo/packed-struct.rs
index 38f8465..e601ac1 100644
--- a/tests/debuginfo/packed-struct.rs
+++ b/tests/debuginfo/packed-struct.rs
@@ -30,16 +30,16 @@
 //@ lldb-command:run
 
 //@ lldb-command:v packed
-//@ lldb-check:[...] { x = 123 y = 234 z = 345 }
+//@ lldb-check:[...] {x:123, y:234, z:345}
 
 //@ lldb-command:v packedInPacked
-//@ lldb-check:[...] { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
+//@ lldb-check:[...] {a:1111, b:{x:2222, y:3333, z:4444}, c:5555, d:{x:6666, y:7777, z:8888}}
 
 //@ lldb-command:v packedInUnpacked
-//@ lldb-check:[...] { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
+//@ lldb-check:[...] {a:-1111, b:{x:-2222, y:-3333, z:-4444}, c:-5555, d:{x:-6666, y:-7777, z:-8888}}
 
 //@ lldb-command:v unpackedInPacked
-//@ lldb-check:[...] { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 }
+//@ lldb-check:[...] {a:987, b:{x:876, y:765, z:654, w:543}, c:{x:432, y:321, z:210, w:109}, d:-98}
 
 //@ lldb-command:expr sizeof(packed)
 //@ lldb-check:[...] 14
diff --git a/tests/debuginfo/path.rs b/tests/debuginfo/path.rs
index 2fffadd..f2bbf8c 100644
--- a/tests/debuginfo/path.rs
+++ b/tests/debuginfo/path.rs
@@ -6,10 +6,10 @@
 
 //@ lldb-command:run
 
-//@ lldb-command:print pathbuf
-//@ lldb-check:[...] "/some/path" { inner = "/some/path" { inner = { inner = size=10 { [0] = '/' [1] = 's' [2] = 'o' [3] = 'm' [4] = 'e' [5] = '/' [6] = 'p' [7] = 'a' [8] = 't' [9] = 'h' } } } }
-//@ lldb-command:print path
-//@ lldb-check:[...] "/some/path" { data_ptr = [...] length = 10 }
+//@ lldb-command:v pathbuf
+//@ lldb-check:[...] "/some/path" [...]
+//@ lldb-command:v path
+//@ lldb-check:[...] "/some/path" [...]
 
 use std::path::Path;
 
diff --git a/tests/debuginfo/self-in-default-method.rs b/tests/debuginfo/self-in-default-method.rs
index 41e4ffc..0ed8e23 100644
--- a/tests/debuginfo/self-in-default-method.rs
+++ b/tests/debuginfo/self-in-default-method.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 100 }
+//@ lldb-check:[...] {x:100}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 200 }
+//@ lldb-check:[...] {x:200}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/self-in-generic-default-method.rs b/tests/debuginfo/self-in-generic-default-method.rs
index 401d652..12cdfec 100644
--- a/tests/debuginfo/self-in-generic-default-method.rs
+++ b/tests/debuginfo/self-in-generic-default-method.rs
@@ -58,7 +58,7 @@
 
 // STACK BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 987 }
+//@ lldb-check:[...] {x:987}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -1
 //@ lldb-command:v arg2
@@ -67,7 +67,7 @@
 
 // STACK BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 987 }
+//@ lldb-check:[...] {x:987}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -3
 //@ lldb-command:v arg2
@@ -76,7 +76,7 @@
 
 // OWNED BY REF
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 879 }
+//@ lldb-check:[...] {x:879}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -5
 //@ lldb-command:v arg2
@@ -85,7 +85,7 @@
 
 // OWNED BY VAL
 //@ lldb-command:v self
-//@ lldb-check:[...] { x = 879 }
+//@ lldb-check:[...] {x:879}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -7
 //@ lldb-command:v arg2
@@ -94,7 +94,7 @@
 
 // OWNED MOVED
 //@ lldb-command:v *self
-//@ lldb-check:[...] { x = 879 }
+//@ lldb-check:[...] {x:879}
 //@ lldb-command:v arg1
 //@ lldb-check:[...] -9
 //@ lldb-command:v arg2
diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs
index a67dc13..fe42e9d 100644
--- a/tests/debuginfo/simple-struct.rs
+++ b/tests/debuginfo/simple-struct.rs
@@ -67,22 +67,22 @@
 //@ lldb-command:run
 
 //@ lldb-command:v no_padding16
-//@ lldb-check:[...] { x = 10000 y = -10001 }
+//@ lldb-check:[...] {x:10000, y:-10001}
 
 //@ lldb-command:v no_padding32
-//@ lldb-check:[...] { x = -10002 y = -10003.5 z = 10004 }
+//@ lldb-check:[...] {x:-10002, y:-10003.5, z:10004}
 
 //@ lldb-command:v no_padding64
-//@ lldb-check:[...] { x = -10005.5 y = 10006 z = 10007 }
+//@ lldb-check:[...] {x:-10005.5, y:10006, z:10007}
 
 //@ lldb-command:v no_padding163264
-//@ lldb-check:[...] { a = -10008 b = 10009 c = 10010 d = 10011 }
+//@ lldb-check:[...] {a:-10008, b:10009, c:10010, d:10011}
 
 //@ lldb-command:v internal_padding
-//@ lldb-check:[...] { x = 10012 y = -10013 }
+//@ lldb-check:[...] {x:10012, y:-10013}
 
 //@ lldb-command:v padding_at_end
-//@ lldb-check:[...] { x = -10014 y = 10015 }
+//@ lldb-check:[...] {x:-10014, y:10015}
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/tests/debuginfo/struct-in-struct.rs b/tests/debuginfo/struct-in-struct.rs
index e5fa841..8b7ceb0 100644
--- a/tests/debuginfo/struct-in-struct.rs
+++ b/tests/debuginfo/struct-in-struct.rs
@@ -21,28 +21,28 @@
 //@ lldb-command:run
 
 //@ lldb-command:v three_simple_structs
-//@ lldb-check:[...] { x = { x = 1 } y = { x = 2 } z = { x = 3 } }
+//@ lldb-check:[...] {x:{x:1}, y:{x:2}, z:{x:3}}
 
 //@ lldb-command:v internal_padding_parent
-//@ lldb-check:[...] { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } }
+//@ lldb-check:[...] {x:{x:4, y:5}, y:{x:6, y:7}, z:{x:8, y:9}}
 
 //@ lldb-command:v padding_at_end_parent
-//@ lldb-check:[...] { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } }
+//@ lldb-check:[...] {x:{x:10, y:11}, y:{x:12, y:13}, z:{x:14, y:15}}
 
 //@ lldb-command:v mixed
-//@ lldb-check:[...] { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 }
+//@ lldb-check:[...] {x:{x:16, y:17}, y:{x:18, y:19}, z:{x:20}, w:21}
 
 //@ lldb-command:v bag
-//@ lldb-check:[...] { x = { x = 22 } }
+//@ lldb-check:[...] {x:{x:22}}
 
 //@ lldb-command:v bag_in_bag
-//@ lldb-check:[...] { x = { x = { x = 23 } } }
+//@ lldb-check:[...] {x:{x:{x:23}}}
 
 //@ lldb-command:v tjo
-//@ lldb-check:[...] { x = { x = { x = { x = 24 } } } }
+//@ lldb-check:[...] {x:{x:{x:{x:24}}}}
 
 //@ lldb-command:v tree
-//@ lldb-check:[...] { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } }
+//@ lldb-check:[...] {x:{x:25}, y:{x:{x:26, y:27}, y:{x:28, y:29}, z:{x:30, y:31}}, z:{x:{x:{x:32}}}}
 
 #![allow(unused_variables)]
 
diff --git a/tests/debuginfo/struct-with-destructor.rs b/tests/debuginfo/struct-with-destructor.rs
index a27ac14..a0ada74 100644
--- a/tests/debuginfo/struct-with-destructor.rs
+++ b/tests/debuginfo/struct-with-destructor.rs
@@ -22,16 +22,16 @@
 
 //@ lldb-command:run
 //@ lldb-command:v simple
-//@ lldb-check:[...] { x = 10 y = 20 }
+//@ lldb-check:[...] {x:10, y:20}
 
 //@ lldb-command:v noDestructor
-//@ lldb-check:[...] { a = { x = 10 y = 20 } guard = -1 }
+//@ lldb-check:[...] {a:{x:10, y:20}, guard:-1}
 
 //@ lldb-command:v withDestructor
-//@ lldb-check:[...] { a = { x = 10 y = 20 } guard = -1 }
+//@ lldb-check:[...] {a:{x:10, y:20}, guard:-1}
 
 //@ lldb-command:v nested
-//@ lldb-check:[...] { a = { a = { x = 7890 y = 9870 } } }
+//@ lldb-check:[...] {a:{a:{x:7890, y:9870}}}
 
 #![allow(unused_variables)]
 
diff --git a/tests/debuginfo/tuple-struct.rs b/tests/debuginfo/tuple-struct.rs
index 9992732..2f06ae4 100644
--- a/tests/debuginfo/tuple-struct.rs
+++ b/tests/debuginfo/tuple-struct.rs
@@ -30,22 +30,22 @@
 //@ lldb-command:run
 
 //@ lldb-command:v no_padding16
-//@ lldb-check:[...] { 0 = 10000 1 = -10001 }
+//@ lldb-check:[...] {0:10000, 1:-10001}
 
 //@ lldb-command:v no_padding32
-//@ lldb-check:[...] { 0 = -10002 1 = -10003.5 2 = 10004 }
+//@ lldb-check:[...] {0:-10002, 1:-10003.5, 2:10004}
 
 //@ lldb-command:v no_padding64
-//@ lldb-check:[...] { 0 = -10005.5 1 = 10006 2 = 10007 }
+//@ lldb-check:[...] {0:-10005.5, 1:10006, 2:10007}
 
 //@ lldb-command:v no_padding163264
-//@ lldb-check:[...] { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 }
+//@ lldb-check:[...] {0:-10008, 1:10009, 2:10010, 3:10011}
 
 //@ lldb-command:v internal_padding
-//@ lldb-check:[...] { 0 = 10012 1 = -10013 }
+//@ lldb-check:[...] {0:10012, 1:-10013}
 
 //@ lldb-command:v padding_at_end
-//@ lldb-check:[...] { 0 = -10014 1 = 10015 }
+//@ lldb-check:[...] {0:-10014, 1:10015}
 
 // This test case mainly makes sure that no field names are generated for tuple structs (as opposed
 // to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
diff --git a/tests/debuginfo/union-smoke.rs b/tests/debuginfo/union-smoke.rs
index 9934a32..bced679 100644
--- a/tests/debuginfo/union-smoke.rs
+++ b/tests/debuginfo/union-smoke.rs
@@ -14,10 +14,10 @@
 
 //@ lldb-command:run
 //@ lldb-command:v u
-//@ lldb-check:[...] { a = ('\x02', '\x02') b = 514 }
+//@ lldb-check:[...] {a:('\x02', '\x02'), b:514}
 
 //@ lldb-command:print union_smoke::SU
-//@ lldb-check:[...] { a = ('\x01', '\x01') b = 257 }
+//@ lldb-check:[...] {a:('\x01', '\x01'), b:257}
 
 #![allow(unused)]
 
diff --git a/tests/debuginfo/var-captured-in-nested-closure.rs b/tests/debuginfo/var-captured-in-nested-closure.rs
index 0fdc6df..aa3eec8 100644
--- a/tests/debuginfo/var-captured-in-nested-closure.rs
+++ b/tests/debuginfo/var-captured-in-nested-closure.rs
@@ -44,9 +44,9 @@
 //@ lldb-command:v constant
 //@ lldb-check:[...] 2
 //@ lldb-command:v a_struct
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *struct_ref
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *owned
 //@ lldb-check:[...] 6
 //@ lldb-command:v closure_local
@@ -58,9 +58,9 @@
 //@ lldb-command:v constant
 //@ lldb-check:[...] 2
 //@ lldb-command:v a_struct
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *struct_ref
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *owned
 //@ lldb-check:[...] 6
 //@ lldb-command:v closure_local
diff --git a/tests/debuginfo/var-captured-in-sendable-closure.rs b/tests/debuginfo/var-captured-in-sendable-closure.rs
index a52e1be..945c7b9 100644
--- a/tests/debuginfo/var-captured-in-sendable-closure.rs
+++ b/tests/debuginfo/var-captured-in-sendable-closure.rs
@@ -25,7 +25,7 @@
 //@ lldb-command:v constant
 //@ lldb-check:[...] 1
 //@ lldb-command:v a_struct
-//@ lldb-check:[...] { a = -2 b = 3.5 c = 4 }
+//@ lldb-check:[...] {a:-2, b:3.5, c:4}
 //@ lldb-command:v *owned
 //@ lldb-check:[...] 5
 
diff --git a/tests/debuginfo/var-captured-in-stack-closure.rs b/tests/debuginfo/var-captured-in-stack-closure.rs
index 31cf028..0a79d3b 100644
--- a/tests/debuginfo/var-captured-in-stack-closure.rs
+++ b/tests/debuginfo/var-captured-in-stack-closure.rs
@@ -40,9 +40,9 @@
 //@ lldb-command:v constant
 //@ lldb-check:[...] 2
 //@ lldb-command:v a_struct
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *struct_ref
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *owned
 //@ lldb-check:[...] 6
 
@@ -53,9 +53,9 @@
 //@ lldb-command:v constant
 //@ lldb-check:[...] 2
 //@ lldb-command:v a_struct
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *struct_ref
-//@ lldb-check:[...] { a = -3 b = 4.5 c = 5 }
+//@ lldb-check:[...] {a:-3, b:4.5, c:5}
 //@ lldb-command:v *owned
 //@ lldb-check:[...] 6
 
diff --git a/tests/debuginfo/vec-slices.rs b/tests/debuginfo/vec-slices.rs
index ad31ca8..b5e6268 100644
--- a/tests/debuginfo/vec-slices.rs
+++ b/tests/debuginfo/vec-slices.rs
@@ -70,7 +70,7 @@
 //@ lldb-check:[...] size=2 { [0] = (6, 7) [1] = (8, 9) }
 
 //@ lldb-command:v padded_struct
-//@ lldb-check:[...] size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } }
+//@ lldb-check:[...] size=2 { [0] = {x:10, y:11, z:12} [1] = {x:13, y:14, z:15} }
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/tests/debuginfo/vec.rs b/tests/debuginfo/vec.rs
index 375ec15..2d6162e 100644
--- a/tests/debuginfo/vec.rs
+++ b/tests/debuginfo/vec.rs
@@ -15,7 +15,7 @@
 
 //@ lldb-command:run
 //@ lldb-command:v a
-//@ lldb-check:[...] { [0] = 1 [1] = 2 [2] = 3 }
+//@ lldb-check:[...] ([0] = 1, [1] = 2, [2] = 3)
 
 #![allow(unused_variables)]
 
diff --git "a/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir" "b/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir"
deleted file mode 100644
index 0a1cab3..0000000
--- "a/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir"
+++ /dev/null
@@ -1,100 +0,0 @@
-// MIR for `a::{closure#0}` 0 coroutine_drop_async
-
-fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _2;
-    debug x => ((*_19).0: T);
-    let mut _0: std::task::Poll<()>;
-    let _3: T;
-    let mut _4: impl std::future::Future<Output = ()>;
-    let mut _5: &mut T;
-    let mut _6: std::pin::Pin<&mut T>;
-    let mut _7: &mut T;
-    let mut _8: std::task::Poll<()>;
-    let mut _9: &mut std::task::Context<'_>;
-    let mut _10: &mut impl std::future::Future<Output = ()>;
-    let mut _11: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
-    let mut _12: isize;
-    let mut _13: &mut std::task::Context<'_>;
-    let mut _14: &mut impl std::future::Future<Output = ()>;
-    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
-    let mut _16: isize;
-    let mut _17: ();
-    let mut _18: u32;
-    let mut _19: &mut {async fn body of a<T>()};
-    scope 1 {
-        debug x => (((*_19) as variant#4).0: T);
-    }
-
-    bb0: {
-        _19 = copy (_1.0: &mut {async fn body of a<T>()});
-        _18 = discriminant((*_19));
-        switchInt(move _18) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
-    }
-
-    bb1: {
-        nop;
-        nop;
-        goto -> bb2;
-    }
-
-    bb2: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-
-    bb3: {
-        _0 = Poll::<()>::Pending;
-        discriminant((*_19)) = 4;
-        return;
-    }
-
-    bb4: {
-        StorageLive(_15);
-        _14 = &mut (((*_19) as variant#4).1: impl std::future::Future<Output = ()>);
-        _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _14) -> [return: bb7, unwind unreachable];
-    }
-
-    bb5: {
-        unreachable;
-    }
-
-    bb6: {
-        StorageDead(_15);
-        _16 = discriminant(_8);
-        switchInt(move _16) -> [0: bb1, 1: bb3, otherwise: bb5];
-    }
-
-    bb7: {
-        _8 = <impl Future<Output = ()> as Future>::poll(move _15, move _13) -> [return: bb6, unwind unreachable];
-    }
-
-    bb8: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-
-    bb9: {
-        goto -> bb11;
-    }
-
-    bb10: {
-        goto -> bb8;
-    }
-
-    bb11: {
-        drop(((*_19).0: T)) -> [return: bb10, unwind unreachable];
-    }
-
-    bb12: {
-        goto -> bb4;
-    }
-
-    bb13: {
-        goto -> bb4;
-    }
-
-    bb14: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-}
diff --git "a/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir" "b/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir"
deleted file mode 100644
index 62fbf10..0000000
--- "a/tests/mir-opt/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir"
+++ /dev/null
@@ -1,123 +0,0 @@
-// MIR for `a::{closure#0}` 0 coroutine_drop_async
-
-fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _2;
-    debug x => ((*_19).0: T);
-    let mut _0: std::task::Poll<()>;
-    let _3: T;
-    let mut _4: impl std::future::Future<Output = ()>;
-    let mut _5: &mut T;
-    let mut _6: std::pin::Pin<&mut T>;
-    let mut _7: &mut T;
-    let mut _8: std::task::Poll<()>;
-    let mut _9: &mut std::task::Context<'_>;
-    let mut _10: &mut impl std::future::Future<Output = ()>;
-    let mut _11: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
-    let mut _12: isize;
-    let mut _13: &mut std::task::Context<'_>;
-    let mut _14: &mut impl std::future::Future<Output = ()>;
-    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
-    let mut _16: isize;
-    let mut _17: ();
-    let mut _18: u32;
-    let mut _19: &mut {async fn body of a<T>()};
-    scope 1 {
-        debug x => (((*_19) as variant#4).0: T);
-    }
-
-    bb0: {
-        _19 = copy (_1.0: &mut {async fn body of a<T>()});
-        _18 = discriminant((*_19));
-        switchInt(move _18) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
-    }
-
-    bb1: {
-        nop;
-        nop;
-        goto -> bb2;
-    }
-
-    bb2: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-
-    bb3 (cleanup): {
-        nop;
-        nop;
-        goto -> bb5;
-    }
-
-    bb4 (cleanup): {
-        goto -> bb15;
-    }
-
-    bb5 (cleanup): {
-        goto -> bb4;
-    }
-
-    bb6: {
-        _0 = Poll::<()>::Pending;
-        discriminant((*_19)) = 4;
-        return;
-    }
-
-    bb7: {
-        StorageLive(_15);
-        _14 = &mut (((*_19) as variant#4).1: impl std::future::Future<Output = ()>);
-        _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _14) -> [return: bb10, unwind: bb15];
-    }
-
-    bb8: {
-        unreachable;
-    }
-
-    bb9: {
-        StorageDead(_15);
-        _16 = discriminant(_8);
-        switchInt(move _16) -> [0: bb1, 1: bb6, otherwise: bb8];
-    }
-
-    bb10: {
-        _8 = <impl Future<Output = ()> as Future>::poll(move _15, move _13) -> [return: bb9, unwind: bb3];
-    }
-
-    bb11: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-
-    bb12: {
-        goto -> bb14;
-    }
-
-    bb13: {
-        goto -> bb11;
-    }
-
-    bb14: {
-        drop(((*_19).0: T)) -> [return: bb13, unwind: bb4];
-    }
-
-    bb15 (cleanup): {
-        discriminant((*_19)) = 2;
-        resume;
-    }
-
-    bb16: {
-        goto -> bb7;
-    }
-
-    bb17: {
-        goto -> bb7;
-    }
-
-    bb18: {
-        assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue];
-    }
-
-    bb19: {
-        _0 = Poll::<()>::Ready(const ());
-        return;
-    }
-}
diff --git "a/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir" "b/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir"
deleted file mode 100644
index d83a511..0000000
--- "a/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir"
+++ /dev/null
@@ -1,123 +0,0 @@
-// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
-
-fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: std::future::ResumeTy) -> ()
-yields ()
- {
-    let mut _0: ();
-    let mut _3: &mut [Foo; 1];
-    let mut _4: *mut [Foo; 1];
-    let mut _5: *mut [Foo];
-    let mut _6: usize;
-    let mut _7: usize;
-    let mut _8: *mut Foo;
-    let mut _9: bool;
-    let mut _10: *mut Foo;
-    let mut _11: bool;
-    let mut _12: impl std::future::Future<Output = ()>;
-    let mut _13: &mut Foo;
-    let mut _14: std::pin::Pin<&mut Foo>;
-    let mut _15: &mut Foo;
-    let mut _16: *mut Foo;
-    let mut _17: bool;
-    let mut _18: impl std::future::Future<Output = ()>;
-    let mut _19: &mut Foo;
-    let mut _20: std::pin::Pin<&mut Foo>;
-    let mut _21: &mut Foo;
-
-    bb0: {
-        _3 = move (_1.0: &mut [Foo; 1]);
-        goto -> bb17;
-    }
-
-    bb1: {
-        return;
-    }
-
-    bb2 (cleanup): {
-        resume;
-    }
-
-    bb3 (cleanup): {
-        _8 = &raw mut (*_5)[_7];
-        _7 = Add(move _7, const 1_usize);
-        drop((*_8)) -> [return: bb4, unwind terminate(cleanup)];
-    }
-
-    bb4 (cleanup): {
-        StorageDead(_12);
-        StorageDead(_18);
-        _9 = Eq(copy _7, copy _6);
-        switchInt(move _9) -> [0: bb3, otherwise: bb2];
-    }
-
-    bb5: {
-        _10 = &raw mut (*_5)[_7];
-        _7 = Add(move _7, const 1_usize);
-        _13 = &mut (*_10);
-        _14 = Pin::<&mut Foo>::new_unchecked(move _13) -> [return: bb9, unwind: bb4];
-    }
-
-    bb6: {
-        StorageDead(_18);
-        _11 = Eq(copy _7, copy _6);
-        switchInt(move _11) -> [0: bb5, otherwise: bb1];
-    }
-
-    bb7: {
-        StorageDead(_12);
-        goto -> bb6;
-    }
-
-    bb8: {
-        async drop((*_10); poll=_12) -> [return: bb7, unwind: bb4];
-    }
-
-    bb9: {
-        _15 = copy (_14.0: &mut Foo);
-        StorageLive(_12);
-        _12 = async_drop_in_place::<Foo>(move _15) -> [return: bb8, unwind: bb4];
-    }
-
-    bb10: {
-        _16 = &raw mut (*_5)[_7];
-        _7 = Add(move _7, const 1_usize);
-        _19 = &mut (*_16);
-        _20 = Pin::<&mut Foo>::new_unchecked(move _19) -> [return: bb14, unwind: bb4];
-    }
-
-    bb11: {
-        _17 = Eq(copy _7, copy _6);
-        switchInt(move _17) -> [0: bb10, otherwise: bb1];
-    }
-
-    bb12: {
-        StorageDead(_18);
-        goto -> bb11;
-    }
-
-    bb13: {
-        async drop((*_16); poll=_18) -> [return: bb12, unwind: bb4, drop: bb6];
-    }
-
-    bb14: {
-        _21 = copy (_20.0: &mut Foo);
-        StorageLive(_18);
-        _18 = async_drop_in_place::<Foo>(move _21) -> [return: bb13, unwind: bb4];
-    }
-
-    bb15: {
-        _6 = PtrMetadata(copy _5);
-        _7 = const 0_usize;
-        goto -> bb11;
-    }
-
-    bb16: {
-        goto -> bb15;
-    }
-
-    bb17: {
-        _4 = &raw mut (*_3);
-        _5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit));
-        goto -> bb16;
-    }
-}
diff --git "a/tests/mir-opt/building/async_await.a-\173closure\0430\175.coroutine_resume.0.mir" "b/tests/mir-opt/building/async_await.a-\173closure\0430\175.coroutine_resume.0.mir"
deleted file mode 100644
index 6cad5b1..0000000
--- "a/tests/mir-opt/building/async_await.a-\173closure\0430\175.coroutine_resume.0.mir"
+++ /dev/null
@@ -1,47 +0,0 @@
-// MIR for `a::{closure#0}` 0 coroutine_resume
-/* coroutine_layout = CoroutineLayout {
-    field_tys: {},
-    variant_fields: {
-        Unresumed(0): [],
-        Returned (1): [],
-        Panicked (2): [],
-    },
-    storage_conflicts: BitMatrix(0x0) {},
-} */
-
-fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _2;
-    let mut _0: std::task::Poll<()>;
-    let mut _3: ();
-    let mut _4: u32;
-    let mut _5: &mut {async fn body of a()};
-
-    bb0: {
-        _5 = copy (_1.0: &mut {async fn body of a()});
-        _4 = discriminant((*_5));
-        switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5];
-    }
-
-    bb1: {
-        _3 = const ();
-        goto -> bb3;
-    }
-
-    bb2: {
-        _0 = Poll::<()>::Ready(move _3);
-        discriminant((*_5)) = 1;
-        return;
-    }
-
-    bb3: {
-        goto -> bb2;
-    }
-
-    bb4: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind unreachable];
-    }
-
-    bb5: {
-        unreachable;
-    }
-}
diff --git "a/tests/mir-opt/building/async_await.b-\173closure\0430\175.coroutine_resume.0.mir" "b/tests/mir-opt/building/async_await.b-\173closure\0430\175.coroutine_resume.0.mir"
deleted file mode 100644
index 96ee371..0000000
--- "a/tests/mir-opt/building/async_await.b-\173closure\0430\175.coroutine_resume.0.mir"
+++ /dev/null
@@ -1,344 +0,0 @@
-// MIR for `b::{closure#0}` 0 coroutine_resume
-/* coroutine_layout = CoroutineLayout {
-    field_tys: {
-        _s0: CoroutineSavedTy {
-            ty: Coroutine(
-                DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
-                [
-                    (),
-                    std::future::ResumeTy,
-                    (),
-                    (),
-                    (),
-                ],
-            ),
-            source_info: SourceInfo {
-                span: $DIR/async_await.rs:16:5: 16:14 (#9),
-                scope: scope[0],
-            },
-            ignore_for_traits: false,
-        },
-        _s1: CoroutineSavedTy {
-            ty: Coroutine(
-                DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
-                [
-                    (),
-                    std::future::ResumeTy,
-                    (),
-                    (),
-                    (),
-                ],
-            ),
-            source_info: SourceInfo {
-                span: $DIR/async_await.rs:17:5: 17:14 (#11),
-                scope: scope[0],
-            },
-            ignore_for_traits: false,
-        },
-    },
-    variant_fields: {
-        Unresumed(0): [],
-        Returned (1): [],
-        Panicked (2): [],
-        Suspend0 (3): [_s0],
-        Suspend1 (4): [_s1],
-    },
-    storage_conflicts: BitMatrix(2x2) {
-        (_s0, _s0),
-        (_s1, _s1),
-    },
-} */
-
-fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
-    debug _task_context => _2;
-    let mut _0: std::task::Poll<()>;
-    let _3: ();
-    let mut _4: {async fn body of a()};
-    let mut _5: {async fn body of a()};
-    let mut _6: {async fn body of a()};
-    let mut _7: ();
-    let _8: ();
-    let mut _9: std::task::Poll<()>;
-    let mut _10: std::pin::Pin<&mut {async fn body of a()}>;
-    let mut _11: &mut {async fn body of a()};
-    let mut _12: &mut {async fn body of a()};
-    let mut _13: &mut std::task::Context<'_>;
-    let mut _14: &mut std::task::Context<'_>;
-    let mut _15: &mut std::task::Context<'_>;
-    let mut _16: isize;
-    let mut _18: !;
-    let mut _19: &mut std::task::Context<'_>;
-    let mut _20: ();
-    let mut _21: {async fn body of a()};
-    let mut _22: {async fn body of a()};
-    let mut _23: {async fn body of a()};
-    let _24: ();
-    let mut _25: std::task::Poll<()>;
-    let mut _26: std::pin::Pin<&mut {async fn body of a()}>;
-    let mut _27: &mut {async fn body of a()};
-    let mut _28: &mut {async fn body of a()};
-    let mut _29: &mut std::task::Context<'_>;
-    let mut _30: &mut std::task::Context<'_>;
-    let mut _31: &mut std::task::Context<'_>;
-    let mut _32: isize;
-    let mut _34: !;
-    let mut _35: &mut std::task::Context<'_>;
-    let mut _36: ();
-    let mut _37: ();
-    let mut _38: u32;
-    let mut _39: &mut {async fn body of b()};
-    scope 1 {
-        debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()});
-        let _17: ();
-        scope 2 {
-            debug result => _17;
-        }
-    }
-    scope 3 {
-        debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()});
-        let _33: ();
-        scope 4 {
-            debug result => _33;
-        }
-    }
-
-    bb0: {
-        _39 = copy (_1.0: &mut {async fn body of b()});
-        _38 = discriminant((*_39));
-        switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
-    }
-
-    bb1: {
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        _5 = a() -> [return: bb2, unwind unreachable];
-    }
-
-    bb2: {
-        _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable];
-    }
-
-    bb3: {
-        StorageDead(_5);
-        PlaceMention(_4);
-        nop;
-        (((*_39) as variant#3).0: {async fn body of a()}) = move _4;
-        goto -> bb4;
-    }
-
-    bb4: {
-        StorageLive(_8);
-        StorageLive(_9);
-        StorageLive(_10);
-        StorageLive(_11);
-        StorageLive(_12);
-        _12 = &mut (((*_39) as variant#3).0: {async fn body of a()});
-        _11 = &mut (*_12);
-        _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable];
-    }
-
-    bb5: {
-        StorageDead(_11);
-        StorageLive(_13);
-        StorageLive(_14);
-        StorageLive(_15);
-        _15 = copy _2;
-        _14 = move _15;
-        goto -> bb6;
-    }
-
-    bb6: {
-        _13 = &mut (*_14);
-        StorageDead(_15);
-        _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable];
-    }
-
-    bb7: {
-        StorageDead(_13);
-        StorageDead(_10);
-        PlaceMention(_9);
-        _16 = discriminant(_9);
-        switchInt(move _16) -> [0: bb10, 1: bb9, otherwise: bb8];
-    }
-
-    bb8: {
-        unreachable;
-    }
-
-    bb9: {
-        _8 = const ();
-        StorageDead(_14);
-        StorageDead(_12);
-        StorageDead(_9);
-        StorageDead(_8);
-        StorageLive(_19);
-        StorageLive(_20);
-        _20 = ();
-        _0 = Poll::<()>::Pending;
-        StorageDead(_3);
-        StorageDead(_4);
-        StorageDead(_19);
-        StorageDead(_20);
-        discriminant((*_39)) = 3;
-        return;
-    }
-
-    bb10: {
-        StorageLive(_17);
-        _17 = copy ((_9 as Ready).0: ());
-        _3 = copy _17;
-        StorageDead(_17);
-        StorageDead(_14);
-        StorageDead(_12);
-        StorageDead(_9);
-        StorageDead(_8);
-        drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable];
-    }
-
-    bb11: {
-        StorageDead(_20);
-        _2 = move _19;
-        StorageDead(_19);
-        _7 = const ();
-        goto -> bb4;
-    }
-
-    bb12: {
-        nop;
-        goto -> bb13;
-    }
-
-    bb13: {
-        StorageDead(_4);
-        StorageDead(_3);
-        StorageLive(_21);
-        StorageLive(_22);
-        _22 = a() -> [return: bb14, unwind unreachable];
-    }
-
-    bb14: {
-        _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable];
-    }
-
-    bb15: {
-        StorageDead(_22);
-        PlaceMention(_21);
-        nop;
-        (((*_39) as variant#4).0: {async fn body of a()}) = move _21;
-        goto -> bb16;
-    }
-
-    bb16: {
-        StorageLive(_24);
-        StorageLive(_25);
-        StorageLive(_26);
-        StorageLive(_27);
-        StorageLive(_28);
-        _28 = &mut (((*_39) as variant#4).0: {async fn body of a()});
-        _27 = &mut (*_28);
-        _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable];
-    }
-
-    bb17: {
-        StorageDead(_27);
-        StorageLive(_29);
-        StorageLive(_30);
-        StorageLive(_31);
-        _31 = copy _2;
-        _30 = move _31;
-        goto -> bb18;
-    }
-
-    bb18: {
-        _29 = &mut (*_30);
-        StorageDead(_31);
-        _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable];
-    }
-
-    bb19: {
-        StorageDead(_29);
-        StorageDead(_26);
-        PlaceMention(_25);
-        _32 = discriminant(_25);
-        switchInt(move _32) -> [0: bb21, 1: bb20, otherwise: bb8];
-    }
-
-    bb20: {
-        _24 = const ();
-        StorageDead(_30);
-        StorageDead(_28);
-        StorageDead(_25);
-        StorageDead(_24);
-        StorageLive(_35);
-        StorageLive(_36);
-        _36 = ();
-        _0 = Poll::<()>::Pending;
-        StorageDead(_21);
-        StorageDead(_35);
-        StorageDead(_36);
-        discriminant((*_39)) = 4;
-        return;
-    }
-
-    bb21: {
-        StorageLive(_33);
-        _33 = copy ((_25 as Ready).0: ());
-        _37 = copy _33;
-        StorageDead(_33);
-        StorageDead(_30);
-        StorageDead(_28);
-        StorageDead(_25);
-        StorageDead(_24);
-        drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable];
-    }
-
-    bb22: {
-        StorageDead(_36);
-        _2 = move _35;
-        StorageDead(_35);
-        _7 = const ();
-        goto -> bb16;
-    }
-
-    bb23: {
-        nop;
-        goto -> bb24;
-    }
-
-    bb24: {
-        StorageDead(_21);
-        goto -> bb26;
-    }
-
-    bb25: {
-        _0 = Poll::<()>::Ready(move _37);
-        discriminant((*_39)) = 1;
-        return;
-    }
-
-    bb26: {
-        goto -> bb25;
-    }
-
-    bb27: {
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_19);
-        StorageLive(_20);
-        _19 = move _2;
-        goto -> bb11;
-    }
-
-    bb28: {
-        StorageLive(_21);
-        StorageLive(_35);
-        StorageLive(_36);
-        _35 = move _2;
-        goto -> bb22;
-    }
-
-    bb29: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable];
-    }
-}
diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs
deleted file mode 100644
index e84f8a6..0000000
--- a/tests/mir-opt/building/async_await.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ skip-filecheck
-// This test makes sure that the coroutine MIR pass eliminates all calls to
-// `get_context`, and that the MIR argument type for an async fn and all locals
-// related to `yield` are `&mut Context`, and its return type is `Poll`.
-
-//@ edition:2018
-//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
-
-#![crate_type = "lib"]
-
-// EMIT_MIR async_await.a-{closure#0}.coroutine_resume.0.mir
-async fn a() {}
-
-// EMIT_MIR async_await.b-{closure#0}.coroutine_resume.0.mir
-pub async fn b() {
-    a().await;
-    a().await
-}
diff --git "a/tests/mir-opt/building/coroutine.main-\173closure\0430\175.StateTransform.after.mir" "b/tests/mir-opt/building/coroutine.main-\173closure\0430\175.StateTransform.after.mir"
deleted file mode 100644
index b61215d..0000000
--- "a/tests/mir-opt/building/coroutine.main-\173closure\0430\175.StateTransform.after.mir"
+++ /dev/null
@@ -1,193 +0,0 @@
-// MIR for `main::{closure#0}` after StateTransform
-/* coroutine_layout = CoroutineLayout {
-    field_tys: {
-        _s0: CoroutineSavedTy {
-            ty: std::string::String,
-            source_info: SourceInfo {
-                span: $DIR/coroutine.rs:18:6: 18:9 (#0),
-                scope: scope[0],
-            },
-            ignore_for_traits: false,
-        },
-    },
-    variant_fields: {
-        Unresumed(0): [],
-        Returned (1): [],
-        Panicked (2): [],
-        Suspend0 (3): [_s0],
-        Suspend1 (4): [_s0],
-    },
-    storage_conflicts: BitMatrix(1x1) {
-        (_s0, _s0),
-    },
-} */
-
-fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
-    debug arg => (((*_18) as variant#4).0: std::string::String);
-    let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
-    let _3: std::string::String;
-    let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
-    let mut _5: std::string::String;
-    let mut _6: &std::string::String;
-    let mut _7: &std::panic::Location<'_>;
-    let _8: std::string::String;
-    let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
-    let mut _10: &str;
-    let _11: &str;
-    let mut _12: std::string::String;
-    let mut _13: &std::string::String;
-    let mut _14: &std::panic::Location<'_>;
-    let _15: &std::panic::Location<'_>;
-    let mut _16: ();
-    let mut _17: u32;
-    let mut _18: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
-
-    bb0: {
-        _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
-        _17 = discriminant((*_18));
-        switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
-    }
-
-    bb1: {
-        (((*_18) as variant#4).0: std::string::String) = move _2;
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        StorageLive(_6);
-        _6 = &(((*_18) as variant#4).0: std::string::String);
-        _5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
-    }
-
-    bb2: {
-        StorageDead(_6);
-        StorageLive(_7);
-        _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
-    }
-
-    bb3: {
-        _4 = (const "first", move _5, move _7);
-        StorageDead(_7);
-        goto -> bb4;
-    }
-
-    bb4: {
-        StorageDead(_5);
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
-        StorageDead(_3);
-        StorageDead(_4);
-        discriminant((*_18)) = 3;
-        return;
-    }
-
-    bb5: {
-        goto -> bb6;
-    }
-
-    bb6: {
-        StorageDead(_4);
-        drop(_3) -> [return: bb7, unwind unreachable];
-    }
-
-    bb7: {
-        StorageDead(_3);
-        StorageLive(_8);
-        StorageLive(_9);
-        StorageLive(_10);
-        StorageLive(_11);
-        _11 = const "second";
-        _10 = &(*_11);
-        StorageLive(_12);
-        StorageLive(_13);
-        _13 = &(((*_18) as variant#4).0: std::string::String);
-        _12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
-    }
-
-    bb8: {
-        StorageDead(_13);
-        StorageLive(_14);
-        StorageLive(_15);
-        _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
-    }
-
-    bb9: {
-        _14 = &(*_15);
-        _9 = (move _10, move _12, move _14);
-        StorageDead(_14);
-        goto -> bb10;
-    }
-
-    bb10: {
-        StorageDead(_12);
-        StorageDead(_10);
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
-        StorageDead(_8);
-        StorageDead(_9);
-        StorageDead(_11);
-        StorageDead(_15);
-        discriminant((*_18)) = 4;
-        return;
-    }
-
-    bb11: {
-        goto -> bb12;
-    }
-
-    bb12: {
-        StorageDead(_9);
-        drop(_8) -> [return: bb13, unwind unreachable];
-    }
-
-    bb13: {
-        StorageDead(_15);
-        StorageDead(_11);
-        StorageDead(_8);
-        _16 = const ();
-        drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
-    }
-
-    bb14: {
-        goto -> bb16;
-    }
-
-    bb15: {
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
-        discriminant((*_18)) = 1;
-        return;
-    }
-
-    bb16: {
-        goto -> bb15;
-    }
-
-    bb17: {
-        StorageLive(_3);
-        StorageLive(_4);
-        _3 = move _2;
-        goto -> bb5;
-    }
-
-    bb18: {
-        StorageLive(_8);
-        StorageLive(_9);
-        StorageLive(_11);
-        StorageLive(_15);
-        _8 = move _2;
-        goto -> bb11;
-    }
-
-    bb19: {
-        assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
-    }
-
-    bb20: {
-        unreachable;
-    }
-}
-
-ALLOC0 (size: 6, align: 1) {
-    73 65 63 6f 6e 64                               │ second
-}
-
-ALLOC1 (size: 5, align: 1) {
-    66 69 72 73 74                                  │ first
-}
diff --git "a/tests/mir-opt/building/coroutine.main-\173closure\0431\175.StateTransform.after.mir" "b/tests/mir-opt/building/coroutine.main-\173closure\0431\175.StateTransform.after.mir"
deleted file mode 100644
index aac028a..0000000
--- "a/tests/mir-opt/building/coroutine.main-\173closure\0431\175.StateTransform.after.mir"
+++ /dev/null
@@ -1,193 +0,0 @@
-// MIR for `main::{closure#1}` after StateTransform
-/* coroutine_layout = CoroutineLayout {
-    field_tys: {
-        _s0: CoroutineSavedTy {
-            ty: std::string::String,
-            source_info: SourceInfo {
-                span: $DIR/coroutine.rs:25:6: 25:9 (#0),
-                scope: scope[0],
-            },
-            ignore_for_traits: false,
-        },
-    },
-    variant_fields: {
-        Unresumed(0): [],
-        Returned (1): [],
-        Panicked (2): [],
-        Suspend0 (3): [_s0],
-        Suspend1 (4): [_s0],
-    },
-    storage_conflicts: BitMatrix(1x1) {
-        (_s0, _s0),
-    },
-} */
-
-fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
-    debug arg => (((*_18) as variant#4).0: std::string::String);
-    let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
-    let _3: std::string::String;
-    let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
-    let mut _5: std::string::String;
-    let mut _6: &std::string::String;
-    let mut _7: &std::panic::Location<'_>;
-    let _8: std::string::String;
-    let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
-    let mut _10: &str;
-    let _11: &str;
-    let mut _12: std::string::String;
-    let mut _13: &std::string::String;
-    let mut _14: &std::panic::Location<'_>;
-    let _15: &std::panic::Location<'_>;
-    let mut _16: ();
-    let mut _17: u32;
-    let mut _18: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
-
-    bb0: {
-        _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
-        _17 = discriminant((*_18));
-        switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
-    }
-
-    bb1: {
-        (((*_18) as variant#4).0: std::string::String) = move _2;
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        StorageLive(_6);
-        _6 = &(((*_18) as variant#4).0: std::string::String);
-        _5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
-    }
-
-    bb2: {
-        StorageDead(_6);
-        StorageLive(_7);
-        _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
-    }
-
-    bb3: {
-        _4 = (const "first", move _5, move _7);
-        StorageDead(_7);
-        goto -> bb4;
-    }
-
-    bb4: {
-        StorageDead(_5);
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
-        StorageDead(_3);
-        StorageDead(_4);
-        discriminant((*_18)) = 3;
-        return;
-    }
-
-    bb5: {
-        goto -> bb6;
-    }
-
-    bb6: {
-        StorageDead(_4);
-        drop(_3) -> [return: bb7, unwind unreachable];
-    }
-
-    bb7: {
-        StorageDead(_3);
-        StorageLive(_8);
-        StorageLive(_9);
-        StorageLive(_10);
-        StorageLive(_11);
-        _11 = const "second";
-        _10 = &(*_11);
-        StorageLive(_12);
-        StorageLive(_13);
-        _13 = &(((*_18) as variant#4).0: std::string::String);
-        _12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
-    }
-
-    bb8: {
-        StorageDead(_13);
-        StorageLive(_14);
-        StorageLive(_15);
-        _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
-    }
-
-    bb9: {
-        _14 = &(*_15);
-        _9 = (move _10, move _12, move _14);
-        StorageDead(_14);
-        goto -> bb10;
-    }
-
-    bb10: {
-        StorageDead(_12);
-        StorageDead(_10);
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
-        StorageDead(_8);
-        StorageDead(_9);
-        StorageDead(_11);
-        StorageDead(_15);
-        discriminant((*_18)) = 4;
-        return;
-    }
-
-    bb11: {
-        goto -> bb12;
-    }
-
-    bb12: {
-        StorageDead(_9);
-        drop(_8) -> [return: bb13, unwind unreachable];
-    }
-
-    bb13: {
-        StorageDead(_15);
-        StorageDead(_11);
-        StorageDead(_8);
-        _16 = const ();
-        drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
-    }
-
-    bb14: {
-        goto -> bb16;
-    }
-
-    bb15: {
-        _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
-        discriminant((*_18)) = 1;
-        return;
-    }
-
-    bb16: {
-        goto -> bb15;
-    }
-
-    bb17: {
-        StorageLive(_3);
-        StorageLive(_4);
-        _3 = move _2;
-        goto -> bb5;
-    }
-
-    bb18: {
-        StorageLive(_8);
-        StorageLive(_9);
-        StorageLive(_11);
-        StorageLive(_15);
-        _8 = move _2;
-        goto -> bb11;
-    }
-
-    bb19: {
-        assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
-    }
-
-    bb20: {
-        unreachable;
-    }
-}
-
-ALLOC0 (size: 6, align: 1) {
-    73 65 63 6f 6e 64                               │ second
-}
-
-ALLOC1 (size: 5, align: 1) {
-    66 69 72 73 74                                  │ first
-}
diff --git "a/tests/mir-opt/coroutine/async_await.a-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_await.a-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..dddd66e
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_await.a-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,56 @@
+- // MIR for `a::{closure#0}` before StateTransform
++ // MIR for `a::{closure#0}` after StateTransform
+  
+- fn a::{closure#0}(_1: {async fn body of a()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     let mut _0: std::task::Poll<()>;
++     let mut _3: ();
++     let mut _4: u32;
++     let mut _5: &mut {async fn body of a()};
+  
+      bb0: {
+-         _0 = const ();
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _5 = copy (_1.0: &mut {async fn body of a()});
++         _4 = discriminant((*_5));
++         switchInt(move _4) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _3);
++         discriminant((*_5)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         _3 = const ();
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_await.b-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_await.b-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..fdbc67d
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_await.b-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,543 @@
+- // MIR for `b::{closure#0}` before StateTransform
++ // MIR for `b::{closure#0}` after StateTransform
+  
+- fn b::{closure#0}(_1: {async fn body of b()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: {async fn body of a()};
++         field _s1: {async fn body of a()};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++             Suspend1 (4): [_s1],
++         }
++         storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug __awaitee => _s0;
++     coroutine debug __awaitee => _s1;
++     let mut _0: std::task::Poll<()>;
+      let _3: ();
+      let mut _4: {async fn body of a()};
+      let mut _5: {async fn body of a()};
+      let mut _6: {async fn body of a()};
+      let mut _7: ();
+      let _8: ();
+      let mut _9: std::task::Poll<()>;
+      let mut _10: std::pin::Pin<&mut {async fn body of a()}>;
+      let mut _11: &mut {async fn body of a()};
+      let mut _12: &mut {async fn body of a()};
+      let mut _13: &mut std::task::Context<'_>;
+      let mut _14: &mut std::task::Context<'_>;
+-     let mut _15: std::future::ResumeTy;
++     let mut _15: &mut std::task::Context<'_>;
+      let mut _16: isize;
+      let mut _18: !;
+-     let mut _19: std::future::ResumeTy;
++     let mut _19: &mut std::task::Context<'_>;
+      let mut _20: ();
+      let mut _21: {async fn body of a()};
+      let mut _22: {async fn body of a()};
+      let mut _23: {async fn body of a()};
+      let _24: ();
+      let mut _25: std::task::Poll<()>;
+      let mut _26: std::pin::Pin<&mut {async fn body of a()}>;
+      let mut _27: &mut {async fn body of a()};
+      let mut _28: &mut {async fn body of a()};
+      let mut _29: &mut std::task::Context<'_>;
+      let mut _30: &mut std::task::Context<'_>;
+-     let mut _31: std::future::ResumeTy;
++     let mut _31: &mut std::task::Context<'_>;
+      let mut _32: isize;
+      let mut _34: !;
+-     let mut _35: std::future::ResumeTy;
++     let mut _35: &mut std::task::Context<'_>;
+      let mut _36: ();
++     let mut _37: ();
++     let mut _38: u32;
++     let mut _39: &mut {async fn body of b()};
+      scope 1 {
+-         debug __awaitee => _6;
++         debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()});
+          let _17: ();
+          scope 2 {
+              debug result => _17;
+          }
+      }
+      scope 3 {
+-         debug __awaitee => _23;
++         debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()});
+          let _33: ();
+          scope 4 {
+              debug result => _33;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         StorageLive(_4);
+-         StorageLive(_5);
+-         _5 = a() -> [return: bb1, unwind: bb47];
++         _39 = copy (_1.0: &mut {async fn body of b()});
++         _38 = discriminant((*_39));
++         switchInt(move _38) -> [0: bb47, 1: bb46, 2: bb45, 3: bb43, 4: bb44, otherwise: bb7];
+      }
+  
+      bb1: {
+-         _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb2, unwind: bb46];
++         _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb2, unwind: bb36];
+      }
+  
+      bb2: {
+          StorageDead(_5);
+          PlaceMention(_4);
+-         StorageLive(_6);
+-         _6 = move _4;
++         nop;
++         (((*_39) as variant#3).0: {async fn body of a()}) = move _4;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageLive(_8);
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+-         _12 = &mut _6;
++         _12 = &mut (((*_39) as variant#3).0: {async fn body of a()});
+          _11 = &mut (*_12);
+-         _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb4, unwind: bb43];
++         _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb4, unwind: bb33];
+      }
+  
+      bb4: {
+          StorageDead(_11);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+          _15 = copy _2;
+-         _14 = std::future::get_context::<'_, '_>(move _15) -> [return: bb5, unwind: bb41];
++         _14 = move _15;
++         goto -> bb5;
+      }
+  
+      bb5: {
+          _13 = &mut (*_14);
+          StorageDead(_15);
+-         _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb6, unwind: bb42];
++         _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb6, unwind: bb32];
+      }
+  
+      bb6: {
+          StorageDead(_13);
+          StorageDead(_10);
+          PlaceMention(_9);
+          _16 = discriminant(_9);
+          switchInt(move _16) -> [0: bb9, 1: bb8, otherwise: bb7];
+      }
+  
+      bb7: {
+          unreachable;
+      }
+  
+      bb8: {
+          _8 = const ();
+          StorageDead(_14);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_8);
+          StorageLive(_19);
+          StorageLive(_20);
+          _20 = ();
+-         _19 = yield(move _20) -> [resume: bb10, drop: bb28];
++         _0 = Poll::<()>::Pending;
++         StorageDead(_3);
++         StorageDead(_4);
++         StorageDead(_19);
++         StorageDead(_20);
++         discriminant((*_39)) = 3;
++         return;
+      }
+  
+      bb9: {
+          StorageLive(_17);
+          _17 = copy ((_9 as Ready).0: ());
+          _3 = copy _17;
+          StorageDead(_17);
+          StorageDead(_14);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_8);
+-         drop(_6) -> [return: bb11, unwind: bb45];
++         drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb11, unwind: bb35];
+      }
+  
+      bb10: {
+          StorageDead(_20);
+          _2 = move _19;
+          StorageDead(_19);
+          _7 = const ();
+          goto -> bb3;
+      }
+  
+      bb11: {
+-         StorageDead(_6);
++         nop;
+          goto -> bb12;
+      }
+  
+      bb12: {
+          StorageDead(_4);
+          StorageDead(_3);
+          StorageLive(_21);
+          StorageLive(_22);
+-         _22 = a() -> [return: bb13, unwind: bb39];
++         _22 = a() -> [return: bb13, unwind: bb30];
+      }
+  
+      bb13: {
+-         _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb14, unwind: bb38];
++         _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb14, unwind: bb29];
+      }
+  
+      bb14: {
+          StorageDead(_22);
+          PlaceMention(_21);
+-         StorageLive(_23);
+-         _23 = move _21;
++         nop;
++         (((*_39) as variant#4).0: {async fn body of a()}) = move _21;
+          goto -> bb15;
+      }
+  
+      bb15: {
+          StorageLive(_24);
+          StorageLive(_25);
+          StorageLive(_26);
+          StorageLive(_27);
+          StorageLive(_28);
+-         _28 = &mut _23;
++         _28 = &mut (((*_39) as variant#4).0: {async fn body of a()});
+          _27 = &mut (*_28);
+-         _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb16, unwind: bb35];
++         _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb16, unwind: bb26];
+      }
+  
+      bb16: {
+          StorageDead(_27);
+          StorageLive(_29);
+          StorageLive(_30);
+          StorageLive(_31);
+          _31 = copy _2;
+-         _30 = std::future::get_context::<'_, '_>(move _31) -> [return: bb17, unwind: bb33];
++         _30 = move _31;
++         goto -> bb17;
+      }
+  
+      bb17: {
+          _29 = &mut (*_30);
+          StorageDead(_31);
+-         _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb18, unwind: bb34];
++         _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb18, unwind: bb25];
+      }
+  
+      bb18: {
+          StorageDead(_29);
+          StorageDead(_26);
+          PlaceMention(_25);
+          _32 = discriminant(_25);
+          switchInt(move _32) -> [0: bb20, 1: bb19, otherwise: bb7];
+      }
+  
+      bb19: {
+          _24 = const ();
+          StorageDead(_30);
+          StorageDead(_28);
+          StorageDead(_25);
+          StorageDead(_24);
+          StorageLive(_35);
+          StorageLive(_36);
+          _36 = ();
+-         _35 = yield(move _36) -> [resume: bb21, drop: bb25];
++         _0 = Poll::<()>::Pending;
++         StorageDead(_21);
++         StorageDead(_35);
++         StorageDead(_36);
++         discriminant((*_39)) = 4;
++         return;
+      }
+  
+      bb20: {
+          StorageLive(_33);
+          _33 = copy ((_25 as Ready).0: ());
+-         _0 = copy _33;
++         _37 = copy _33;
+          StorageDead(_33);
+          StorageDead(_30);
+          StorageDead(_28);
+          StorageDead(_25);
+          StorageDead(_24);
+-         drop(_23) -> [return: bb22, unwind: bb37];
++         drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb22, unwind: bb28];
+      }
+  
+      bb21: {
+          StorageDead(_36);
+          _2 = move _35;
+          StorageDead(_35);
+          _7 = const ();
+          goto -> bb15;
+      }
+  
+      bb22: {
+-         StorageDead(_23);
++         nop;
+          goto -> bb23;
+      }
+  
+      bb23: {
+          StorageDead(_21);
+-         drop(_1) -> [return: bb24, unwind: bb50];
++         goto -> bb41;
+      }
+  
+      bb24: {
++         _0 = Poll::<()>::Ready(move _37);
++         discriminant((*_39)) = 1;
+          return;
+      }
+  
+-     bb25: {
+-         StorageDead(_36);
+-         StorageDead(_35);
+-         drop(_23) -> [return: bb26, unwind: bb51];
+-     }
+- 
+-     bb26: {
+-         StorageDead(_23);
+-         goto -> bb27;
+-     }
+- 
+-     bb27: {
+-         StorageDead(_21);
+-         goto -> bb31;
+-     }
+- 
+-     bb28: {
+-         StorageDead(_20);
+-         StorageDead(_19);
+-         drop(_6) -> [return: bb29, unwind: bb53];
+-     }
+- 
+-     bb29: {
+-         StorageDead(_6);
+-         goto -> bb30;
+-     }
+- 
+-     bb30: {
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         goto -> bb31;
+-     }
+- 
+-     bb31: {
+-         drop(_1) -> [return: bb32, unwind: bb50];
+-     }
+- 
+-     bb32: {
+-         coroutine_drop;
+-     }
+- 
+-     bb33 (cleanup): {
+-         StorageDead(_31);
+-         goto -> bb34;
+-     }
+- 
+-     bb34 (cleanup): {
++     bb25 (cleanup): {
+          StorageDead(_29);
+          StorageDead(_26);
+          StorageDead(_30);
+-         goto -> bb36;
++         goto -> bb27;
+      }
+  
+-     bb35 (cleanup): {
++     bb26 (cleanup): {
+          StorageDead(_27);
+          StorageDead(_26);
+-         goto -> bb36;
++         goto -> bb27;
+      }
+  
+-     bb36 (cleanup): {
++     bb27 (cleanup): {
+          StorageDead(_28);
+          StorageDead(_25);
+          StorageDead(_24);
+-         drop(_23) -> [return: bb37, unwind terminate(cleanup)];
++         drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb28, unwind terminate(cleanup)];
+      }
+  
+-     bb37 (cleanup): {
+-         StorageDead(_23);
+-         goto -> bb40;
++     bb28 (cleanup): {
++         nop;
++         goto -> bb31;
+      }
+  
+-     bb38 (cleanup): {
+-         goto -> bb39;
++     bb29 (cleanup): {
++         goto -> bb30;
+      }
+  
+-     bb39 (cleanup): {
++     bb30 (cleanup): {
+          StorageDead(_22);
+-         goto -> bb40;
++         goto -> bb31;
+      }
+  
+-     bb40 (cleanup): {
++     bb31 (cleanup): {
+          StorageDead(_21);
+-         goto -> bb49;
++         goto -> bb39;
+      }
+  
+-     bb41 (cleanup): {
+-         StorageDead(_15);
+-         goto -> bb42;
+-     }
+- 
+-     bb42 (cleanup): {
++     bb32 (cleanup): {
+          StorageDead(_13);
+          StorageDead(_10);
+          StorageDead(_14);
+-         goto -> bb44;
++         goto -> bb34;
+      }
+  
+-     bb43 (cleanup): {
++     bb33 (cleanup): {
+          StorageDead(_11);
+          StorageDead(_10);
+-         goto -> bb44;
++         goto -> bb34;
+      }
+  
+-     bb44 (cleanup): {
++     bb34 (cleanup): {
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_8);
+-         drop(_6) -> [return: bb45, unwind terminate(cleanup)];
++         drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb35, unwind terminate(cleanup)];
+      }
+  
+-     bb45 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb48;
++     bb35 (cleanup): {
++         nop;
++         goto -> bb38;
+      }
+  
+-     bb46 (cleanup): {
+-         goto -> bb47;
++     bb36 (cleanup): {
++         goto -> bb37;
+      }
+  
+-     bb47 (cleanup): {
++     bb37 (cleanup): {
+          StorageDead(_5);
+-         goto -> bb48;
++         goto -> bb38;
+      }
+  
+-     bb48 (cleanup): {
++     bb38 (cleanup): {
+          StorageDead(_4);
+          StorageDead(_3);
+-         goto -> bb49;
++         goto -> bb39;
+      }
+  
+-     bb49 (cleanup): {
+-         drop(_1) -> [return: bb50, unwind terminate(cleanup)];
++     bb39 (cleanup): {
++         goto -> bb40;
+      }
+  
+-     bb50 (cleanup): {
++     bb40 (cleanup): {
++         goto -> bb42;
++     }
++ 
++     bb41: {
++         goto -> bb24;
++     }
++ 
++     bb42 (cleanup): {
++         discriminant((*_39)) = 2;
+          resume;
+      }
+  
+-     bb51 (cleanup): {
+-         StorageDead(_23);
+-         goto -> bb52;
++     bb43: {
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_19);
++         StorageLive(_20);
++         _19 = move _2;
++         goto -> bb10;
+      }
+  
+-     bb52 (cleanup): {
+-         StorageDead(_21);
+-         goto -> bb55;
++     bb44: {
++         StorageLive(_21);
++         StorageLive(_35);
++         StorageLive(_36);
++         _35 = move _2;
++         goto -> bb21;
+      }
+  
+-     bb53 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb54;
++     bb45: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb45, unwind continue];
+      }
+  
+-     bb54 (cleanup): {
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         goto -> bb55;
++     bb46: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb46, unwind continue];
+      }
+  
+-     bb55 (cleanup): {
+-         drop(_1) -> [return: bb50, unwind terminate(cleanup)];
++     bb47: {
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_5);
++         _5 = a() -> [return: bb1, unwind: bb37];
+      }
+  }
+  
diff --git a/tests/mir-opt/coroutine/async_await.rs b/tests/mir-opt/coroutine/async_await.rs
new file mode 100644
index 0000000..4e506ed
--- /dev/null
+++ b/tests/mir-opt/coroutine/async_await.rs
@@ -0,0 +1,29 @@
+// This test makes sure that the coroutine MIR pass eliminates all calls to
+// `get_context`, and that the MIR argument type for an async fn and all locals
+// related to `yield` are `&mut Context`, and its return type is `Poll`.
+
+//@ edition:2018
+//@ compile-flags: -Zmir-opt-level=0
+//@ needs-unwind
+
+#![crate_type = "lib"]
+
+// EMIT_MIR async_await.a-{closure#0}.StateTransform.diff
+async fn a() {
+    // CHECK-LABEL: fn a::{closure#0}(
+    // CHECK-SAME: _1: Pin<&mut {async fn body of a()}>
+    // CHECK-SAME: _2: &mut Context<'_>
+    // CHECK-SAME: -> Poll<()>
+    // CHECK-NOT: get_context
+}
+
+// EMIT_MIR async_await.b-{closure#0}.StateTransform.diff
+pub async fn b() {
+    // CHECK-LABEL: fn b::{closure#0}(
+    // CHECK-SAME: _1: Pin<&mut {async fn body of b()}>
+    // CHECK-SAME: _2: &mut Context<'_>
+    // CHECK-SAME: -> Poll<()>
+    // CHECK-NOT: get_context
+    a().await;
+    a().await
+}
diff --git "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0430\175.built.after.mir"
diff --git "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs
similarity index 100%
rename from tests/mir-opt/async_closure_fake_read_for_by_move.rs
rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
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/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir" "b/tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
similarity index 100%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
rename to "tests/mir-opt/coroutine/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/coroutine/async_closure_shims.rs
similarity index 100%
rename from tests/mir-opt/async_closure_shims.rs
rename to tests/mir-opt/coroutine/async_closure_shims.rs
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.MentionedItems.after.mir"
new file mode 100644
index 0000000..d0a63ff
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.MentionedItems.after.mir"
@@ -0,0 +1,377 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncEnum>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut AsyncEnum;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: std::future::ResumeTy;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: std::future::ResumeTy;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: std::pin::Pin<&mut AsyncInt>;
+    let mut _13: &mut AsyncInt;
+    let mut _14: impl std::future::Future<Output = ()>;
+    let mut _15: std::future::ResumeTy;
+    let mut _16: std::task::Poll<()>;
+    let mut _17: isize;
+    let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: std::future::ResumeTy;
+    let mut _21: &mut impl std::future::Future<Output = ()>;
+    let mut _22: std::future::ResumeTy;
+    let mut _23: std::task::Poll<()>;
+    let mut _24: isize;
+    let mut _25: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _26: &mut std::task::Context<'_>;
+    let mut _27: std::future::ResumeTy;
+    let mut _28: &mut impl std::future::Future<Output = ()>;
+    let mut _29: std::pin::Pin<&mut AsyncInt>;
+    let mut _30: &mut AsyncInt;
+    let mut _31: isize;
+    let mut _32: isize;
+    let mut _33: isize;
+    let mut _34: impl std::future::Future<Output = ()>;
+    let mut _35: std::future::ResumeTy;
+    let mut _36: std::task::Poll<()>;
+    let mut _37: isize;
+    let mut _38: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _39: &mut std::task::Context<'_>;
+    let mut _40: std::future::ResumeTy;
+    let mut _41: &mut impl std::future::Future<Output = ()>;
+    let mut _42: std::future::ResumeTy;
+    let mut _43: std::task::Poll<()>;
+    let mut _44: isize;
+    let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _46: &mut std::task::Context<'_>;
+    let mut _47: std::future::ResumeTy;
+    let mut _48: &mut impl std::future::Future<Output = ()>;
+    let mut _49: std::pin::Pin<&mut AsyncEnum>;
+    let mut _50: &mut AsyncEnum;
+
+    bb0: {
+        _3 = move (_1.0: &mut AsyncEnum);
+        goto -> bb65;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4 (cleanup): {
+        drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb5 (cleanup): {
+        drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb6: {
+        StorageDead(_4);
+        goto -> bb1;
+    }
+
+    bb7 (cleanup): {
+        StorageDead(_4);
+        goto -> bb2;
+    }
+
+    bb8: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7];
+    }
+
+    bb9: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb8;
+    }
+
+    bb10: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb16;
+    }
+
+    bb11: {
+        StorageLive(_5);
+        _5 = yield(const ()) -> [resume: bb9, drop: bb10];
+    }
+
+    bb12: {
+        unreachable;
+    }
+
+    bb13: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12];
+    }
+
+    bb14: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7];
+    }
+
+    bb15: {
+        _10 = move _2;
+        _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7];
+    }
+
+    bb16: {
+        _11 = &mut _4;
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb15, unwind: bb7];
+    }
+
+    bb17: {
+        StorageLive(_4);
+        _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7];
+    }
+
+    bb18: {
+        _13 = &mut (((*_3) as A).0: AsyncInt);
+        _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2];
+    }
+
+    bb19: {
+        StorageDead(_14);
+        goto -> bb3;
+    }
+
+    bb20: {
+        StorageDead(_14);
+        goto -> bb1;
+    }
+
+    bb21 (cleanup): {
+        StorageDead(_14);
+        goto -> bb2;
+    }
+
+    bb22: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb22, unwind: bb21];
+    }
+
+    bb23: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb22;
+    }
+
+    bb24: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb29;
+    }
+
+    bb25: {
+        StorageLive(_15);
+        _15 = yield(const ()) -> [resume: bb23, drop: bb24];
+    }
+
+    bb26: {
+        _17 = discriminant(_16);
+        switchInt(move _17) -> [0: bb20, 1: bb25, otherwise: bb12];
+    }
+
+    bb27: {
+        _16 = <impl Future<Output = ()> as Future>::poll(move _18, move _19) -> [return: bb26, unwind: bb21];
+    }
+
+    bb28: {
+        _20 = move _2;
+        _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb27, unwind: bb21];
+    }
+
+    bb29: {
+        _21 = &mut _14;
+        _18 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _21) -> [return: bb28, unwind: bb21];
+    }
+
+    bb30: {
+        _2 = move _22;
+        StorageDead(_22);
+        goto -> bb36;
+    }
+
+    bb31: {
+        _2 = move _22;
+        StorageDead(_22);
+        goto -> bb29;
+    }
+
+    bb32: {
+        StorageLive(_22);
+        _22 = yield(const ()) -> [resume: bb30, drop: bb31];
+    }
+
+    bb33: {
+        _24 = discriminant(_23);
+        switchInt(move _24) -> [0: bb19, 1: bb32, otherwise: bb12];
+    }
+
+    bb34: {
+        _23 = <impl Future<Output = ()> as Future>::poll(move _25, move _26) -> [return: bb33, unwind: bb21];
+    }
+
+    bb35: {
+        _27 = move _2;
+        _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb34, unwind: bb21];
+    }
+
+    bb36: {
+        _28 = &mut _14;
+        _25 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _28) -> [return: bb35, unwind: bb21];
+    }
+
+    bb37: {
+        StorageLive(_14);
+        _14 = async_drop_in_place::<AsyncInt>(copy (_29.0: &mut AsyncInt)) -> [return: bb36, unwind: bb21];
+    }
+
+    bb38: {
+        _30 = &mut (((*_3) as A).0: AsyncInt);
+        _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb37, unwind: bb2];
+    }
+
+    bb39 (cleanup): {
+        drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb40 (cleanup): {
+        drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb41: {
+        drop((((*_3) as B).0: SyncInt)) -> [return: bb1, unwind: bb2];
+    }
+
+    bb42: {
+        drop((((*_3) as B).0: SyncInt)) -> [return: bb3, unwind: bb2];
+    }
+
+    bb43: {
+        _31 = discriminant((*_3));
+        switchInt(move _31) -> [0: bb38, otherwise: bb42];
+    }
+
+    bb44 (cleanup): {
+        _32 = discriminant((*_3));
+        switchInt(move _32) -> [0: bb4, otherwise: bb39];
+    }
+
+    bb45: {
+        _33 = discriminant((*_3));
+        switchInt(move _33) -> [0: bb18, otherwise: bb41];
+    }
+
+    bb46: {
+        StorageDead(_34);
+        goto -> bb43;
+    }
+
+    bb47: {
+        StorageDead(_34);
+        goto -> bb45;
+    }
+
+    bb48 (cleanup): {
+        StorageDead(_34);
+        goto -> bb44;
+    }
+
+    bb49: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb49, unwind: bb48];
+    }
+
+    bb50: {
+        _2 = move _35;
+        StorageDead(_35);
+        goto -> bb49;
+    }
+
+    bb51: {
+        _2 = move _35;
+        StorageDead(_35);
+        goto -> bb56;
+    }
+
+    bb52: {
+        StorageLive(_35);
+        _35 = yield(const ()) -> [resume: bb50, drop: bb51];
+    }
+
+    bb53: {
+        _37 = discriminant(_36);
+        switchInt(move _37) -> [0: bb47, 1: bb52, otherwise: bb12];
+    }
+
+    bb54: {
+        _36 = <impl Future<Output = ()> as Future>::poll(move _38, move _39) -> [return: bb53, unwind: bb48];
+    }
+
+    bb55: {
+        _40 = move _2;
+        _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb54, unwind: bb48];
+    }
+
+    bb56: {
+        _41 = &mut _34;
+        _38 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _41) -> [return: bb55, unwind: bb48];
+    }
+
+    bb57: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb63;
+    }
+
+    bb58: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb56;
+    }
+
+    bb59: {
+        StorageLive(_42);
+        _42 = yield(const ()) -> [resume: bb57, drop: bb58];
+    }
+
+    bb60: {
+        _44 = discriminant(_43);
+        switchInt(move _44) -> [0: bb46, 1: bb59, otherwise: bb12];
+    }
+
+    bb61: {
+        _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb60, unwind: bb48];
+    }
+
+    bb62: {
+        _47 = move _2;
+        _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb61, unwind: bb48];
+    }
+
+    bb63: {
+        _48 = &mut _34;
+        _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb62, unwind: bb48];
+    }
+
+    bb64: {
+        StorageLive(_34);
+        _34 = <AsyncEnum as AsyncDrop>::drop(move _49) -> [return: bb63, unwind: bb48];
+    }
+
+    bb65: {
+        _50 = &mut (*_3);
+        _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb64, unwind: bb44];
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.StateTransform.diff"
new file mode 100644
index 0000000..aedc5a0
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncEnum.StateTransform.diff"
@@ -0,0 +1,507 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncEnum>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<AsyncEnum>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: &mut AsyncEnum;
++         field _s1: impl Future<Output = ()>;
++         field _s2: impl Future<Output = ()>;
++         field _s3: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1],
++             Suspend1 (4): [_s2],
++             Suspend2 (5): [_s2],
++             Suspend3 (6): [_s0, _s3],
++             Suspend4 (7): [_s0, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3)}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut AsyncEnum;
+      let mut _4: impl std::future::Future<Output = ()>;
+-     let mut _5: std::future::ResumeTy;
++     let mut _5: &mut std::task::Context<'_>;
+      let mut _6: std::task::Poll<()>;
+      let mut _7: isize;
+      let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _9: &mut std::task::Context<'_>;
+-     let mut _10: std::future::ResumeTy;
++     let mut _10: &mut std::task::Context<'_>;
+      let mut _11: &mut impl std::future::Future<Output = ()>;
+      let mut _12: std::pin::Pin<&mut AsyncInt>;
+      let mut _13: &mut AsyncInt;
+      let mut _14: impl std::future::Future<Output = ()>;
+-     let mut _15: std::future::ResumeTy;
++     let mut _15: &mut std::task::Context<'_>;
+      let mut _16: std::task::Poll<()>;
+      let mut _17: isize;
+      let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _19: &mut std::task::Context<'_>;
+-     let mut _20: std::future::ResumeTy;
++     let mut _20: &mut std::task::Context<'_>;
+      let mut _21: &mut impl std::future::Future<Output = ()>;
+-     let mut _22: std::future::ResumeTy;
++     let mut _22: &mut std::task::Context<'_>;
+      let mut _23: std::task::Poll<()>;
+      let mut _24: isize;
+      let mut _25: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _26: &mut std::task::Context<'_>;
+-     let mut _27: std::future::ResumeTy;
++     let mut _27: &mut std::task::Context<'_>;
+      let mut _28: &mut impl std::future::Future<Output = ()>;
+      let mut _29: std::pin::Pin<&mut AsyncInt>;
+      let mut _30: &mut AsyncInt;
+      let mut _31: isize;
+      let mut _32: isize;
+      let mut _33: isize;
+      let mut _34: impl std::future::Future<Output = ()>;
+-     let mut _35: std::future::ResumeTy;
++     let mut _35: &mut std::task::Context<'_>;
+      let mut _36: std::task::Poll<()>;
+      let mut _37: isize;
+      let mut _38: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _39: &mut std::task::Context<'_>;
+-     let mut _40: std::future::ResumeTy;
++     let mut _40: &mut std::task::Context<'_>;
+      let mut _41: &mut impl std::future::Future<Output = ()>;
+-     let mut _42: std::future::ResumeTy;
++     let mut _42: &mut std::task::Context<'_>;
+      let mut _43: std::task::Poll<()>;
+      let mut _44: isize;
+      let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _46: &mut std::task::Context<'_>;
+-     let mut _47: std::future::ResumeTy;
++     let mut _47: &mut std::task::Context<'_>;
+      let mut _48: &mut impl std::future::Future<Output = ()>;
+      let mut _49: std::pin::Pin<&mut AsyncEnum>;
+      let mut _50: &mut AsyncEnum;
++     let mut _51: ();
++     let mut _52: u32;
++     let mut _53: &mut {async fn body of std::future::async_drop_in_place<AsyncEnum>()};
++     let mut _54: &mut AsyncEnum;
++     let mut _55: &mut AsyncEnum;
++     let mut _56: &mut AsyncEnum;
++     let mut _57: &mut AsyncEnum;
++     let mut _58: &mut AsyncEnum;
++     let mut _59: &mut AsyncEnum;
++     let mut _60: &mut AsyncEnum;
+  
+      bb0: {
+-         _3 = move (_1.0: &mut AsyncEnum);
+-         _50 = &mut (*_3);
+-         _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb59, unwind: bb40];
++         _53 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<AsyncEnum>()});
++         _52 = discriminant((*_53));
++         switchInt(move _52) -> [0: bb42, 1: bb41, 2: bb40, 3: bb35, 4: bb36, 5: bb37, 6: bb38, 7: bb39, otherwise: bb7];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _51);
++         discriminant((*_53)) = 1;
+          return;
+      }
+  
+      bb2 (cleanup): {
+-         resume;
++         goto -> bb34;
+      }
+  
+      bb3 (cleanup): {
+-         drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
++         _54 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         drop((((*_54) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+      }
+  
+-     bb4: {
+-         StorageDead(_4);
+-         goto -> bb1;
++     bb4 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb5 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb2;
++     bb5: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb5, unwind: bb4];
+      }
+  
+      bb6: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5];
++         _2 = move _5;
++         StorageDead(_5);
++         goto -> bb5;
+      }
+  
+      bb7: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb6;
++         unreachable;
+      }
+  
+      bb8: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb14;
++         nop;
++         goto -> bb1;
+      }
+  
+-     bb9: {
+-         StorageLive(_5);
+-         _5 = yield(const ()) -> [resume: bb7, drop: bb8];
++     bb9 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+      bb10: {
+-         unreachable;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb10, unwind: bb9];
+      }
+  
+      bb11: {
+-         _7 = discriminant(_6);
+-         switchInt(move _7) -> [0: bb4, 1: bb9, otherwise: bb10];
++         _2 = move _15;
++         StorageDead(_15);
++         goto -> bb10;
+      }
+  
+      bb12: {
+-         _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb11, unwind: bb5];
++         _2 = move _22;
++         StorageDead(_22);
++         goto -> bb17;
+      }
+  
+      bb13: {
+-         _10 = move _2;
+-         _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb12, unwind: bb5];
++         StorageLive(_22);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_22);
++         discriminant((*_53)) = 5;
++         return;
+      }
+  
+      bb14: {
+-         _11 = &mut _4;
+-         _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb13, unwind: bb5];
++         _24 = discriminant(_23);
++         switchInt(move _24) -> [0: bb8, 1: bb13, otherwise: bb7];
+      }
+  
+      bb15: {
+-         StorageLive(_4);
+-         _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb14, unwind: bb5];
++         _23 = <impl Future<Output = ()> as Future>::poll(move _25, move _26) -> [return: bb14, unwind: bb9];
+      }
+  
+      bb16: {
+-         _13 = &mut (((*_3) as A).0: AsyncInt);
+-         _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb15, unwind: bb2];
++         _27 = move _2;
++         _26 = move _27;
++         goto -> bb15;
+      }
+  
+      bb17: {
+-         StorageDead(_14);
+-         goto -> bb1;
++         _28 = &mut (((*_53) as variant#5).0: impl std::future::Future<Output = ()>);
++         _25 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _28) -> [return: bb16, unwind: bb9];
+      }
+  
+      bb18: {
+-         StorageDead(_14);
+-         goto -> bb1;
++         nop;
++         (((*_53) as variant#5).0: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_29.0: &mut AsyncInt)) -> [return: bb17, unwind: bb9];
+      }
+  
+-     bb19 (cleanup): {
+-         StorageDead(_14);
+-         goto -> bb2;
++     bb19: {
++         _55 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         _30 = &mut (((*_55) as A).0: AsyncInt);
++         _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb18, unwind: bb2];
+      }
+  
+-     bb20: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb20, unwind: bb19];
++     bb20 (cleanup): {
++         _56 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         drop((((*_56) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+      }
+  
+      bb21: {
+-         _2 = move _15;
+-         StorageDead(_15);
+-         goto -> bb20;
++         _57 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         drop((((*_57) as B).0: SyncInt)) -> [return: bb1, unwind: bb2];
+      }
+  
+-     bb22: {
+-         _2 = move _15;
+-         StorageDead(_15);
+-         goto -> bb27;
++     bb22 (cleanup): {
++         _58 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         _32 = discriminant((*_58));
++         switchInt(move _32) -> [0: bb3, otherwise: bb20];
+      }
+  
+      bb23: {
+-         StorageLive(_15);
+-         _15 = yield(const ()) -> [resume: bb21, drop: bb22];
++         nop;
++         _59 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         _31 = discriminant((*_59));
++         switchInt(move _31) -> [0: bb19, otherwise: bb21];
+      }
+  
+-     bb24: {
+-         _17 = discriminant(_16);
+-         switchInt(move _17) -> [0: bb18, 1: bb23, otherwise: bb10];
++     bb24 (cleanup): {
++         nop;
++         goto -> bb22;
+      }
+  
+      bb25: {
+-         _16 = <impl Future<Output = ()> as Future>::poll(move _18, move _19) -> [return: bb24, unwind: bb19];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24];
+      }
+  
+      bb26: {
+-         _20 = move _2;
+-         _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb25, unwind: bb19];
++         _2 = move _35;
++         StorageDead(_35);
++         goto -> bb25;
+      }
+  
+      bb27: {
+-         _21 = &mut _14;
+-         _18 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _21) -> [return: bb26, unwind: bb19];
++         _2 = move _42;
++         StorageDead(_42);
++         goto -> bb32;
+      }
+  
+      bb28: {
+-         _2 = move _22;
+-         StorageDead(_22);
+-         goto -> bb34;
++         StorageLive(_42);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_42);
++         discriminant((*_53)) = 7;
++         return;
+      }
+  
+      bb29: {
+-         _2 = move _22;
+-         StorageDead(_22);
+-         goto -> bb27;
++         _44 = discriminant(_43);
++         switchInt(move _44) -> [0: bb23, 1: bb28, otherwise: bb7];
+      }
+  
+      bb30: {
+-         StorageLive(_22);
+-         _22 = yield(const ()) -> [resume: bb28, drop: bb29];
++         _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb29, unwind: bb24];
+      }
+  
+      bb31: {
+-         _24 = discriminant(_23);
+-         switchInt(move _24) -> [0: bb17, 1: bb30, otherwise: bb10];
++         _47 = move _2;
++         _46 = move _47;
++         goto -> bb30;
+      }
+  
+      bb32: {
+-         _23 = <impl Future<Output = ()> as Future>::poll(move _25, move _26) -> [return: bb31, unwind: bb19];
++         _48 = &mut (((*_53) as variant#7).1: impl std::future::Future<Output = ()>);
++         _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb31, unwind: bb24];
+      }
+  
+      bb33: {
+-         _27 = move _2;
+-         _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb32, unwind: bb19];
++         nop;
++         (((*_53) as variant#7).1: impl std::future::Future<Output = ()>) = <AsyncEnum as AsyncDrop>::drop(move _49) -> [return: bb32, unwind: bb24];
+      }
+  
+-     bb34: {
+-         _28 = &mut _14;
+-         _25 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _28) -> [return: bb33, unwind: bb19];
++     bb34 (cleanup): {
++         discriminant((*_53)) = 2;
++         resume;
+      }
+  
+      bb35: {
+-         StorageLive(_14);
+-         _14 = async_drop_in_place::<AsyncInt>(copy (_29.0: &mut AsyncInt)) -> [return: bb34, unwind: bb19];
++         StorageLive(_5);
++         _5 = move _2;
++         goto -> bb6;
+      }
+  
+      bb36: {
+-         _30 = &mut (((*_3) as A).0: AsyncInt);
+-         _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb35, unwind: bb2];
++         StorageLive(_15);
++         _15 = move _2;
++         goto -> bb11;
+      }
+  
+-     bb37 (cleanup): {
+-         drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)];
++     bb37: {
++         StorageLive(_22);
++         _22 = move _2;
++         goto -> bb12;
+      }
+  
+      bb38: {
+-         drop((((*_3) as B).0: SyncInt)) -> [return: bb1, unwind: bb2];
++         StorageLive(_35);
++         _35 = move _2;
++         goto -> bb26;
+      }
+  
+      bb39: {
+-         drop((((*_3) as B).0: SyncInt)) -> [return: bb1, unwind: bb2];
++         StorageLive(_42);
++         _42 = move _2;
++         goto -> bb27;
+      }
+  
+-     bb40 (cleanup): {
+-         _32 = discriminant((*_3));
+-         switchInt(move _32) -> [0: bb3, otherwise: bb37];
++     bb40: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb40, unwind continue];
+      }
+  
+      bb41: {
+-         StorageDead(_34);
+-         _31 = discriminant((*_3));
+-         switchInt(move _31) -> [0: bb36, otherwise: bb39];
++         _0 = Poll::<()>::Ready(const ());
++         return;
+      }
+  
+      bb42: {
+-         StorageDead(_34);
+-         _33 = discriminant((*_3));
+-         switchInt(move _33) -> [0: bb16, otherwise: bb38];
+-     }
+- 
+-     bb43 (cleanup): {
+-         StorageDead(_34);
+-         goto -> bb40;
+-     }
+- 
+-     bb44: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb44, unwind: bb43];
+-     }
+- 
+-     bb45: {
+-         _2 = move _35;
+-         StorageDead(_35);
+-         goto -> bb44;
+-     }
+- 
+-     bb46: {
+-         _2 = move _35;
+-         StorageDead(_35);
+-         goto -> bb51;
+-     }
+- 
+-     bb47: {
+-         StorageLive(_35);
+-         _35 = yield(const ()) -> [resume: bb45, drop: bb46];
+-     }
+- 
+-     bb48: {
+-         _37 = discriminant(_36);
+-         switchInt(move _37) -> [0: bb42, 1: bb47, otherwise: bb10];
+-     }
+- 
+-     bb49: {
+-         _36 = <impl Future<Output = ()> as Future>::poll(move _38, move _39) -> [return: bb48, unwind: bb43];
+-     }
+- 
+-     bb50: {
+-         _40 = move _2;
+-         _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb49, unwind: bb43];
+-     }
+- 
+-     bb51: {
+-         _41 = &mut _34;
+-         _38 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _41) -> [return: bb50, unwind: bb43];
+-     }
+- 
+-     bb52: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb58;
+-     }
+- 
+-     bb53: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb51;
+-     }
+- 
+-     bb54: {
+-         StorageLive(_42);
+-         _42 = yield(const ()) -> [resume: bb52, drop: bb53];
+-     }
+- 
+-     bb55: {
+-         _44 = discriminant(_43);
+-         switchInt(move _44) -> [0: bb41, 1: bb54, otherwise: bb10];
+-     }
+- 
+-     bb56: {
+-         _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb55, unwind: bb43];
+-     }
+- 
+-     bb57: {
+-         _47 = move _2;
+-         _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb56, unwind: bb43];
+-     }
+- 
+-     bb58: {
+-         _48 = &mut _34;
+-         _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb57, unwind: bb43];
+-     }
+- 
+-     bb59: {
+-         StorageLive(_34);
+-         _34 = <AsyncEnum as AsyncDrop>::drop(move _49) -> [return: bb58, unwind: bb43];
++         (((*_53) as variant#7).0: &mut AsyncEnum) = move ((*_53).0: &mut AsyncEnum);
++         _60 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum);
++         _50 = &mut (*_60);
++         _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb33, unwind: bb22];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.MentionedItems.after.mir"
new file mode 100644
index 0000000..da6f0f8
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.MentionedItems.after.mir"
@@ -0,0 +1,147 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncInt>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut AsyncInt;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: std::future::ResumeTy;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: std::future::ResumeTy;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: std::future::ResumeTy;
+    let mut _13: std::task::Poll<()>;
+    let mut _14: isize;
+    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: std::future::ResumeTy;
+    let mut _18: &mut impl std::future::Future<Output = ()>;
+    let mut _19: std::pin::Pin<&mut AsyncInt>;
+    let mut _20: &mut AsyncInt;
+
+    bb0: {
+        _3 = move (_1.0: &mut AsyncInt);
+        goto -> bb24;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb5: {
+        StorageDead(_4);
+        goto -> bb1;
+    }
+
+    bb6 (cleanup): {
+        StorageDead(_4);
+        goto -> bb2;
+    }
+
+    bb7: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6];
+    }
+
+    bb8: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb7;
+    }
+
+    bb9: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb15;
+    }
+
+    bb10: {
+        StorageLive(_5);
+        _5 = yield(const ()) -> [resume: bb8, drop: bb9];
+    }
+
+    bb11: {
+        unreachable;
+    }
+
+    bb12: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11];
+    }
+
+    bb13: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6];
+    }
+
+    bb14: {
+        _10 = move _2;
+        _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6];
+    }
+
+    bb15: {
+        _11 = &mut _4;
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb14, unwind: bb6];
+    }
+
+    bb16: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb22;
+    }
+
+    bb17: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb15;
+    }
+
+    bb18: {
+        StorageLive(_12);
+        _12 = yield(const ()) -> [resume: bb16, drop: bb17];
+    }
+
+    bb19: {
+        _14 = discriminant(_13);
+        switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11];
+    }
+
+    bb20: {
+        _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6];
+    }
+
+    bb21: {
+        _17 = move _2;
+        _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6];
+    }
+
+    bb22: {
+        _18 = &mut _4;
+        _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb21, unwind: bb6];
+    }
+
+    bb23: {
+        StorageLive(_4);
+        _4 = <AsyncInt as AsyncDrop>::drop(move _19) -> [return: bb22, unwind: bb6];
+    }
+
+    bb24: {
+        _20 = &mut (*_3);
+        _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb23, unwind: bb2];
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.StateTransform.diff"
new file mode 100644
index 0000000..f384928
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncInt.StateTransform.diff"
@@ -0,0 +1,209 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncInt>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<AsyncInt>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++             Suspend1 (4): [_s0],
++         }
++         storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut AsyncInt;
+      let mut _4: impl std::future::Future<Output = ()>;
+-     let mut _5: std::future::ResumeTy;
++     let mut _5: &mut std::task::Context<'_>;
+      let mut _6: std::task::Poll<()>;
+      let mut _7: isize;
+      let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _9: &mut std::task::Context<'_>;
+-     let mut _10: std::future::ResumeTy;
++     let mut _10: &mut std::task::Context<'_>;
+      let mut _11: &mut impl std::future::Future<Output = ()>;
+-     let mut _12: std::future::ResumeTy;
++     let mut _12: &mut std::task::Context<'_>;
+      let mut _13: std::task::Poll<()>;
+      let mut _14: isize;
+      let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _16: &mut std::task::Context<'_>;
+-     let mut _17: std::future::ResumeTy;
++     let mut _17: &mut std::task::Context<'_>;
+      let mut _18: &mut impl std::future::Future<Output = ()>;
+      let mut _19: std::pin::Pin<&mut AsyncInt>;
+      let mut _20: &mut AsyncInt;
++     let mut _21: ();
++     let mut _22: u32;
++     let mut _23: &mut {async fn body of std::future::async_drop_in_place<AsyncInt>()};
+  
+      bb0: {
+-         _3 = move (_1.0: &mut AsyncInt);
+-         _20 = &mut (*_3);
+-         _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb22, unwind: bb2];
++         _23 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<AsyncInt>()});
++         _22 = discriminant((*_23));
++         switchInt(move _22) -> [0: bb20, 1: bb19, 2: bb18, 3: bb16, 4: bb17, otherwise: bb7];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _21);
++         discriminant((*_23)) = 1;
+          return;
+      }
+  
+      bb2 (cleanup): {
+-         resume;
++         goto -> bb15;
+      }
+  
+      bb3: {
+-         StorageDead(_4);
++         nop;
+          goto -> bb1;
+      }
+  
+-     bb4: {
+-         StorageDead(_4);
+-         goto -> bb1;
++     bb4 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb5 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb2;
++     bb5: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb5, unwind: bb4];
+      }
+  
+      bb6: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5];
++         _2 = move _5;
++         StorageDead(_5);
++         goto -> bb5;
+      }
+  
+      bb7: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb6;
++         unreachable;
+      }
+  
+      bb8: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb14;
++         _2 = move _12;
++         StorageDead(_12);
++         goto -> bb13;
+      }
+  
+      bb9: {
+-         StorageLive(_5);
+-         _5 = yield(const ()) -> [resume: bb7, drop: bb8];
++         StorageLive(_12);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_12);
++         discriminant((*_23)) = 4;
++         return;
+      }
+  
+      bb10: {
+-         unreachable;
++         _14 = discriminant(_13);
++         switchInt(move _14) -> [0: bb3, 1: bb9, otherwise: bb7];
+      }
+  
+      bb11: {
+-         _7 = discriminant(_6);
+-         switchInt(move _7) -> [0: bb4, 1: bb9, otherwise: bb10];
++         _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb10, unwind: bb4];
+      }
+  
+      bb12: {
+-         _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb11, unwind: bb5];
++         _17 = move _2;
++         _16 = move _17;
++         goto -> bb11;
+      }
+  
+      bb13: {
+-         _10 = move _2;
+-         _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb12, unwind: bb5];
++         _18 = &mut (((*_23) as variant#4).0: impl std::future::Future<Output = ()>);
++         _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb12, unwind: bb4];
+      }
+  
+      bb14: {
+-         _11 = &mut _4;
+-         _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb13, unwind: bb5];
++         nop;
++         (((*_23) as variant#4).0: impl std::future::Future<Output = ()>) = <AsyncInt as AsyncDrop>::drop(move _19) -> [return: bb13, unwind: bb4];
+      }
+  
+-     bb15: {
+-         _2 = move _12;
+-         StorageDead(_12);
+-         goto -> bb21;
++     bb15 (cleanup): {
++         discriminant((*_23)) = 2;
++         resume;
+      }
+  
+      bb16: {
+-         _2 = move _12;
+-         StorageDead(_12);
+-         goto -> bb14;
++         StorageLive(_5);
++         _5 = move _2;
++         goto -> bb6;
+      }
+  
+      bb17: {
+          StorageLive(_12);
+-         _12 = yield(const ()) -> [resume: bb15, drop: bb16];
++         _12 = move _2;
++         goto -> bb8;
+      }
+  
+      bb18: {
+-         _14 = discriminant(_13);
+-         switchInt(move _14) -> [0: bb3, 1: bb17, otherwise: bb10];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue];
+      }
+  
+      bb19: {
+-         _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb18, unwind: bb5];
++         _0 = Poll::<()>::Ready(const ());
++         return;
+      }
+  
+      bb20: {
+-         _17 = move _2;
+-         _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb19, unwind: bb5];
+-     }
+- 
+-     bb21: {
+-         _18 = &mut _4;
+-         _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb20, unwind: bb5];
+-     }
+- 
+-     bb22: {
+-         StorageLive(_4);
+-         _4 = <AsyncInt as AsyncDrop>::drop(move _19) -> [return: bb21, unwind: bb5];
++         _3 = move ((*_23).0: &mut AsyncInt);
++         _20 = &mut (*_3);
++         _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb14, unwind: bb2];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.MentionedItems.after.mir"
new file mode 100644
index 0000000..bfb1aed
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.MentionedItems.after.mir"
@@ -0,0 +1,147 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncReference<'_>>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut AsyncReference<'_>;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: std::future::ResumeTy;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: std::future::ResumeTy;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: std::future::ResumeTy;
+    let mut _13: std::task::Poll<()>;
+    let mut _14: isize;
+    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: std::future::ResumeTy;
+    let mut _18: &mut impl std::future::Future<Output = ()>;
+    let mut _19: std::pin::Pin<&mut AsyncReference<'_>>;
+    let mut _20: &mut AsyncReference<'_>;
+
+    bb0: {
+        _3 = move (_1.0: &mut AsyncReference<'_>);
+        goto -> bb24;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb5: {
+        StorageDead(_4);
+        goto -> bb1;
+    }
+
+    bb6 (cleanup): {
+        StorageDead(_4);
+        goto -> bb2;
+    }
+
+    bb7: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6];
+    }
+
+    bb8: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb7;
+    }
+
+    bb9: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb15;
+    }
+
+    bb10: {
+        StorageLive(_5);
+        _5 = yield(const ()) -> [resume: bb8, drop: bb9];
+    }
+
+    bb11: {
+        unreachable;
+    }
+
+    bb12: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11];
+    }
+
+    bb13: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6];
+    }
+
+    bb14: {
+        _10 = move _2;
+        _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6];
+    }
+
+    bb15: {
+        _11 = &mut _4;
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb14, unwind: bb6];
+    }
+
+    bb16: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb22;
+    }
+
+    bb17: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb15;
+    }
+
+    bb18: {
+        StorageLive(_12);
+        _12 = yield(const ()) -> [resume: bb16, drop: bb17];
+    }
+
+    bb19: {
+        _14 = discriminant(_13);
+        switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11];
+    }
+
+    bb20: {
+        _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6];
+    }
+
+    bb21: {
+        _17 = move _2;
+        _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6];
+    }
+
+    bb22: {
+        _18 = &mut _4;
+        _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb21, unwind: bb6];
+    }
+
+    bb23: {
+        StorageLive(_4);
+        _4 = <AsyncReference<'_> as AsyncDrop>::drop(move _19) -> [return: bb22, unwind: bb6];
+    }
+
+    bb24: {
+        _20 = &mut (*_3);
+        _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb23, unwind: bb2];
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.StateTransform.diff"
new file mode 100644
index 0000000..120028d
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncReference_\047__.StateTransform.diff"
@@ -0,0 +1,209 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncReference<'_>>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<AsyncReference<'_>>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++             Suspend1 (4): [_s0],
++         }
++         storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut AsyncReference<'_>;
+      let mut _4: impl std::future::Future<Output = ()>;
+-     let mut _5: std::future::ResumeTy;
++     let mut _5: &mut std::task::Context<'_>;
+      let mut _6: std::task::Poll<()>;
+      let mut _7: isize;
+      let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _9: &mut std::task::Context<'_>;
+-     let mut _10: std::future::ResumeTy;
++     let mut _10: &mut std::task::Context<'_>;
+      let mut _11: &mut impl std::future::Future<Output = ()>;
+-     let mut _12: std::future::ResumeTy;
++     let mut _12: &mut std::task::Context<'_>;
+      let mut _13: std::task::Poll<()>;
+      let mut _14: isize;
+      let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _16: &mut std::task::Context<'_>;
+-     let mut _17: std::future::ResumeTy;
++     let mut _17: &mut std::task::Context<'_>;
+      let mut _18: &mut impl std::future::Future<Output = ()>;
+      let mut _19: std::pin::Pin<&mut AsyncReference<'_>>;
+      let mut _20: &mut AsyncReference<'_>;
++     let mut _21: ();
++     let mut _22: u32;
++     let mut _23: &mut {async fn body of std::future::async_drop_in_place<AsyncReference<'_>>()};
+  
+      bb0: {
+-         _3 = move (_1.0: &mut AsyncReference<'_>);
+-         _20 = &mut (*_3);
+-         _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb22, unwind: bb2];
++         _23 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<AsyncReference<'_>>()});
++         _22 = discriminant((*_23));
++         switchInt(move _22) -> [0: bb20, 1: bb19, 2: bb18, 3: bb16, 4: bb17, otherwise: bb7];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _21);
++         discriminant((*_23)) = 1;
+          return;
+      }
+  
+      bb2 (cleanup): {
+-         resume;
++         goto -> bb15;
+      }
+  
+      bb3: {
+-         StorageDead(_4);
++         nop;
+          goto -> bb1;
+      }
+  
+-     bb4: {
+-         StorageDead(_4);
+-         goto -> bb1;
++     bb4 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb5 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb2;
++     bb5: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb5, unwind: bb4];
+      }
+  
+      bb6: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5];
++         _2 = move _5;
++         StorageDead(_5);
++         goto -> bb5;
+      }
+  
+      bb7: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb6;
++         unreachable;
+      }
+  
+      bb8: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb14;
++         _2 = move _12;
++         StorageDead(_12);
++         goto -> bb13;
+      }
+  
+      bb9: {
+-         StorageLive(_5);
+-         _5 = yield(const ()) -> [resume: bb7, drop: bb8];
++         StorageLive(_12);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_12);
++         discriminant((*_23)) = 4;
++         return;
+      }
+  
+      bb10: {
+-         unreachable;
++         _14 = discriminant(_13);
++         switchInt(move _14) -> [0: bb3, 1: bb9, otherwise: bb7];
+      }
+  
+      bb11: {
+-         _7 = discriminant(_6);
+-         switchInt(move _7) -> [0: bb4, 1: bb9, otherwise: bb10];
++         _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb10, unwind: bb4];
+      }
+  
+      bb12: {
+-         _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb11, unwind: bb5];
++         _17 = move _2;
++         _16 = move _17;
++         goto -> bb11;
+      }
+  
+      bb13: {
+-         _10 = move _2;
+-         _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb12, unwind: bb5];
++         _18 = &mut (((*_23) as variant#4).0: impl std::future::Future<Output = ()>);
++         _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb12, unwind: bb4];
+      }
+  
+      bb14: {
+-         _11 = &mut _4;
+-         _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb13, unwind: bb5];
++         nop;
++         (((*_23) as variant#4).0: impl std::future::Future<Output = ()>) = <AsyncReference<'_> as AsyncDrop>::drop(move _19) -> [return: bb13, unwind: bb4];
+      }
+  
+-     bb15: {
+-         _2 = move _12;
+-         StorageDead(_12);
+-         goto -> bb21;
++     bb15 (cleanup): {
++         discriminant((*_23)) = 2;
++         resume;
+      }
+  
+      bb16: {
+-         _2 = move _12;
+-         StorageDead(_12);
+-         goto -> bb14;
++         StorageLive(_5);
++         _5 = move _2;
++         goto -> bb6;
+      }
+  
+      bb17: {
+          StorageLive(_12);
+-         _12 = yield(const ()) -> [resume: bb15, drop: bb16];
++         _12 = move _2;
++         goto -> bb8;
+      }
+  
+      bb18: {
+-         _14 = discriminant(_13);
+-         switchInt(move _14) -> [0: bb3, 1: bb17, otherwise: bb10];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue];
+      }
+  
+      bb19: {
+-         _13 = <impl Future<Output = ()> as Future>::poll(move _15, move _16) -> [return: bb18, unwind: bb5];
++         _0 = Poll::<()>::Ready(const ());
++         return;
+      }
+  
+      bb20: {
+-         _17 = move _2;
+-         _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb19, unwind: bb5];
+-     }
+- 
+-     bb21: {
+-         _18 = &mut _4;
+-         _15 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _18) -> [return: bb20, unwind: bb5];
+-     }
+- 
+-     bb22: {
+-         StorageLive(_4);
+-         _4 = <AsyncReference<'_> as AsyncDrop>::drop(move _19) -> [return: bb21, unwind: bb5];
++         _3 = move ((*_23).0: &mut AsyncReference<'_>);
++         _20 = &mut (*_3);
++         _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb14, unwind: bb2];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.MentionedItems.after.mir"
new file mode 100644
index 0000000..3a42ae5
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.MentionedItems.after.mir"
@@ -0,0 +1,531 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncStruct>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut AsyncStruct;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: std::future::ResumeTy;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: std::future::ResumeTy;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: std::pin::Pin<&mut AsyncInt>;
+    let mut _13: &mut AsyncInt;
+    let mut _14: impl std::future::Future<Output = ()>;
+    let mut _15: std::future::ResumeTy;
+    let mut _16: std::task::Poll<()>;
+    let mut _17: isize;
+    let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: std::future::ResumeTy;
+    let mut _21: &mut impl std::future::Future<Output = ()>;
+    let mut _22: std::pin::Pin<&mut AsyncInt>;
+    let mut _23: &mut AsyncInt;
+    let mut _24: impl std::future::Future<Output = ()>;
+    let mut _25: std::future::ResumeTy;
+    let mut _26: std::task::Poll<()>;
+    let mut _27: isize;
+    let mut _28: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _29: &mut std::task::Context<'_>;
+    let mut _30: std::future::ResumeTy;
+    let mut _31: &mut impl std::future::Future<Output = ()>;
+    let mut _32: std::future::ResumeTy;
+    let mut _33: std::task::Poll<()>;
+    let mut _34: isize;
+    let mut _35: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _36: &mut std::task::Context<'_>;
+    let mut _37: std::future::ResumeTy;
+    let mut _38: &mut impl std::future::Future<Output = ()>;
+    let mut _39: std::pin::Pin<&mut AsyncInt>;
+    let mut _40: &mut AsyncInt;
+    let mut _41: impl std::future::Future<Output = ()>;
+    let mut _42: std::future::ResumeTy;
+    let mut _43: std::task::Poll<()>;
+    let mut _44: isize;
+    let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _46: &mut std::task::Context<'_>;
+    let mut _47: std::future::ResumeTy;
+    let mut _48: &mut impl std::future::Future<Output = ()>;
+    let mut _49: std::future::ResumeTy;
+    let mut _50: std::task::Poll<()>;
+    let mut _51: isize;
+    let mut _52: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _53: &mut std::task::Context<'_>;
+    let mut _54: std::future::ResumeTy;
+    let mut _55: &mut impl std::future::Future<Output = ()>;
+    let mut _56: std::pin::Pin<&mut AsyncInt>;
+    let mut _57: &mut AsyncInt;
+    let mut _58: impl std::future::Future<Output = ()>;
+    let mut _59: std::future::ResumeTy;
+    let mut _60: std::task::Poll<()>;
+    let mut _61: isize;
+    let mut _62: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _63: &mut std::task::Context<'_>;
+    let mut _64: std::future::ResumeTy;
+    let mut _65: &mut impl std::future::Future<Output = ()>;
+    let mut _66: std::future::ResumeTy;
+    let mut _67: std::task::Poll<()>;
+    let mut _68: isize;
+    let mut _69: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _70: &mut std::task::Context<'_>;
+    let mut _71: std::future::ResumeTy;
+    let mut _72: &mut impl std::future::Future<Output = ()>;
+    let mut _73: std::pin::Pin<&mut AsyncStruct>;
+    let mut _74: &mut AsyncStruct;
+
+    bb0: {
+        _3 = move (_1.0: &mut AsyncStruct);
+        goto -> bb90;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4 (cleanup): {
+        drop(((*_3).2: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb5 (cleanup): {
+        drop(((*_3).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)];
+    }
+
+    bb6: {
+        StorageDead(_4);
+        goto -> bb1;
+    }
+
+    bb7 (cleanup): {
+        StorageDead(_4);
+        goto -> bb2;
+    }
+
+    bb8: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7];
+    }
+
+    bb9: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb8;
+    }
+
+    bb10: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb16;
+    }
+
+    bb11: {
+        StorageLive(_5);
+        _5 = yield(const ()) -> [resume: bb9, drop: bb10];
+    }
+
+    bb12: {
+        unreachable;
+    }
+
+    bb13: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12];
+    }
+
+    bb14: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7];
+    }
+
+    bb15: {
+        _10 = move _2;
+        _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7];
+    }
+
+    bb16: {
+        _11 = &mut _4;
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb15, unwind: bb7];
+    }
+
+    bb17: {
+        StorageLive(_4);
+        _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7];
+    }
+
+    bb18: {
+        _13 = &mut ((*_3).2: AsyncInt);
+        _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2];
+    }
+
+    bb19: {
+        StorageDead(_14);
+        goto -> bb18;
+    }
+
+    bb20 (cleanup): {
+        StorageDead(_14);
+        goto -> bb4;
+    }
+
+    bb21: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb21, unwind: bb20];
+    }
+
+    bb22: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb21;
+    }
+
+    bb23: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb28;
+    }
+
+    bb24: {
+        StorageLive(_15);
+        _15 = yield(const ()) -> [resume: bb22, drop: bb23];
+    }
+
+    bb25: {
+        _17 = discriminant(_16);
+        switchInt(move _17) -> [0: bb19, 1: bb24, otherwise: bb12];
+    }
+
+    bb26: {
+        _16 = <impl Future<Output = ()> as Future>::poll(move _18, move _19) -> [return: bb25, unwind: bb20];
+    }
+
+    bb27: {
+        _20 = move _2;
+        _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb26, unwind: bb20];
+    }
+
+    bb28: {
+        _21 = &mut _14;
+        _18 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _21) -> [return: bb27, unwind: bb20];
+    }
+
+    bb29: {
+        StorageLive(_14);
+        _14 = async_drop_in_place::<AsyncInt>(copy (_22.0: &mut AsyncInt)) -> [return: bb28, unwind: bb20];
+    }
+
+    bb30: {
+        _23 = &mut ((*_3).1: AsyncInt);
+        _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb29, unwind: bb4];
+    }
+
+    bb31: {
+        StorageDead(_24);
+        goto -> bb3;
+    }
+
+    bb32: {
+        StorageDead(_24);
+        goto -> bb1;
+    }
+
+    bb33 (cleanup): {
+        StorageDead(_24);
+        goto -> bb2;
+    }
+
+    bb34: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb34, unwind: bb33];
+    }
+
+    bb35: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb34;
+    }
+
+    bb36: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb41;
+    }
+
+    bb37: {
+        StorageLive(_25);
+        _25 = yield(const ()) -> [resume: bb35, drop: bb36];
+    }
+
+    bb38: {
+        _27 = discriminant(_26);
+        switchInt(move _27) -> [0: bb32, 1: bb37, otherwise: bb12];
+    }
+
+    bb39: {
+        _26 = <impl Future<Output = ()> as Future>::poll(move _28, move _29) -> [return: bb38, unwind: bb33];
+    }
+
+    bb40: {
+        _30 = move _2;
+        _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb39, unwind: bb33];
+    }
+
+    bb41: {
+        _31 = &mut _24;
+        _28 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _31) -> [return: bb40, unwind: bb33];
+    }
+
+    bb42: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb48;
+    }
+
+    bb43: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb41;
+    }
+
+    bb44: {
+        StorageLive(_32);
+        _32 = yield(const ()) -> [resume: bb42, drop: bb43];
+    }
+
+    bb45: {
+        _34 = discriminant(_33);
+        switchInt(move _34) -> [0: bb31, 1: bb44, otherwise: bb12];
+    }
+
+    bb46: {
+        _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb45, unwind: bb33];
+    }
+
+    bb47: {
+        _37 = move _2;
+        _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb46, unwind: bb33];
+    }
+
+    bb48: {
+        _38 = &mut _24;
+        _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb47, unwind: bb33];
+    }
+
+    bb49: {
+        StorageLive(_24);
+        _24 = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb48, unwind: bb33];
+    }
+
+    bb50: {
+        _40 = &mut ((*_3).2: AsyncInt);
+        _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb49, unwind: bb2];
+    }
+
+    bb51: {
+        StorageDead(_41);
+        goto -> bb50;
+    }
+
+    bb52: {
+        StorageDead(_41);
+        goto -> bb18;
+    }
+
+    bb53 (cleanup): {
+        StorageDead(_41);
+        goto -> bb4;
+    }
+
+    bb54: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb54, unwind: bb53];
+    }
+
+    bb55: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb54;
+    }
+
+    bb56: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb61;
+    }
+
+    bb57: {
+        StorageLive(_42);
+        _42 = yield(const ()) -> [resume: bb55, drop: bb56];
+    }
+
+    bb58: {
+        _44 = discriminant(_43);
+        switchInt(move _44) -> [0: bb52, 1: bb57, otherwise: bb12];
+    }
+
+    bb59: {
+        _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb58, unwind: bb53];
+    }
+
+    bb60: {
+        _47 = move _2;
+        _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb59, unwind: bb53];
+    }
+
+    bb61: {
+        _48 = &mut _41;
+        _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb60, unwind: bb53];
+    }
+
+    bb62: {
+        _2 = move _49;
+        StorageDead(_49);
+        goto -> bb68;
+    }
+
+    bb63: {
+        _2 = move _49;
+        StorageDead(_49);
+        goto -> bb61;
+    }
+
+    bb64: {
+        StorageLive(_49);
+        _49 = yield(const ()) -> [resume: bb62, drop: bb63];
+    }
+
+    bb65: {
+        _51 = discriminant(_50);
+        switchInt(move _51) -> [0: bb51, 1: bb64, otherwise: bb12];
+    }
+
+    bb66: {
+        _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb65, unwind: bb53];
+    }
+
+    bb67: {
+        _54 = move _2;
+        _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb66, unwind: bb53];
+    }
+
+    bb68: {
+        _55 = &mut _41;
+        _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb67, unwind: bb53];
+    }
+
+    bb69: {
+        StorageLive(_41);
+        _41 = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb68, unwind: bb53];
+    }
+
+    bb70: {
+        _57 = &mut ((*_3).1: AsyncInt);
+        _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb69, unwind: bb4];
+    }
+
+    bb71: {
+        StorageDead(_58);
+        goto -> bb70;
+    }
+
+    bb72: {
+        StorageDead(_58);
+        goto -> bb30;
+    }
+
+    bb73 (cleanup): {
+        StorageDead(_58);
+        goto -> bb5;
+    }
+
+    bb74: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb74, unwind: bb73];
+    }
+
+    bb75: {
+        _2 = move _59;
+        StorageDead(_59);
+        goto -> bb74;
+    }
+
+    bb76: {
+        _2 = move _59;
+        StorageDead(_59);
+        goto -> bb81;
+    }
+
+    bb77: {
+        StorageLive(_59);
+        _59 = yield(const ()) -> [resume: bb75, drop: bb76];
+    }
+
+    bb78: {
+        _61 = discriminant(_60);
+        switchInt(move _61) -> [0: bb72, 1: bb77, otherwise: bb12];
+    }
+
+    bb79: {
+        _60 = <impl Future<Output = ()> as Future>::poll(move _62, move _63) -> [return: bb78, unwind: bb73];
+    }
+
+    bb80: {
+        _64 = move _2;
+        _63 = std::future::get_context::<'_, '_>(move _64) -> [return: bb79, unwind: bb73];
+    }
+
+    bb81: {
+        _65 = &mut _58;
+        _62 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _65) -> [return: bb80, unwind: bb73];
+    }
+
+    bb82: {
+        _2 = move _66;
+        StorageDead(_66);
+        goto -> bb88;
+    }
+
+    bb83: {
+        _2 = move _66;
+        StorageDead(_66);
+        goto -> bb81;
+    }
+
+    bb84: {
+        StorageLive(_66);
+        _66 = yield(const ()) -> [resume: bb82, drop: bb83];
+    }
+
+    bb85: {
+        _68 = discriminant(_67);
+        switchInt(move _68) -> [0: bb71, 1: bb84, otherwise: bb12];
+    }
+
+    bb86: {
+        _67 = <impl Future<Output = ()> as Future>::poll(move _69, move _70) -> [return: bb85, unwind: bb73];
+    }
+
+    bb87: {
+        _71 = move _2;
+        _70 = std::future::get_context::<'_, '_>(move _71) -> [return: bb86, unwind: bb73];
+    }
+
+    bb88: {
+        _72 = &mut _58;
+        _69 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _72) -> [return: bb87, unwind: bb73];
+    }
+
+    bb89: {
+        StorageLive(_58);
+        _58 = <AsyncStruct as AsyncDrop>::drop(move _73) -> [return: bb88, unwind: bb73];
+    }
+
+    bb90: {
+        _74 = &mut (*_3);
+        _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb89, unwind: bb5];
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.StateTransform.diff"
new file mode 100644
index 0000000..0de0be9
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.AsyncStruct.StateTransform.diff"
@@ -0,0 +1,709 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<AsyncStruct>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<AsyncStruct>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: &mut AsyncStruct;
++         field _s1: impl Future<Output = ()>;
++         field _s2: impl Future<Output = ()>;
++         field _s3: impl Future<Output = ()>;
++         field _s4: impl Future<Output = ()>;
++         field _s5: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1],
++             Suspend1 (4): [_s0, _s2],
++             Suspend2 (5): [_s3],
++             Suspend3 (6): [_s3],
++             Suspend4 (7): [_s0, _s4],
++             Suspend5 (8): [_s0, _s4],
++             Suspend6 (9): [_s0, _s5],
++             Suspend7 (10): [_s0, _s5],
++         }
++         storage_conflicts = BitMatrix(6x6) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3), (_s4, _s0), (_s4, _s4), (_s5, _s0), (_s5, _s5)}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut AsyncStruct;
+      let mut _4: impl std::future::Future<Output = ()>;
+-     let mut _5: std::future::ResumeTy;
++     let mut _5: &mut std::task::Context<'_>;
+      let mut _6: std::task::Poll<()>;
+      let mut _7: isize;
+      let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _9: &mut std::task::Context<'_>;
+-     let mut _10: std::future::ResumeTy;
++     let mut _10: &mut std::task::Context<'_>;
+      let mut _11: &mut impl std::future::Future<Output = ()>;
+      let mut _12: std::pin::Pin<&mut AsyncInt>;
+      let mut _13: &mut AsyncInt;
+      let mut _14: impl std::future::Future<Output = ()>;
+-     let mut _15: std::future::ResumeTy;
++     let mut _15: &mut std::task::Context<'_>;
+      let mut _16: std::task::Poll<()>;
+      let mut _17: isize;
+      let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _19: &mut std::task::Context<'_>;
+-     let mut _20: std::future::ResumeTy;
++     let mut _20: &mut std::task::Context<'_>;
+      let mut _21: &mut impl std::future::Future<Output = ()>;
+      let mut _22: std::pin::Pin<&mut AsyncInt>;
+      let mut _23: &mut AsyncInt;
+      let mut _24: impl std::future::Future<Output = ()>;
+-     let mut _25: std::future::ResumeTy;
++     let mut _25: &mut std::task::Context<'_>;
+      let mut _26: std::task::Poll<()>;
+      let mut _27: isize;
+      let mut _28: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _29: &mut std::task::Context<'_>;
+-     let mut _30: std::future::ResumeTy;
++     let mut _30: &mut std::task::Context<'_>;
+      let mut _31: &mut impl std::future::Future<Output = ()>;
+-     let mut _32: std::future::ResumeTy;
++     let mut _32: &mut std::task::Context<'_>;
+      let mut _33: std::task::Poll<()>;
+      let mut _34: isize;
+      let mut _35: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _36: &mut std::task::Context<'_>;
+-     let mut _37: std::future::ResumeTy;
++     let mut _37: &mut std::task::Context<'_>;
+      let mut _38: &mut impl std::future::Future<Output = ()>;
+      let mut _39: std::pin::Pin<&mut AsyncInt>;
+      let mut _40: &mut AsyncInt;
+      let mut _41: impl std::future::Future<Output = ()>;
+-     let mut _42: std::future::ResumeTy;
++     let mut _42: &mut std::task::Context<'_>;
+      let mut _43: std::task::Poll<()>;
+      let mut _44: isize;
+      let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _46: &mut std::task::Context<'_>;
+-     let mut _47: std::future::ResumeTy;
++     let mut _47: &mut std::task::Context<'_>;
+      let mut _48: &mut impl std::future::Future<Output = ()>;
+-     let mut _49: std::future::ResumeTy;
++     let mut _49: &mut std::task::Context<'_>;
+      let mut _50: std::task::Poll<()>;
+      let mut _51: isize;
+      let mut _52: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _53: &mut std::task::Context<'_>;
+-     let mut _54: std::future::ResumeTy;
++     let mut _54: &mut std::task::Context<'_>;
+      let mut _55: &mut impl std::future::Future<Output = ()>;
+      let mut _56: std::pin::Pin<&mut AsyncInt>;
+      let mut _57: &mut AsyncInt;
+      let mut _58: impl std::future::Future<Output = ()>;
+-     let mut _59: std::future::ResumeTy;
++     let mut _59: &mut std::task::Context<'_>;
+      let mut _60: std::task::Poll<()>;
+      let mut _61: isize;
+      let mut _62: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _63: &mut std::task::Context<'_>;
+-     let mut _64: std::future::ResumeTy;
++     let mut _64: &mut std::task::Context<'_>;
+      let mut _65: &mut impl std::future::Future<Output = ()>;
+-     let mut _66: std::future::ResumeTy;
++     let mut _66: &mut std::task::Context<'_>;
+      let mut _67: std::task::Poll<()>;
+      let mut _68: isize;
+      let mut _69: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _70: &mut std::task::Context<'_>;
+-     let mut _71: std::future::ResumeTy;
++     let mut _71: &mut std::task::Context<'_>;
+      let mut _72: &mut impl std::future::Future<Output = ()>;
+      let mut _73: std::pin::Pin<&mut AsyncStruct>;
+      let mut _74: &mut AsyncStruct;
++     let mut _75: ();
++     let mut _76: u32;
++     let mut _77: &mut {async fn body of std::future::async_drop_in_place<AsyncStruct>()};
++     let mut _78: &mut AsyncStruct;
++     let mut _79: &mut AsyncStruct;
++     let mut _80: &mut AsyncStruct;
++     let mut _81: &mut AsyncStruct;
++     let mut _82: &mut AsyncStruct;
+  
+      bb0: {
+-         _3 = move (_1.0: &mut AsyncStruct);
+-         _74 = &mut (*_3);
+-         _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb85, unwind: bb4];
++         _77 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<AsyncStruct>()});
++         _76 = discriminant((*_77));
++         switchInt(move _76) -> [0: bb56, 1: bb55, 2: bb54, 3: bb46, 4: bb47, 5: bb48, 6: bb49, 7: bb50, 8: bb51, 9: bb52, 10: bb53, otherwise: bb8];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _75);
++         discriminant((*_77)) = 1;
+          return;
+      }
+  
+      bb2 (cleanup): {
+-         resume;
++         goto -> bb45;
+      }
+  
+      bb3 (cleanup): {
+-         drop(((*_3).2: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
++         _78 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct);
++         drop(((*_78).2: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+      }
+  
+      bb4 (cleanup): {
+-         drop(((*_3).1: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)];
++         _79 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct);
++         drop(((*_79).1: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)];
+      }
+  
+-     bb5: {
+-         StorageDead(_4);
+-         goto -> bb1;
++     bb5 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb6 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb2;
++     bb6: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5];
+      }
+  
+      bb7: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6];
++         _2 = move _5;
++         StorageDead(_5);
++         goto -> bb6;
+      }
+  
+      bb8: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb7;
++         unreachable;
+      }
+  
+-     bb9: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb15;
++     bb9 (cleanup): {
++         nop;
++         goto -> bb3;
+      }
+  
+      bb10: {
+-         StorageLive(_5);
+-         _5 = yield(const ()) -> [resume: bb8, drop: bb9];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb10, unwind: bb9];
+      }
+  
+      bb11: {
+-         unreachable;
++         _2 = move _15;
++         StorageDead(_15);
++         goto -> bb10;
+      }
+  
+      bb12: {
+-         _7 = discriminant(_6);
+-         switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11];
++         nop;
++         goto -> bb1;
+      }
+  
+-     bb13: {
+-         _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6];
++     bb13 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+      bb14: {
+-         _10 = move _2;
+-         _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb14, unwind: bb13];
+      }
+  
+      bb15: {
+-         _11 = &mut _4;
+-         _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb14, unwind: bb6];
++         _2 = move _25;
++         StorageDead(_25);
++         goto -> bb14;
+      }
+  
+      bb16: {
+-         StorageLive(_4);
+-         _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb15, unwind: bb6];
++         _2 = move _32;
++         StorageDead(_32);
++         goto -> bb21;
+      }
+  
+      bb17: {
+-         _13 = &mut ((*_3).2: AsyncInt);
+-         _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb16, unwind: bb2];
++         StorageLive(_32);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_32);
++         discriminant((*_77)) = 6;
++         return;
+      }
+  
+      bb18: {
+-         StorageDead(_14);
+-         goto -> bb17;
++         _34 = discriminant(_33);
++         switchInt(move _34) -> [0: bb12, 1: bb17, otherwise: bb8];
+      }
+  
+-     bb19 (cleanup): {
+-         StorageDead(_14);
+-         goto -> bb3;
++     bb19: {
++         _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb18, unwind: bb13];
+      }
+  
+      bb20: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb20, unwind: bb19];
++         _37 = move _2;
++         _36 = move _37;
++         goto -> bb19;
+      }
+  
+      bb21: {
+-         _2 = move _15;
+-         StorageDead(_15);
+-         goto -> bb20;
++         _38 = &mut (((*_77) as variant#6).0: impl std::future::Future<Output = ()>);
++         _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb20, unwind: bb13];
+      }
+  
+      bb22: {
+-         _2 = move _15;
+-         StorageDead(_15);
+-         goto -> bb27;
++         nop;
++         (((*_77) as variant#6).0: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb21, unwind: bb13];
+      }
+  
+      bb23: {
+-         StorageLive(_15);
+-         _15 = yield(const ()) -> [resume: bb21, drop: bb22];
++         nop;
++         _80 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct);
++         _40 = &mut ((*_80).2: AsyncInt);
++         _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb22, unwind: bb2];
+      }
+  
+-     bb24: {
+-         _17 = discriminant(_16);
+-         switchInt(move _17) -> [0: bb18, 1: bb23, otherwise: bb11];
++     bb24 (cleanup): {
++         nop;
++         goto -> bb3;
+      }
+  
+      bb25: {
+-         _16 = <impl Future<Output = ()> as Future>::poll(move _18, move _19) -> [return: bb24, unwind: bb19];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24];
+      }
+  
+      bb26: {
+-         _20 = move _2;
+-         _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb25, unwind: bb19];
++         _2 = move _42;
++         StorageDead(_42);
++         goto -> bb25;
+      }
+  
+      bb27: {
+-         _21 = &mut _14;
+-         _18 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _21) -> [return: bb26, unwind: bb19];
++         _2 = move _49;
++         StorageDead(_49);
++         goto -> bb32;
+      }
+  
+      bb28: {
+-         StorageLive(_14);
+-         _14 = async_drop_in_place::<AsyncInt>(copy (_22.0: &mut AsyncInt)) -> [return: bb27, unwind: bb19];
++         StorageLive(_49);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_49);
++         discriminant((*_77)) = 8;
++         return;
+      }
+  
+      bb29: {
+-         StorageDead(_24);
+-         goto -> bb1;
++         _51 = discriminant(_50);
++         switchInt(move _51) -> [0: bb23, 1: bb28, otherwise: bb8];
+      }
+  
+      bb30: {
+-         StorageDead(_24);
+-         goto -> bb1;
++         _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb29, unwind: bb24];
+      }
+  
+-     bb31 (cleanup): {
+-         StorageDead(_24);
+-         goto -> bb2;
++     bb31: {
++         _54 = move _2;
++         _53 = move _54;
++         goto -> bb30;
+      }
+  
+      bb32: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb32, unwind: bb31];
++         _55 = &mut (((*_77) as variant#8).1: impl std::future::Future<Output = ()>);
++         _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb31, unwind: bb24];
+      }
+  
+      bb33: {
+-         _2 = move _25;
+-         StorageDead(_25);
+-         goto -> bb32;
++         nop;
++         (((*_77) as variant#8).1: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb32, unwind: bb24];
+      }
+  
+      bb34: {
+-         _2 = move _25;
+-         StorageDead(_25);
+-         goto -> bb39;
++         nop;
++         _81 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct);
++         _57 = &mut ((*_81).1: AsyncInt);
++         _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb33, unwind: bb3];
+      }
+  
+-     bb35: {
+-         StorageLive(_25);
+-         _25 = yield(const ()) -> [resume: bb33, drop: bb34];
++     bb35 (cleanup): {
++         nop;
++         goto -> bb4;
+      }
+  
+      bb36: {
+-         _27 = discriminant(_26);
+-         switchInt(move _27) -> [0: bb30, 1: bb35, otherwise: bb11];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb36, unwind: bb35];
+      }
+  
+      bb37: {
+-         _26 = <impl Future<Output = ()> as Future>::poll(move _28, move _29) -> [return: bb36, unwind: bb31];
++         _2 = move _59;
++         StorageDead(_59);
++         goto -> bb36;
+      }
+  
+      bb38: {
+-         _30 = move _2;
+-         _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb37, unwind: bb31];
++         _2 = move _66;
++         StorageDead(_66);
++         goto -> bb43;
+      }
+  
+      bb39: {
+-         _31 = &mut _24;
+-         _28 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _31) -> [return: bb38, unwind: bb31];
++         StorageLive(_66);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_66);
++         discriminant((*_77)) = 10;
++         return;
+      }
+  
+      bb40: {
+-         _2 = move _32;
+-         StorageDead(_32);
+-         goto -> bb46;
++         _68 = discriminant(_67);
++         switchInt(move _68) -> [0: bb34, 1: bb39, otherwise: bb8];
+      }
+  
+      bb41: {
+-         _2 = move _32;
+-         StorageDead(_32);
+-         goto -> bb39;
++         _67 = <impl Future<Output = ()> as Future>::poll(move _69, move _70) -> [return: bb40, unwind: bb35];
+      }
+  
+      bb42: {
+-         StorageLive(_32);
+-         _32 = yield(const ()) -> [resume: bb40, drop: bb41];
++         _71 = move _2;
++         _70 = move _71;
++         goto -> bb41;
+      }
+  
+      bb43: {
+-         _34 = discriminant(_33);
+-         switchInt(move _34) -> [0: bb29, 1: bb42, otherwise: bb11];
++         _72 = &mut (((*_77) as variant#10).1: impl std::future::Future<Output = ()>);
++         _69 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _72) -> [return: bb42, unwind: bb35];
+      }
+  
+      bb44: {
+-         _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb43, unwind: bb31];
++         nop;
++         (((*_77) as variant#10).1: impl std::future::Future<Output = ()>) = <AsyncStruct as AsyncDrop>::drop(move _73) -> [return: bb43, unwind: bb35];
+      }
+  
+-     bb45: {
+-         _37 = move _2;
+-         _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb44, unwind: bb31];
++     bb45 (cleanup): {
++         discriminant((*_77)) = 2;
++         resume;
+      }
+  
+      bb46: {
+-         _38 = &mut _24;
+-         _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb45, unwind: bb31];
++         StorageLive(_5);
++         _5 = move _2;
++         goto -> bb7;
+      }
+  
+      bb47: {
+-         StorageLive(_24);
+-         _24 = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb46, unwind: bb31];
++         StorageLive(_15);
++         _15 = move _2;
++         goto -> bb11;
+      }
+  
+      bb48: {
+-         StorageDead(_41);
+-         _40 = &mut ((*_3).2: AsyncInt);
+-         _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb47, unwind: bb2];
++         StorageLive(_25);
++         _25 = move _2;
++         goto -> bb15;
+      }
+  
+      bb49: {
+-         StorageDead(_41);
+-         goto -> bb17;
++         StorageLive(_32);
++         _32 = move _2;
++         goto -> bb16;
+      }
+  
+-     bb50 (cleanup): {
+-         StorageDead(_41);
+-         goto -> bb3;
++     bb50: {
++         StorageLive(_42);
++         _42 = move _2;
++         goto -> bb26;
+      }
+  
+      bb51: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb51, unwind: bb50];
++         StorageLive(_49);
++         _49 = move _2;
++         goto -> bb27;
+      }
+  
+      bb52: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb51;
++         StorageLive(_59);
++         _59 = move _2;
++         goto -> bb37;
+      }
+  
+      bb53: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb58;
++         StorageLive(_66);
++         _66 = move _2;
++         goto -> bb38;
+      }
+  
+      bb54: {
+-         StorageLive(_42);
+-         _42 = yield(const ()) -> [resume: bb52, drop: bb53];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb54, unwind continue];
+      }
+  
+      bb55: {
+-         _44 = discriminant(_43);
+-         switchInt(move _44) -> [0: bb49, 1: bb54, otherwise: bb11];
++         _0 = Poll::<()>::Ready(const ());
++         return;
+      }
+  
+      bb56: {
+-         _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb55, unwind: bb50];
+-     }
+- 
+-     bb57: {
+-         _47 = move _2;
+-         _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb56, unwind: bb50];
+-     }
+- 
+-     bb58: {
+-         _48 = &mut _41;
+-         _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb57, unwind: bb50];
+-     }
+- 
+-     bb59: {
+-         _2 = move _49;
+-         StorageDead(_49);
+-         goto -> bb65;
+-     }
+- 
+-     bb60: {
+-         _2 = move _49;
+-         StorageDead(_49);
+-         goto -> bb58;
+-     }
+- 
+-     bb61: {
+-         StorageLive(_49);
+-         _49 = yield(const ()) -> [resume: bb59, drop: bb60];
+-     }
+- 
+-     bb62: {
+-         _51 = discriminant(_50);
+-         switchInt(move _51) -> [0: bb48, 1: bb61, otherwise: bb11];
+-     }
+- 
+-     bb63: {
+-         _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb62, unwind: bb50];
+-     }
+- 
+-     bb64: {
+-         _54 = move _2;
+-         _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb63, unwind: bb50];
+-     }
+- 
+-     bb65: {
+-         _55 = &mut _41;
+-         _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb64, unwind: bb50];
+-     }
+- 
+-     bb66: {
+-         StorageLive(_41);
+-         _41 = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb65, unwind: bb50];
+-     }
+- 
+-     bb67: {
+-         StorageDead(_58);
+-         _57 = &mut ((*_3).1: AsyncInt);
+-         _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb66, unwind: bb3];
+-     }
+- 
+-     bb68: {
+-         StorageDead(_58);
+-         _23 = &mut ((*_3).1: AsyncInt);
+-         _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb28, unwind: bb3];
+-     }
+- 
+-     bb69 (cleanup): {
+-         StorageDead(_58);
+-         goto -> bb4;
+-     }
+- 
+-     bb70: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb70, unwind: bb69];
+-     }
+- 
+-     bb71: {
+-         _2 = move _59;
+-         StorageDead(_59);
+-         goto -> bb70;
+-     }
+- 
+-     bb72: {
+-         _2 = move _59;
+-         StorageDead(_59);
+-         goto -> bb77;
+-     }
+- 
+-     bb73: {
+-         StorageLive(_59);
+-         _59 = yield(const ()) -> [resume: bb71, drop: bb72];
+-     }
+- 
+-     bb74: {
+-         _61 = discriminant(_60);
+-         switchInt(move _61) -> [0: bb68, 1: bb73, otherwise: bb11];
+-     }
+- 
+-     bb75: {
+-         _60 = <impl Future<Output = ()> as Future>::poll(move _62, move _63) -> [return: bb74, unwind: bb69];
+-     }
+- 
+-     bb76: {
+-         _64 = move _2;
+-         _63 = std::future::get_context::<'_, '_>(move _64) -> [return: bb75, unwind: bb69];
+-     }
+- 
+-     bb77: {
+-         _65 = &mut _58;
+-         _62 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _65) -> [return: bb76, unwind: bb69];
+-     }
+- 
+-     bb78: {
+-         _2 = move _66;
+-         StorageDead(_66);
+-         goto -> bb84;
+-     }
+- 
+-     bb79: {
+-         _2 = move _66;
+-         StorageDead(_66);
+-         goto -> bb77;
+-     }
+- 
+-     bb80: {
+-         StorageLive(_66);
+-         _66 = yield(const ()) -> [resume: bb78, drop: bb79];
+-     }
+- 
+-     bb81: {
+-         _68 = discriminant(_67);
+-         switchInt(move _68) -> [0: bb67, 1: bb80, otherwise: bb11];
+-     }
+- 
+-     bb82: {
+-         _67 = <impl Future<Output = ()> as Future>::poll(move _69, move _70) -> [return: bb81, unwind: bb69];
+-     }
+- 
+-     bb83: {
+-         _71 = move _2;
+-         _70 = std::future::get_context::<'_, '_>(move _71) -> [return: bb82, unwind: bb69];
+-     }
+- 
+-     bb84: {
+-         _72 = &mut _58;
+-         _69 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _72) -> [return: bb83, unwind: bb69];
+-     }
+- 
+-     bb85: {
+-         StorageLive(_58);
+-         _58 = <AsyncStruct as AsyncDrop>::drop(move _73) -> [return: bb84, unwind: bb69];
++         (((*_77) as variant#10).0: &mut AsyncStruct) = move ((*_77).0: &mut AsyncStruct);
++         _82 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct);
++         _74 = &mut (*_82);
++         _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb44, unwind: bb4];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.MentionedItems.after.mir"
new file mode 100644
index 0000000..7823a86
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.MentionedItems.after.mir"
@@ -0,0 +1,15 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<Int>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+
+    bb0: {
+        goto -> bb1;
+    }
+
+    bb1: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.StateTransform.diff"
new file mode 100644
index 0000000..1536d5b
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.Int.StateTransform.diff"
@@ -0,0 +1,43 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<Int>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<Int>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
++     let mut _0: std::task::Poll<()>;
++     let mut _3: ();
++     let mut _4: u32;
++     let mut _5: &mut {async fn body of std::future::async_drop_in_place<Int>()};
+  
+      bb0: {
++         _5 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<Int>()});
++         _4 = discriminant((*_5));
++         switchInt(move _4) -> [0: bb3, 1: bb1, otherwise: bb2];
++     }
++ 
++     bb1: {
++         _0 = Poll::<()>::Ready(const ());
++         return;
++     }
++ 
++     bb2: {
++         unreachable;
++     }
++ 
++     bb3: {
++         _0 = Poll::<()>::Ready(move _3);
++         discriminant((*_5)) = 1;
+          return;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.MentionedItems.after.mir"
new file mode 100644
index 0000000..b958b84
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.MentionedItems.after.mir"
@@ -0,0 +1,17 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<SyncInt>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut SyncInt;
+
+    bb0: {
+        _3 = no_retag copy (_1.0: &mut SyncInt);
+        drop((*_3)) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.StateTransform.diff"
new file mode 100644
index 0000000..198209a
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncInt.StateTransform.diff"
@@ -0,0 +1,60 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<SyncInt>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<SyncInt>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut SyncInt;
++     let mut _4: ();
++     let mut _5: u32;
++     let mut _6: &mut {async fn body of std::future::async_drop_in_place<SyncInt>()};
+  
+      bb0: {
+-         _3 = no_retag copy (_1.0: &mut SyncInt);
+-         drop((*_3)) -> [return: bb1, unwind continue];
++         _6 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<SyncInt>()});
++         _5 = discriminant((*_6));
++         switchInt(move _5) -> [0: bb6, 1: bb4, 2: bb3, otherwise: bb5];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _4);
++         discriminant((*_6)) = 1;
+          return;
++     }
++ 
++     bb2 (cleanup): {
++         discriminant((*_6)) = 2;
++         resume;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         _0 = Poll::<()>::Ready(const ());
++         return;
++     }
++ 
++     bb5: {
++         unreachable;
++     }
++ 
++     bb6: {
++         _3 = no_retag copy ((*_6).0: &mut SyncInt);
++         drop((*_3)) -> [return: bb1, unwind: bb2];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.MentionedItems.after.mir"
new file mode 100644
index 0000000..b5d451b
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.MentionedItems.after.mir"
@@ -0,0 +1,432 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<SyncThenAsync>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut SyncThenAsync;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: std::future::ResumeTy;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: std::future::ResumeTy;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: std::pin::Pin<&mut AsyncInt>;
+    let mut _13: &mut AsyncInt;
+    let mut _14: impl std::future::Future<Output = ()>;
+    let mut _15: std::future::ResumeTy;
+    let mut _16: std::task::Poll<()>;
+    let mut _17: isize;
+    let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: std::future::ResumeTy;
+    let mut _21: &mut impl std::future::Future<Output = ()>;
+    let mut _22: std::pin::Pin<&mut AsyncInt>;
+    let mut _23: &mut AsyncInt;
+    let mut _24: impl std::future::Future<Output = ()>;
+    let mut _25: std::future::ResumeTy;
+    let mut _26: std::task::Poll<()>;
+    let mut _27: isize;
+    let mut _28: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _29: &mut std::task::Context<'_>;
+    let mut _30: std::future::ResumeTy;
+    let mut _31: &mut impl std::future::Future<Output = ()>;
+    let mut _32: std::future::ResumeTy;
+    let mut _33: std::task::Poll<()>;
+    let mut _34: isize;
+    let mut _35: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _36: &mut std::task::Context<'_>;
+    let mut _37: std::future::ResumeTy;
+    let mut _38: &mut impl std::future::Future<Output = ()>;
+    let mut _39: std::pin::Pin<&mut AsyncInt>;
+    let mut _40: &mut AsyncInt;
+    let mut _41: impl std::future::Future<Output = ()>;
+    let mut _42: std::future::ResumeTy;
+    let mut _43: std::task::Poll<()>;
+    let mut _44: isize;
+    let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _46: &mut std::task::Context<'_>;
+    let mut _47: std::future::ResumeTy;
+    let mut _48: &mut impl std::future::Future<Output = ()>;
+    let mut _49: std::future::ResumeTy;
+    let mut _50: std::task::Poll<()>;
+    let mut _51: isize;
+    let mut _52: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _53: &mut std::task::Context<'_>;
+    let mut _54: std::future::ResumeTy;
+    let mut _55: &mut impl std::future::Future<Output = ()>;
+    let mut _56: std::pin::Pin<&mut AsyncInt>;
+    let mut _57: &mut AsyncInt;
+    let mut _58: &mut SyncThenAsync;
+    let mut _59: ();
+
+    bb0: {
+        _3 = move (_1.0: &mut SyncThenAsync);
+        goto -> bb74;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4 (cleanup): {
+        drop(((*_3).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+    }
+
+    bb5 (cleanup): {
+        drop(((*_3).2: SyncInt)) -> [return: bb4, unwind terminate(cleanup)];
+    }
+
+    bb6 (cleanup): {
+        drop(((*_3).1: AsyncInt)) -> [return: bb5, unwind terminate(cleanup)];
+    }
+
+    bb7: {
+        StorageDead(_4);
+        goto -> bb1;
+    }
+
+    bb8 (cleanup): {
+        StorageDead(_4);
+        goto -> bb2;
+    }
+
+    bb9: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8];
+    }
+
+    bb10: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb9;
+    }
+
+    bb11: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb17;
+    }
+
+    bb12: {
+        StorageLive(_5);
+        _5 = yield(const ()) -> [resume: bb10, drop: bb11];
+    }
+
+    bb13: {
+        unreachable;
+    }
+
+    bb14: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb7, 1: bb12, otherwise: bb13];
+    }
+
+    bb15: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb14, unwind: bb8];
+    }
+
+    bb16: {
+        _10 = move _2;
+        _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb15, unwind: bb8];
+    }
+
+    bb17: {
+        _11 = &mut _4;
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb16, unwind: bb8];
+    }
+
+    bb18: {
+        StorageLive(_4);
+        _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb17, unwind: bb8];
+    }
+
+    bb19: {
+        _13 = &mut ((*_3).3: AsyncInt);
+        _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb18, unwind: bb2];
+    }
+
+    bb20: {
+        drop(((*_3).2: SyncInt)) -> [return: bb19, unwind: bb4];
+    }
+
+    bb21: {
+        StorageDead(_14);
+        goto -> bb20;
+    }
+
+    bb22 (cleanup): {
+        StorageDead(_14);
+        goto -> bb5;
+    }
+
+    bb23: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb23, unwind: bb22];
+    }
+
+    bb24: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb23;
+    }
+
+    bb25: {
+        _2 = move _15;
+        StorageDead(_15);
+        goto -> bb30;
+    }
+
+    bb26: {
+        StorageLive(_15);
+        _15 = yield(const ()) -> [resume: bb24, drop: bb25];
+    }
+
+    bb27: {
+        _17 = discriminant(_16);
+        switchInt(move _17) -> [0: bb21, 1: bb26, otherwise: bb13];
+    }
+
+    bb28: {
+        _16 = <impl Future<Output = ()> as Future>::poll(move _18, move _19) -> [return: bb27, unwind: bb22];
+    }
+
+    bb29: {
+        _20 = move _2;
+        _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb28, unwind: bb22];
+    }
+
+    bb30: {
+        _21 = &mut _14;
+        _18 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _21) -> [return: bb29, unwind: bb22];
+    }
+
+    bb31: {
+        StorageLive(_14);
+        _14 = async_drop_in_place::<AsyncInt>(copy (_22.0: &mut AsyncInt)) -> [return: bb30, unwind: bb22];
+    }
+
+    bb32: {
+        _23 = &mut ((*_3).1: AsyncInt);
+        _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb31, unwind: bb5];
+    }
+
+    bb33: {
+        StorageDead(_24);
+        goto -> bb3;
+    }
+
+    bb34: {
+        StorageDead(_24);
+        goto -> bb1;
+    }
+
+    bb35 (cleanup): {
+        StorageDead(_24);
+        goto -> bb2;
+    }
+
+    bb36: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb36, unwind: bb35];
+    }
+
+    bb37: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb36;
+    }
+
+    bb38: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb43;
+    }
+
+    bb39: {
+        StorageLive(_25);
+        _25 = yield(const ()) -> [resume: bb37, drop: bb38];
+    }
+
+    bb40: {
+        _27 = discriminant(_26);
+        switchInt(move _27) -> [0: bb34, 1: bb39, otherwise: bb13];
+    }
+
+    bb41: {
+        _26 = <impl Future<Output = ()> as Future>::poll(move _28, move _29) -> [return: bb40, unwind: bb35];
+    }
+
+    bb42: {
+        _30 = move _2;
+        _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb41, unwind: bb35];
+    }
+
+    bb43: {
+        _31 = &mut _24;
+        _28 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _31) -> [return: bb42, unwind: bb35];
+    }
+
+    bb44: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb50;
+    }
+
+    bb45: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb43;
+    }
+
+    bb46: {
+        StorageLive(_32);
+        _32 = yield(const ()) -> [resume: bb44, drop: bb45];
+    }
+
+    bb47: {
+        _34 = discriminant(_33);
+        switchInt(move _34) -> [0: bb33, 1: bb46, otherwise: bb13];
+    }
+
+    bb48: {
+        _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb47, unwind: bb35];
+    }
+
+    bb49: {
+        _37 = move _2;
+        _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb48, unwind: bb35];
+    }
+
+    bb50: {
+        _38 = &mut _24;
+        _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb49, unwind: bb35];
+    }
+
+    bb51: {
+        StorageLive(_24);
+        _24 = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb50, unwind: bb35];
+    }
+
+    bb52: {
+        _40 = &mut ((*_3).3: AsyncInt);
+        _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb51, unwind: bb2];
+    }
+
+    bb53: {
+        drop(((*_3).2: SyncInt)) -> [return: bb52, unwind: bb4];
+    }
+
+    bb54: {
+        StorageDead(_41);
+        goto -> bb53;
+    }
+
+    bb55: {
+        StorageDead(_41);
+        goto -> bb20;
+    }
+
+    bb56 (cleanup): {
+        StorageDead(_41);
+        goto -> bb5;
+    }
+
+    bb57: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb57, unwind: bb56];
+    }
+
+    bb58: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb57;
+    }
+
+    bb59: {
+        _2 = move _42;
+        StorageDead(_42);
+        goto -> bb64;
+    }
+
+    bb60: {
+        StorageLive(_42);
+        _42 = yield(const ()) -> [resume: bb58, drop: bb59];
+    }
+
+    bb61: {
+        _44 = discriminant(_43);
+        switchInt(move _44) -> [0: bb55, 1: bb60, otherwise: bb13];
+    }
+
+    bb62: {
+        _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb61, unwind: bb56];
+    }
+
+    bb63: {
+        _47 = move _2;
+        _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb62, unwind: bb56];
+    }
+
+    bb64: {
+        _48 = &mut _41;
+        _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb63, unwind: bb56];
+    }
+
+    bb65: {
+        _2 = move _49;
+        StorageDead(_49);
+        goto -> bb71;
+    }
+
+    bb66: {
+        _2 = move _49;
+        StorageDead(_49);
+        goto -> bb64;
+    }
+
+    bb67: {
+        StorageLive(_49);
+        _49 = yield(const ()) -> [resume: bb65, drop: bb66];
+    }
+
+    bb68: {
+        _51 = discriminant(_50);
+        switchInt(move _51) -> [0: bb54, 1: bb67, otherwise: bb13];
+    }
+
+    bb69: {
+        _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb68, unwind: bb56];
+    }
+
+    bb70: {
+        _54 = move _2;
+        _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb69, unwind: bb56];
+    }
+
+    bb71: {
+        _55 = &mut _41;
+        _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb70, unwind: bb56];
+    }
+
+    bb72: {
+        StorageLive(_41);
+        _41 = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb71, unwind: bb56];
+    }
+
+    bb73: {
+        _57 = &mut ((*_3).1: AsyncInt);
+        _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb72, unwind: bb5];
+    }
+
+    bb74: {
+        _58 = &mut (*_3);
+        _59 = <SyncThenAsync as Drop>::drop(move _58) -> [return: bb73, unwind: bb6];
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.StateTransform.diff"
new file mode 100644
index 0000000..1247a7f
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-\173closure\0430\175.SyncThenAsync.StateTransform.diff"
@@ -0,0 +1,506 @@
+- // MIR for `std::future::async_drop_in_place::{closure#0}` before StateTransform
++ // MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform
+  
+- fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<SyncThenAsync>()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place<SyncThenAsync>()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: &mut SyncThenAsync;
++         field _s1: impl Future<Output = ()>;
++         field _s2: impl Future<Output = ()>;
++         field _s3: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1],
++             Suspend1 (4): [_s2],
++             Suspend2 (5): [_s2],
++             Suspend3 (6): [_s0, _s3],
++             Suspend4 (7): [_s0, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3)}
++     }
++     let mut _0: std::task::Poll<()>;
+      let mut _3: &mut SyncThenAsync;
+      let mut _4: impl std::future::Future<Output = ()>;
+-     let mut _5: std::future::ResumeTy;
++     let mut _5: &mut std::task::Context<'_>;
+      let mut _6: std::task::Poll<()>;
+      let mut _7: isize;
+      let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _9: &mut std::task::Context<'_>;
+-     let mut _10: std::future::ResumeTy;
++     let mut _10: &mut std::task::Context<'_>;
+      let mut _11: &mut impl std::future::Future<Output = ()>;
+      let mut _12: std::pin::Pin<&mut AsyncInt>;
+      let mut _13: &mut AsyncInt;
+      let mut _14: impl std::future::Future<Output = ()>;
+      let mut _15: std::future::ResumeTy;
+      let mut _16: std::task::Poll<()>;
+      let mut _17: isize;
+      let mut _18: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _19: &mut std::task::Context<'_>;
+      let mut _20: std::future::ResumeTy;
+      let mut _21: &mut impl std::future::Future<Output = ()>;
+      let mut _22: std::pin::Pin<&mut AsyncInt>;
+      let mut _23: &mut AsyncInt;
+      let mut _24: impl std::future::Future<Output = ()>;
+-     let mut _25: std::future::ResumeTy;
++     let mut _25: &mut std::task::Context<'_>;
+      let mut _26: std::task::Poll<()>;
+      let mut _27: isize;
+      let mut _28: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _29: &mut std::task::Context<'_>;
+-     let mut _30: std::future::ResumeTy;
++     let mut _30: &mut std::task::Context<'_>;
+      let mut _31: &mut impl std::future::Future<Output = ()>;
+-     let mut _32: std::future::ResumeTy;
++     let mut _32: &mut std::task::Context<'_>;
+      let mut _33: std::task::Poll<()>;
+      let mut _34: isize;
+      let mut _35: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _36: &mut std::task::Context<'_>;
+-     let mut _37: std::future::ResumeTy;
++     let mut _37: &mut std::task::Context<'_>;
+      let mut _38: &mut impl std::future::Future<Output = ()>;
+      let mut _39: std::pin::Pin<&mut AsyncInt>;
+      let mut _40: &mut AsyncInt;
+      let mut _41: impl std::future::Future<Output = ()>;
+-     let mut _42: std::future::ResumeTy;
++     let mut _42: &mut std::task::Context<'_>;
+      let mut _43: std::task::Poll<()>;
+      let mut _44: isize;
+      let mut _45: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _46: &mut std::task::Context<'_>;
+-     let mut _47: std::future::ResumeTy;
++     let mut _47: &mut std::task::Context<'_>;
+      let mut _48: &mut impl std::future::Future<Output = ()>;
+-     let mut _49: std::future::ResumeTy;
++     let mut _49: &mut std::task::Context<'_>;
+      let mut _50: std::task::Poll<()>;
+      let mut _51: isize;
+      let mut _52: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _53: &mut std::task::Context<'_>;
+-     let mut _54: std::future::ResumeTy;
++     let mut _54: &mut std::task::Context<'_>;
+      let mut _55: &mut impl std::future::Future<Output = ()>;
+      let mut _56: std::pin::Pin<&mut AsyncInt>;
+      let mut _57: &mut AsyncInt;
+      let mut _58: &mut SyncThenAsync;
+      let mut _59: ();
++     let mut _60: ();
++     let mut _61: u32;
++     let mut _62: &mut {async fn body of std::future::async_drop_in_place<SyncThenAsync>()};
++     let mut _63: &mut SyncThenAsync;
++     let mut _64: &mut SyncThenAsync;
++     let mut _65: &mut SyncThenAsync;
++     let mut _66: &mut SyncThenAsync;
++     let mut _67: &mut SyncThenAsync;
++     let mut _68: &mut SyncThenAsync;
++     let mut _69: &mut SyncThenAsync;
+  
+      bb0: {
+-         _3 = move (_1.0: &mut SyncThenAsync);
+-         _58 = &mut (*_3);
+-         _59 = <SyncThenAsync as Drop>::drop(move _58) -> [return: bb58, unwind: bb5];
++         _62 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place<SyncThenAsync>()});
++         _61 = discriminant((*_62));
++         switchInt(move _61) -> [0: bb42, 1: bb41, 2: bb40, 3: bb35, 4: bb36, 5: bb37, 6: bb38, 7: bb39, otherwise: bb9];
+      }
+  
+      bb1: {
++         _0 = Poll::<()>::Ready(move _60);
++         discriminant((*_62)) = 1;
+          return;
+      }
+  
+      bb2 (cleanup): {
+-         resume;
++         goto -> bb34;
+      }
+  
+      bb3 (cleanup): {
+-         drop(((*_3).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
++         _63 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         drop(((*_63).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)];
+      }
+  
+      bb4 (cleanup): {
+-         drop(((*_3).2: SyncInt)) -> [return: bb3, unwind terminate(cleanup)];
++         _64 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         drop(((*_64).2: SyncInt)) -> [return: bb3, unwind terminate(cleanup)];
+      }
+  
+      bb5 (cleanup): {
+-         drop(((*_3).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)];
++         _65 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         drop(((*_65).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)];
+      }
+  
+-     bb6: {
+-         StorageDead(_4);
+-         goto -> bb1;
++     bb6 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb7 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb2;
++     bb7: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6];
+      }
+  
+      bb8: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7];
++         _2 = move _5;
++         StorageDead(_5);
++         goto -> bb7;
+      }
+  
+      bb9: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb8;
++         unreachable;
+      }
+  
+      bb10: {
+-         _2 = move _5;
+-         StorageDead(_5);
+-         goto -> bb16;
++         nop;
++         goto -> bb1;
+      }
+  
+-     bb11: {
+-         StorageLive(_5);
+-         _5 = yield(const ()) -> [resume: bb9, drop: bb10];
++     bb11 (cleanup): {
++         nop;
++         goto -> bb2;
+      }
+  
+      bb12: {
+-         unreachable;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb12, unwind: bb11];
+      }
+  
+      bb13: {
+-         _7 = discriminant(_6);
+-         switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12];
++         _2 = move _25;
++         StorageDead(_25);
++         goto -> bb12;
+      }
+  
+      bb14: {
+-         _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7];
++         _2 = move _32;
++         StorageDead(_32);
++         goto -> bb19;
+      }
+  
+      bb15: {
+-         _10 = move _2;
+-         _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7];
++         StorageLive(_32);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_32);
++         discriminant((*_62)) = 5;
++         return;
+      }
+  
+      bb16: {
+-         _11 = &mut _4;
+-         _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb15, unwind: bb7];
++         _34 = discriminant(_33);
++         switchInt(move _34) -> [0: bb10, 1: bb15, otherwise: bb9];
+      }
+  
+      bb17: {
+-         StorageLive(_4);
+-         _4 = async_drop_in_place::<AsyncInt>(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7];
++         _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb16, unwind: bb11];
+      }
+  
+      bb18: {
+-         _13 = &mut ((*_3).3: AsyncInt);
+-         _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2];
++         _37 = move _2;
++         _36 = move _37;
++         goto -> bb17;
+      }
+  
+      bb19: {
+-         StorageDead(_24);
+-         goto -> bb1;
++         _38 = &mut (((*_62) as variant#5).0: impl std::future::Future<Output = ()>);
++         _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb18, unwind: bb11];
+      }
+  
+      bb20: {
+-         StorageDead(_24);
+-         goto -> bb1;
++         nop;
++         (((*_62) as variant#5).0: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb19, unwind: bb11];
+      }
+  
+-     bb21 (cleanup): {
+-         StorageDead(_24);
+-         goto -> bb2;
++     bb21: {
++         _66 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         _40 = &mut ((*_66).3: AsyncInt);
++         _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb20, unwind: bb2];
+      }
+  
+      bb22: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb22, unwind: bb21];
++         nop;
++         _67 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         drop(((*_67).2: SyncInt)) -> [return: bb21, unwind: bb3];
+      }
+  
+-     bb23: {
+-         _2 = move _25;
+-         StorageDead(_25);
+-         goto -> bb22;
++     bb23 (cleanup): {
++         nop;
++         goto -> bb4;
+      }
+  
+      bb24: {
+-         _2 = move _25;
+-         StorageDead(_25);
+-         goto -> bb29;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb24, unwind: bb23];
+      }
+  
+      bb25: {
+-         StorageLive(_25);
+-         _25 = yield(const ()) -> [resume: bb23, drop: bb24];
++         _2 = move _42;
++         StorageDead(_42);
++         goto -> bb24;
+      }
+  
+      bb26: {
+-         _27 = discriminant(_26);
+-         switchInt(move _27) -> [0: bb20, 1: bb25, otherwise: bb12];
++         _2 = move _49;
++         StorageDead(_49);
++         goto -> bb31;
+      }
+  
+      bb27: {
+-         _26 = <impl Future<Output = ()> as Future>::poll(move _28, move _29) -> [return: bb26, unwind: bb21];
++         StorageLive(_49);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_49);
++         discriminant((*_62)) = 7;
++         return;
+      }
+  
+      bb28: {
+-         _30 = move _2;
+-         _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb27, unwind: bb21];
++         _51 = discriminant(_50);
++         switchInt(move _51) -> [0: bb22, 1: bb27, otherwise: bb9];
+      }
+  
+      bb29: {
+-         _31 = &mut _24;
+-         _28 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _31) -> [return: bb28, unwind: bb21];
++         _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb28, unwind: bb23];
+      }
+  
+      bb30: {
+-         _2 = move _32;
+-         StorageDead(_32);
+-         goto -> bb36;
++         _54 = move _2;
++         _53 = move _54;
++         goto -> bb29;
+      }
+  
+      bb31: {
+-         _2 = move _32;
+-         StorageDead(_32);
+-         goto -> bb29;
++         _55 = &mut (((*_62) as variant#7).1: impl std::future::Future<Output = ()>);
++         _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb30, unwind: bb23];
+      }
+  
+      bb32: {
+-         StorageLive(_32);
+-         _32 = yield(const ()) -> [resume: bb30, drop: bb31];
++         nop;
++         (((*_62) as variant#7).1: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb31, unwind: bb23];
+      }
+  
+      bb33: {
+-         _34 = discriminant(_33);
+-         switchInt(move _34) -> [0: bb19, 1: bb32, otherwise: bb12];
++         _68 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         _57 = &mut ((*_68).1: AsyncInt);
++         _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb32, unwind: bb4];
+      }
+  
+-     bb34: {
+-         _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb33, unwind: bb21];
++     bb34 (cleanup): {
++         discriminant((*_62)) = 2;
++         resume;
+      }
+  
+      bb35: {
+-         _37 = move _2;
+-         _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb34, unwind: bb21];
++         StorageLive(_5);
++         _5 = move _2;
++         goto -> bb8;
+      }
+  
+      bb36: {
+-         _38 = &mut _24;
+-         _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb35, unwind: bb21];
++         StorageLive(_25);
++         _25 = move _2;
++         goto -> bb13;
+      }
+  
+      bb37: {
+-         StorageLive(_24);
+-         _24 = async_drop_in_place::<AsyncInt>(copy (_39.0: &mut AsyncInt)) -> [return: bb36, unwind: bb21];
++         StorageLive(_32);
++         _32 = move _2;
++         goto -> bb14;
+      }
+  
+      bb38: {
+-         _40 = &mut ((*_3).3: AsyncInt);
+-         _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb37, unwind: bb2];
++         StorageLive(_42);
++         _42 = move _2;
++         goto -> bb25;
+      }
+  
+      bb39: {
+-         StorageDead(_41);
+-         drop(((*_3).2: SyncInt)) -> [return: bb38, unwind: bb3];
++         StorageLive(_49);
++         _49 = move _2;
++         goto -> bb26;
+      }
+  
+      bb40: {
+-         StorageDead(_41);
+-         drop(((*_3).2: SyncInt)) -> [return: bb18, unwind: bb3];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb40, unwind continue];
+      }
+  
+-     bb41 (cleanup): {
+-         StorageDead(_41);
+-         goto -> bb4;
++     bb41: {
++         _0 = Poll::<()>::Ready(const ());
++         return;
+      }
+  
+      bb42: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb42, unwind: bb41];
+-     }
+- 
+-     bb43: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb42;
+-     }
+- 
+-     bb44: {
+-         _2 = move _42;
+-         StorageDead(_42);
+-         goto -> bb49;
+-     }
+- 
+-     bb45: {
+-         StorageLive(_42);
+-         _42 = yield(const ()) -> [resume: bb43, drop: bb44];
+-     }
+- 
+-     bb46: {
+-         _44 = discriminant(_43);
+-         switchInt(move _44) -> [0: bb40, 1: bb45, otherwise: bb12];
+-     }
+- 
+-     bb47: {
+-         _43 = <impl Future<Output = ()> as Future>::poll(move _45, move _46) -> [return: bb46, unwind: bb41];
+-     }
+- 
+-     bb48: {
+-         _47 = move _2;
+-         _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb47, unwind: bb41];
+-     }
+- 
+-     bb49: {
+-         _48 = &mut _41;
+-         _45 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _48) -> [return: bb48, unwind: bb41];
+-     }
+- 
+-     bb50: {
+-         _2 = move _49;
+-         StorageDead(_49);
+-         goto -> bb56;
+-     }
+- 
+-     bb51: {
+-         _2 = move _49;
+-         StorageDead(_49);
+-         goto -> bb49;
+-     }
+- 
+-     bb52: {
+-         StorageLive(_49);
+-         _49 = yield(const ()) -> [resume: bb50, drop: bb51];
+-     }
+- 
+-     bb53: {
+-         _51 = discriminant(_50);
+-         switchInt(move _51) -> [0: bb39, 1: bb52, otherwise: bb12];
+-     }
+- 
+-     bb54: {
+-         _50 = <impl Future<Output = ()> as Future>::poll(move _52, move _53) -> [return: bb53, unwind: bb41];
+-     }
+- 
+-     bb55: {
+-         _54 = move _2;
+-         _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb54, unwind: bb41];
+-     }
+- 
+-     bb56: {
+-         _55 = &mut _41;
+-         _52 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _55) -> [return: bb55, unwind: bb41];
+-     }
+- 
+-     bb57: {
+-         StorageLive(_41);
+-         _41 = async_drop_in_place::<AsyncInt>(copy (_56.0: &mut AsyncInt)) -> [return: bb56, unwind: bb41];
+-     }
+- 
+-     bb58: {
+-         _57 = &mut ((*_3).1: AsyncInt);
+-         _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb57, unwind: bb4];
++         (((*_62) as variant#7).0: &mut SyncThenAsync) = move ((*_62).0: &mut SyncThenAsync);
++         _69 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync);
++         _58 = &mut (*_69);
++         _59 = <SyncThenAsync as Drop>::drop(move _58) -> [return: bb33, unwind: bb5];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.ElaborateDrops.diff" "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.ElaborateDrops.diff"
new file mode 100644
index 0000000..b11d65b
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.ElaborateDrops.diff"
@@ -0,0 +1,348 @@
+- // MIR for `double::{closure#0}` before ElaborateDrops
++ // MIR for `double::{closure#0}` after ElaborateDrops
+  
+  fn double::{closure#0}(_1: {async fn body of double()}, _2: std::future::ResumeTy) -> ()
+  yields ()
+   {
+      debug _task_context => _2;
+      let mut _0: ();
+      let _3: SyncInt;
++     let mut _6: impl std::future::Future<Output = ()>;
++     let mut _7: std::future::ResumeTy;
++     let mut _8: std::task::Poll<()>;
++     let mut _9: isize;
++     let mut _10: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _11: &mut std::task::Context<'_>;
++     let mut _12: std::future::ResumeTy;
++     let mut _13: &mut impl std::future::Future<Output = ()>;
++     let mut _14: std::future::ResumeTy;
++     let mut _15: std::task::Poll<()>;
++     let mut _16: isize;
++     let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _18: &mut std::task::Context<'_>;
++     let mut _19: std::future::ResumeTy;
++     let mut _20: &mut impl std::future::Future<Output = ()>;
++     let mut _21: std::pin::Pin<&mut AsyncInt>;
++     let mut _22: &mut AsyncInt;
++     let mut _23: impl std::future::Future<Output = ()>;
++     let mut _24: std::future::ResumeTy;
++     let mut _25: std::task::Poll<()>;
++     let mut _26: isize;
++     let mut _27: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _28: &mut std::task::Context<'_>;
++     let mut _29: std::future::ResumeTy;
++     let mut _30: &mut impl std::future::Future<Output = ()>;
++     let mut _31: std::future::ResumeTy;
++     let mut _32: std::task::Poll<()>;
++     let mut _33: isize;
++     let mut _34: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _35: &mut std::task::Context<'_>;
++     let mut _36: std::future::ResumeTy;
++     let mut _37: &mut impl std::future::Future<Output = ()>;
++     let mut _38: std::pin::Pin<&mut AsyncInt>;
++     let mut _39: &mut AsyncInt;
+      scope 1 {
+          debug sync_int => _3;
+          let _4: AsyncInt;
+          scope 2 {
+              debug async_int => _4;
+              let _5: AsyncInt;
+              scope 3 {
+                  debug async_int_again => _5;
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_3);
+          _3 = SyncInt(const 0_i32);
+          StorageLive(_4);
+          _4 = AsyncInt(const 0_i32);
+          StorageLive(_5);
+          _5 = AsyncInt(const 0_i32);
+          _0 = const ();
+-         drop(_5) -> [return: bb1, unwind: bb9, drop: bb5];
++         goto -> bb35;
+      }
+  
+      bb1: {
+          StorageDead(_5);
+-         drop(_4) -> [return: bb2, unwind: bb10, drop: bb6];
++         goto -> bb55;
+      }
+  
+      bb2: {
+          StorageDead(_4);
+          drop(_3) -> [return: bb3, unwind: bb11];
+      }
+  
+      bb3: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb4, drop: bb8, unwind continue];
++         drop(_1) -> [return: bb4, unwind: bb12];
+      }
+  
+      bb4: {
+          return;
+      }
+  
+      bb5: {
+          StorageDead(_5);
+-         drop(_4) -> [return: bb6, unwind: bb13];
++         goto -> bb6;
+      }
+  
+      bb6: {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb7, unwind: bb14];
++         goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb8, unwind continue];
++         goto -> bb8;
+      }
+  
+      bb8: {
+          coroutine_drop;
+      }
+  
+      bb9 (cleanup): {
+          StorageDead(_5);
+          drop(_4) -> [return: bb10, unwind terminate(cleanup)];
+      }
+  
+      bb10 (cleanup): {
+          StorageDead(_4);
+          drop(_3) -> [return: bb11, unwind terminate(cleanup)];
+      }
+  
+      bb11 (cleanup): {
+          StorageDead(_3);
+          drop(_1) -> [return: bb12, unwind terminate(cleanup)];
+      }
+  
+      bb12 (cleanup): {
+          resume;
+      }
+  
+      bb13 (cleanup): {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb14, unwind terminate(cleanup)];
++         goto -> bb14;
+      }
+  
+      bb14 (cleanup): {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb12, unwind terminate(cleanup)];
++         goto -> bb12;
++     }
++ 
++     bb15: {
++         StorageDead(_6);
++         goto -> bb1;
++     }
++ 
++     bb16: {
++         StorageDead(_6);
++         goto -> bb5;
++     }
++ 
++     bb17 (cleanup): {
++         StorageDead(_6);
++         goto -> bb9;
++     }
++ 
++     bb18: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb18, unwind: bb17];
++     }
++ 
++     bb19: {
++         _2 = move _7;
++         StorageDead(_7);
++         goto -> bb18;
++     }
++ 
++     bb20: {
++         _2 = move _7;
++         StorageDead(_7);
++         goto -> bb26;
++     }
++ 
++     bb21: {
++         StorageLive(_7);
++         _7 = yield(const ()) -> [resume: bb19, drop: bb20];
++     }
++ 
++     bb22: {
++         unreachable;
++     }
++ 
++     bb23: {
++         _9 = discriminant(_8);
++         switchInt(move _9) -> [0: bb16, 1: bb21, otherwise: bb22];
++     }
++ 
++     bb24: {
++         _8 = <impl Future<Output = ()> as Future>::poll(move _10, move _11) -> [return: bb23, unwind: bb17];
++     }
++ 
++     bb25: {
++         _12 = move _2;
++         _11 = std::future::get_context::<'_, '_>(move _12) -> [return: bb24, unwind: bb17];
++     }
++ 
++     bb26: {
++         _13 = &mut _6;
++         _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _13) -> [return: bb25, unwind: bb17];
++     }
++ 
++     bb27: {
++         _2 = move _14;
++         StorageDead(_14);
++         goto -> bb33;
++     }
++ 
++     bb28: {
++         _2 = move _14;
++         StorageDead(_14);
++         goto -> bb26;
++     }
++ 
++     bb29: {
++         StorageLive(_14);
++         _14 = yield(const ()) -> [resume: bb27, drop: bb28];
++     }
++ 
++     bb30: {
++         _16 = discriminant(_15);
++         switchInt(move _16) -> [0: bb15, 1: bb29, otherwise: bb22];
++     }
++ 
++     bb31: {
++         _15 = <impl Future<Output = ()> as Future>::poll(move _17, move _18) -> [return: bb30, unwind: bb17];
++     }
++ 
++     bb32: {
++         _19 = move _2;
++         _18 = std::future::get_context::<'_, '_>(move _19) -> [return: bb31, unwind: bb17];
++     }
++ 
++     bb33: {
++         _20 = &mut _6;
++         _17 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _20) -> [return: bb32, unwind: bb17];
++     }
++ 
++     bb34: {
++         StorageLive(_6);
++         _6 = async_drop_in_place::<AsyncInt>(copy (_21.0: &mut AsyncInt)) -> [return: bb33, unwind: bb17];
++     }
++ 
++     bb35: {
++         _22 = &mut _5;
++         _21 = Pin::<&mut AsyncInt>::new_unchecked(move _22) -> [return: bb34, unwind: bb9];
++     }
++ 
++     bb36: {
++         StorageDead(_23);
++         goto -> bb2;
++     }
++ 
++     bb37: {
++         StorageDead(_23);
++         goto -> bb6;
++     }
++ 
++     bb38 (cleanup): {
++         StorageDead(_23);
++         goto -> bb10;
++     }
++ 
++     bb39: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb39, unwind: bb38];
++     }
++ 
++     bb40: {
++         _2 = move _24;
++         StorageDead(_24);
++         goto -> bb39;
++     }
++ 
++     bb41: {
++         _2 = move _24;
++         StorageDead(_24);
++         goto -> bb46;
++     }
++ 
++     bb42: {
++         StorageLive(_24);
++         _24 = yield(const ()) -> [resume: bb40, drop: bb41];
++     }
++ 
++     bb43: {
++         _26 = discriminant(_25);
++         switchInt(move _26) -> [0: bb37, 1: bb42, otherwise: bb22];
++     }
++ 
++     bb44: {
++         _25 = <impl Future<Output = ()> as Future>::poll(move _27, move _28) -> [return: bb43, unwind: bb38];
++     }
++ 
++     bb45: {
++         _29 = move _2;
++         _28 = std::future::get_context::<'_, '_>(move _29) -> [return: bb44, unwind: bb38];
++     }
++ 
++     bb46: {
++         _30 = &mut _23;
++         _27 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _30) -> [return: bb45, unwind: bb38];
++     }
++ 
++     bb47: {
++         _2 = move _31;
++         StorageDead(_31);
++         goto -> bb53;
++     }
++ 
++     bb48: {
++         _2 = move _31;
++         StorageDead(_31);
++         goto -> bb46;
++     }
++ 
++     bb49: {
++         StorageLive(_31);
++         _31 = yield(const ()) -> [resume: bb47, drop: bb48];
++     }
++ 
++     bb50: {
++         _33 = discriminant(_32);
++         switchInt(move _33) -> [0: bb36, 1: bb49, otherwise: bb22];
++     }
++ 
++     bb51: {
++         _32 = <impl Future<Output = ()> as Future>::poll(move _34, move _35) -> [return: bb50, unwind: bb38];
++     }
++ 
++     bb52: {
++         _36 = move _2;
++         _35 = std::future::get_context::<'_, '_>(move _36) -> [return: bb51, unwind: bb38];
++     }
++ 
++     bb53: {
++         _37 = &mut _23;
++         _34 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _37) -> [return: bb52, unwind: bb38];
++     }
++ 
++     bb54: {
++         StorageLive(_23);
++         _23 = async_drop_in_place::<AsyncInt>(copy (_38.0: &mut AsyncInt)) -> [return: bb53, unwind: bb38];
++     }
++ 
++     bb55: {
++         _39 = &mut _4;
++         _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb54, unwind: bb10];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..b59d810
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,477 @@
+- // MIR for `double::{closure#0}` before StateTransform
++ // MIR for `double::{closure#0}` after StateTransform
+  
+- fn double::{closure#0}(_1: {async fn body of double()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: ();
++         field _s1: SyncInt;
++         field _s2: AsyncInt;
++         field _s3: AsyncInt;
++         field _s4: impl Future<Output = ()>;
++         field _s5: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1, _s2, _s3, _s4],
++             Suspend1 (4): [_s0, _s1, _s2, _s3, _s4],
++             Suspend2 (5): [_s1, _s2, _s5],
++             Suspend3 (6): [_s0, _s1, _s2, _s5],
++         }
++         storage_conflicts = BitMatrix(6x6) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s1, _s5), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s2, _s5), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s3, _s4), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s3), (_s4, _s4), (_s5, _s0), (_s5, _s1), (_s5, _s2), (_s5, _s5)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug sync_int => _s1;
++     let mut _0: std::task::Poll<()>;
+      let _3: SyncInt;
+      let mut _6: impl std::future::Future<Output = ()>;
+-     let mut _7: std::future::ResumeTy;
++     let mut _7: &mut std::task::Context<'_>;
+      let mut _8: std::task::Poll<()>;
+      let mut _9: isize;
+      let mut _10: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _11: &mut std::task::Context<'_>;
+-     let mut _12: std::future::ResumeTy;
++     let mut _12: &mut std::task::Context<'_>;
+      let mut _13: &mut impl std::future::Future<Output = ()>;
+-     let mut _14: std::future::ResumeTy;
++     let mut _14: &mut std::task::Context<'_>;
+      let mut _15: std::task::Poll<()>;
+      let mut _16: isize;
+      let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _18: &mut std::task::Context<'_>;
+-     let mut _19: std::future::ResumeTy;
++     let mut _19: &mut std::task::Context<'_>;
+      let mut _20: &mut impl std::future::Future<Output = ()>;
+      let mut _21: std::pin::Pin<&mut AsyncInt>;
+      let mut _22: &mut AsyncInt;
+      let mut _23: impl std::future::Future<Output = ()>;
+-     let mut _24: std::future::ResumeTy;
++     let mut _24: &mut std::task::Context<'_>;
+      let mut _25: std::task::Poll<()>;
+      let mut _26: isize;
+      let mut _27: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _28: &mut std::task::Context<'_>;
+-     let mut _29: std::future::ResumeTy;
++     let mut _29: &mut std::task::Context<'_>;
+      let mut _30: &mut impl std::future::Future<Output = ()>;
+-     let mut _31: std::future::ResumeTy;
++     let mut _31: &mut std::task::Context<'_>;
+      let mut _32: std::task::Poll<()>;
+      let mut _33: isize;
+      let mut _34: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _35: &mut std::task::Context<'_>;
+-     let mut _36: std::future::ResumeTy;
++     let mut _36: &mut std::task::Context<'_>;
+      let mut _37: &mut impl std::future::Future<Output = ()>;
+      let mut _38: std::pin::Pin<&mut AsyncInt>;
+      let mut _39: &mut AsyncInt;
++     let mut _40: ();
++     let mut _41: u32;
++     let mut _42: &mut {async fn body of double()};
+      scope 1 {
+-         debug sync_int => _3;
++         debug sync_int => (((*_42) as variant#6).1: SyncInt);
++         coroutine debug async_int => _s2;
+          let _4: AsyncInt;
+          scope 2 {
+-             debug async_int => _4;
++             debug async_int => (((*_42) as variant#6).2: AsyncInt);
++             coroutine debug async_int_again => _s3;
+              let _5: AsyncInt;
+              scope 3 {
+-                 debug async_int_again => _5;
++                 debug async_int_again => (((*_42) as variant#4).3: AsyncInt);
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = SyncInt(const 0_i32);
+-         StorageLive(_4);
+-         _4 = AsyncInt(const 0_i32);
+-         StorageLive(_5);
+-         _5 = AsyncInt(const 0_i32);
+-         _0 = const ();
+-         goto -> bb33;
++         _42 = copy (_1.0: &mut {async fn body of double()});
++         _41 = discriminant((*_42));
++         switchInt(move _41) -> [0: bb42, 1: bb41, 2: bb40, 3: bb36, 4: bb37, 5: bb38, 6: bb39, otherwise: bb13];
+      }
+  
+      bb1: {
+-         StorageDead(_5);
+-         goto -> bb53;
++         nop;
++         goto -> bb33;
+      }
+  
+      bb2: {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb3, unwind: bb11];
++         nop;
++         drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb3, unwind: bb7];
+      }
+  
+      bb3: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb4, unwind: bb12];
++         nop;
++         goto -> bb34;
+      }
+  
+      bb4: {
++         _0 = Poll::<()>::Ready(move (((*_42) as variant#6).0: ()));
++         discriminant((*_42)) = 1;
+          return;
+      }
+  
+-     bb5: {
+-         StorageDead(_5);
+-         goto -> bb6;
++     bb5 (cleanup): {
++         nop;
++         drop((((*_42) as variant#6).2: AsyncInt)) -> [return: bb6, unwind terminate(cleanup)];
+      }
+  
+-     bb6: {
+-         StorageDead(_4);
+-         goto -> bb7;
++     bb6 (cleanup): {
++         nop;
++         drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb7, unwind terminate(cleanup)];
+      }
+  
+-     bb7: {
+-         StorageDead(_3);
++     bb7 (cleanup): {
++         nop;
+          goto -> bb8;
+      }
+  
+-     bb8: {
+-         coroutine_drop;
++     bb8 (cleanup): {
++         goto -> bb35;
+      }
+  
+-     bb9 (cleanup): {
+-         StorageDead(_5);
+-         drop(_4) -> [return: bb10, unwind terminate(cleanup)];
++     bb9: {
++         nop;
++         goto -> bb1;
+      }
+  
+      bb10 (cleanup): {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb11, unwind terminate(cleanup)];
++         nop;
++         goto -> bb5;
+      }
+  
+-     bb11 (cleanup): {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb12, unwind terminate(cleanup)];
++     bb11: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb11, unwind: bb10];
+      }
+  
+-     bb12 (cleanup): {
+-         resume;
++     bb12: {
++         _2 = move _7;
++         StorageDead(_7);
++         goto -> bb11;
+      }
+  
+      bb13: {
+-         StorageDead(_6);
+-         goto -> bb1;
++         unreachable;
+      }
+  
+      bb14: {
+-         StorageDead(_6);
+-         goto -> bb5;
++         _2 = move _14;
++         StorageDead(_14);
++         goto -> bb19;
+      }
+  
+-     bb15 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb9;
++     bb15: {
++         StorageLive(_14);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_14);
++         discriminant((*_42)) = 4;
++         return;
+      }
+  
+      bb16: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb16, unwind: bb15];
++         _16 = discriminant(_15);
++         switchInt(move _16) -> [0: bb9, 1: bb15, otherwise: bb13];
+      }
+  
+      bb17: {
+-         _2 = move _7;
+-         StorageDead(_7);
+-         goto -> bb16;
++         _15 = <impl Future<Output = ()> as Future>::poll(move _17, move _18) -> [return: bb16, unwind: bb10];
+      }
+  
+      bb18: {
+-         _2 = move _7;
+-         StorageDead(_7);
+-         goto -> bb24;
++         _19 = move _2;
++         _18 = move _19;
++         goto -> bb17;
+      }
+  
+      bb19: {
+-         StorageLive(_7);
+-         _7 = yield(const ()) -> [resume: bb17, drop: bb18];
++         _20 = &mut (((*_42) as variant#4).4: impl std::future::Future<Output = ()>);
++         _17 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _20) -> [return: bb18, unwind: bb10];
+      }
+  
+      bb20: {
+-         unreachable;
++         nop;
++         (((*_42) as variant#4).4: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_21.0: &mut AsyncInt)) -> [return: bb19, unwind: bb10];
+      }
+  
+      bb21: {
+-         _9 = discriminant(_8);
+-         switchInt(move _9) -> [0: bb14, 1: bb19, otherwise: bb20];
++         _22 = &mut (((*_42) as variant#4).3: AsyncInt);
++         _21 = Pin::<&mut AsyncInt>::new_unchecked(move _22) -> [return: bb20, unwind: bb5];
+      }
+  
+      bb22: {
+-         _8 = <impl Future<Output = ()> as Future>::poll(move _10, move _11) -> [return: bb21, unwind: bb15];
++         nop;
++         goto -> bb2;
+      }
+  
+-     bb23: {
+-         _12 = move _2;
+-         _11 = std::future::get_context::<'_, '_>(move _12) -> [return: bb22, unwind: bb15];
++     bb23 (cleanup): {
++         nop;
++         goto -> bb6;
+      }
+  
+      bb24: {
+-         _13 = &mut _6;
+-         _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _13) -> [return: bb23, unwind: bb15];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb24, unwind: bb23];
+      }
+  
+      bb25: {
+-         _2 = move _14;
+-         StorageDead(_14);
+-         goto -> bb31;
++         _2 = move _24;
++         StorageDead(_24);
++         goto -> bb24;
+      }
+  
+      bb26: {
+-         _2 = move _14;
+-         StorageDead(_14);
+-         goto -> bb24;
++         _2 = move _31;
++         StorageDead(_31);
++         goto -> bb31;
+      }
+  
+      bb27: {
+-         StorageLive(_14);
+-         _14 = yield(const ()) -> [resume: bb25, drop: bb26];
++         StorageLive(_31);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_31);
++         discriminant((*_42)) = 6;
++         return;
+      }
+  
+      bb28: {
+-         _16 = discriminant(_15);
+-         switchInt(move _16) -> [0: bb13, 1: bb27, otherwise: bb20];
++         _33 = discriminant(_32);
++         switchInt(move _33) -> [0: bb22, 1: bb27, otherwise: bb13];
+      }
+  
+      bb29: {
+-         _15 = <impl Future<Output = ()> as Future>::poll(move _17, move _18) -> [return: bb28, unwind: bb15];
++         _32 = <impl Future<Output = ()> as Future>::poll(move _34, move _35) -> [return: bb28, unwind: bb23];
+      }
+  
+      bb30: {
+-         _19 = move _2;
+-         _18 = std::future::get_context::<'_, '_>(move _19) -> [return: bb29, unwind: bb15];
++         _36 = move _2;
++         _35 = move _36;
++         goto -> bb29;
+      }
+  
+      bb31: {
+-         _20 = &mut _6;
+-         _17 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _20) -> [return: bb30, unwind: bb15];
++         _37 = &mut (((*_42) as variant#6).3: impl std::future::Future<Output = ()>);
++         _34 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _37) -> [return: bb30, unwind: bb23];
+      }
+  
+      bb32: {
+-         StorageLive(_6);
+-         _6 = async_drop_in_place::<AsyncInt>(copy (_21.0: &mut AsyncInt)) -> [return: bb31, unwind: bb15];
++         nop;
++         (((*_42) as variant#6).3: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_38.0: &mut AsyncInt)) -> [return: bb31, unwind: bb23];
+      }
+  
+      bb33: {
+-         _22 = &mut _5;
+-         _21 = Pin::<&mut AsyncInt>::new_unchecked(move _22) -> [return: bb32, unwind: bb9];
++         _39 = &mut (((*_42) as variant#6).2: AsyncInt);
++         _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb32, unwind: bb6];
+      }
+  
+      bb34: {
+-         StorageDead(_23);
+-         goto -> bb2;
++         goto -> bb4;
+      }
+  
+-     bb35: {
+-         StorageDead(_23);
+-         goto -> bb6;
++     bb35 (cleanup): {
++         discriminant((*_42)) = 2;
++         resume;
+      }
+  
+-     bb36 (cleanup): {
+-         StorageDead(_23);
+-         goto -> bb10;
++     bb36: {
++         StorageLive(_7);
++         _7 = move _2;
++         goto -> bb12;
+      }
+  
+      bb37: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb37, unwind: bb36];
++         StorageLive(_14);
++         _14 = move _2;
++         goto -> bb14;
+      }
+  
+      bb38: {
+-         _2 = move _24;
+-         StorageDead(_24);
+-         goto -> bb37;
++         StorageLive(_24);
++         _24 = move _2;
++         goto -> bb25;
+      }
+  
+      bb39: {
+-         _2 = move _24;
+-         StorageDead(_24);
+-         goto -> bb44;
++         StorageLive(_31);
++         _31 = move _2;
++         goto -> bb26;
+      }
+  
+      bb40: {
+-         StorageLive(_24);
+-         _24 = yield(const ()) -> [resume: bb38, drop: bb39];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb40, unwind continue];
+      }
+  
+      bb41: {
+-         _26 = discriminant(_25);
+-         switchInt(move _26) -> [0: bb35, 1: bb40, otherwise: bb20];
++         assert(const false, "`async fn` resumed after completion") -> [success: bb41, unwind continue];
+      }
+  
+      bb42: {
+-         _25 = <impl Future<Output = ()> as Future>::poll(move _27, move _28) -> [return: bb41, unwind: bb36];
+-     }
+- 
+-     bb43: {
+-         _29 = move _2;
+-         _28 = std::future::get_context::<'_, '_>(move _29) -> [return: bb42, unwind: bb36];
+-     }
+- 
+-     bb44: {
+-         _30 = &mut _23;
+-         _27 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _30) -> [return: bb43, unwind: bb36];
+-     }
+- 
+-     bb45: {
+-         _2 = move _31;
+-         StorageDead(_31);
+-         goto -> bb51;
+-     }
+- 
+-     bb46: {
+-         _2 = move _31;
+-         StorageDead(_31);
+-         goto -> bb44;
+-     }
+- 
+-     bb47: {
+-         StorageLive(_31);
+-         _31 = yield(const ()) -> [resume: bb45, drop: bb46];
+-     }
+- 
+-     bb48: {
+-         _33 = discriminant(_32);
+-         switchInt(move _33) -> [0: bb34, 1: bb47, otherwise: bb20];
+-     }
+- 
+-     bb49: {
+-         _32 = <impl Future<Output = ()> as Future>::poll(move _34, move _35) -> [return: bb48, unwind: bb36];
+-     }
+- 
+-     bb50: {
+-         _36 = move _2;
+-         _35 = std::future::get_context::<'_, '_>(move _36) -> [return: bb49, unwind: bb36];
+-     }
+- 
+-     bb51: {
+-         _37 = &mut _23;
+-         _34 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _37) -> [return: bb50, unwind: bb36];
+-     }
+- 
+-     bb52: {
+-         StorageLive(_23);
+-         _23 = async_drop_in_place::<AsyncInt>(copy (_38.0: &mut AsyncInt)) -> [return: bb51, unwind: bb36];
+-     }
+- 
+-     bb53: {
+-         _39 = &mut _4;
+-         _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb52, unwind: bb10];
++         nop;
++         (((*_42) as variant#6).1: SyncInt) = SyncInt(const 0_i32);
++         nop;
++         (((*_42) as variant#6).2: AsyncInt) = AsyncInt(const 0_i32);
++         nop;
++         (((*_42) as variant#4).3: AsyncInt) = AsyncInt(const 0_i32);
++         (((*_42) as variant#6).0: ()) = const ();
++         goto -> bb21;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.coroutine_drop_async.0.mir" "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.coroutine_drop_async.0.mir"
new file mode 100644
index 0000000..acd0228
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.double-\173closure\0430\175.coroutine_drop_async.0.mir"
@@ -0,0 +1,255 @@
+// MIR for `double::{closure#0}` 0 coroutine_drop_async
+
+fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _2;
+    let mut _0: std::task::Poll<()>;
+    let _3: SyncInt;
+    let mut _6: impl std::future::Future<Output = ()>;
+    let mut _7: &mut std::task::Context<'_>;
+    let mut _8: std::task::Poll<()>;
+    let mut _9: isize;
+    let mut _10: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _11: &mut std::task::Context<'_>;
+    let mut _12: &mut std::task::Context<'_>;
+    let mut _13: &mut impl std::future::Future<Output = ()>;
+    let mut _14: &mut std::task::Context<'_>;
+    let mut _15: std::task::Poll<()>;
+    let mut _16: isize;
+    let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: &mut impl std::future::Future<Output = ()>;
+    let mut _21: std::pin::Pin<&mut AsyncInt>;
+    let mut _22: &mut AsyncInt;
+    let mut _23: impl std::future::Future<Output = ()>;
+    let mut _24: &mut std::task::Context<'_>;
+    let mut _25: std::task::Poll<()>;
+    let mut _26: isize;
+    let mut _27: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _28: &mut std::task::Context<'_>;
+    let mut _29: &mut std::task::Context<'_>;
+    let mut _30: &mut impl std::future::Future<Output = ()>;
+    let mut _31: &mut std::task::Context<'_>;
+    let mut _32: std::task::Poll<()>;
+    let mut _33: isize;
+    let mut _34: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _35: &mut std::task::Context<'_>;
+    let mut _36: &mut std::task::Context<'_>;
+    let mut _37: &mut impl std::future::Future<Output = ()>;
+    let mut _38: std::pin::Pin<&mut AsyncInt>;
+    let mut _39: &mut AsyncInt;
+    let mut _40: ();
+    let mut _41: u32;
+    let mut _42: &mut {async fn body of double()};
+    scope 1 {
+        debug sync_int => (((*_42) as variant#6).1: SyncInt);
+        let _4: AsyncInt;
+        scope 2 {
+            debug async_int => (((*_42) as variant#6).2: AsyncInt);
+            let _5: AsyncInt;
+            scope 3 {
+                debug async_int_again => (((*_42) as variant#4).3: AsyncInt);
+            }
+        }
+    }
+
+    bb0: {
+        _42 = copy (_1.0: &mut {async fn body of double()});
+        _41 = discriminant((*_42));
+        switchInt(move _41) -> [0: bb29, 2: bb36, 3: bb32, 4: bb33, 5: bb34, 6: bb35, otherwise: bb37];
+    }
+
+    bb1: {
+        nop;
+        goto -> bb2;
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        nop;
+        goto -> bb4;
+    }
+
+    bb4: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb5 (cleanup): {
+        nop;
+        drop((((*_42) as variant#6).2: AsyncInt)) -> [return: bb6, unwind terminate(cleanup)];
+    }
+
+    bb6 (cleanup): {
+        nop;
+        drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb7, unwind terminate(cleanup)];
+    }
+
+    bb7 (cleanup): {
+        nop;
+        goto -> bb8;
+    }
+
+    bb8 (cleanup): {
+        goto -> bb31;
+    }
+
+    bb9: {
+        nop;
+        goto -> bb1;
+    }
+
+    bb10 (cleanup): {
+        nop;
+        goto -> bb5;
+    }
+
+    bb11: {
+        _2 = move _7;
+        StorageDead(_7);
+        goto -> bb17;
+    }
+
+    bb12: {
+        StorageLive(_7);
+        _0 = Poll::<()>::Pending;
+        StorageDead(_7);
+        discriminant((*_42)) = 3;
+        return;
+    }
+
+    bb13: {
+        unreachable;
+    }
+
+    bb14: {
+        _9 = discriminant(_8);
+        switchInt(move _9) -> [0: bb9, 1: bb12, otherwise: bb13];
+    }
+
+    bb15: {
+        _8 = <impl Future<Output = ()> as Future>::poll(move _10, move _11) -> [return: bb14, unwind: bb10];
+    }
+
+    bb16: {
+        _12 = move _2;
+        _11 = move _12;
+        goto -> bb15;
+    }
+
+    bb17: {
+        _13 = &mut (((*_42) as variant#4).4: impl std::future::Future<Output = ()>);
+        _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _13) -> [return: bb16, unwind: bb10];
+    }
+
+    bb18: {
+        _2 = move _14;
+        StorageDead(_14);
+        goto -> bb17;
+    }
+
+    bb19: {
+        nop;
+        goto -> bb2;
+    }
+
+    bb20 (cleanup): {
+        nop;
+        goto -> bb6;
+    }
+
+    bb21: {
+        _2 = move _24;
+        StorageDead(_24);
+        goto -> bb26;
+    }
+
+    bb22: {
+        StorageLive(_24);
+        _0 = Poll::<()>::Pending;
+        StorageDead(_24);
+        discriminant((*_42)) = 5;
+        return;
+    }
+
+    bb23: {
+        _26 = discriminant(_25);
+        switchInt(move _26) -> [0: bb19, 1: bb22, otherwise: bb13];
+    }
+
+    bb24: {
+        _25 = <impl Future<Output = ()> as Future>::poll(move _27, move _28) -> [return: bb23, unwind: bb20];
+    }
+
+    bb25: {
+        _29 = move _2;
+        _28 = move _29;
+        goto -> bb24;
+    }
+
+    bb26: {
+        _30 = &mut (((*_42) as variant#6).3: impl std::future::Future<Output = ()>);
+        _27 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _30) -> [return: bb25, unwind: bb20];
+    }
+
+    bb27: {
+        _2 = move _31;
+        StorageDead(_31);
+        goto -> bb26;
+    }
+
+    bb28: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb29: {
+        goto -> bb30;
+    }
+
+    bb30: {
+        goto -> bb28;
+    }
+
+    bb31 (cleanup): {
+        discriminant((*_42)) = 2;
+        resume;
+    }
+
+    bb32: {
+        StorageLive(_7);
+        _7 = move _2;
+        goto -> bb11;
+    }
+
+    bb33: {
+        StorageLive(_14);
+        _14 = move _2;
+        goto -> bb18;
+    }
+
+    bb34: {
+        StorageLive(_24);
+        _24 = move _2;
+        goto -> bb21;
+    }
+
+    bb35: {
+        StorageLive(_31);
+        _31 = move _2;
+        goto -> bb27;
+    }
+
+    bb36: {
+        assert(const false, "`async fn` resumed after panicking") -> [success: bb36, unwind continue];
+    }
+
+    bb37: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.ElaborateDrops.diff" "b/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.ElaborateDrops.diff"
new file mode 100644
index 0000000..dd65409
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.ElaborateDrops.diff"
@@ -0,0 +1,1657 @@
+- // MIR for `elaborate_drops::{closure#0}` before ElaborateDrops
++ // MIR for `elaborate_drops::{closure#0}` after ElaborateDrops
+  
+  fn elaborate_drops::{closure#0}(_1: {async fn body of elaborate_drops()}, _2: std::future::ResumeTy) -> ()
+  yields ()
+   {
+      debug _task_context => _2;
+      let mut _0: ();
+      let _3: SyncInt;
+      let mut _6: AsyncInt;
+      let mut _7: AsyncInt;
+      let mut _9: AsyncInt;
+      let mut _10: AsyncInt;
+      let mut _12: AsyncInt;
+      let mut _13: SyncInt;
+      let mut _14: AsyncInt;
+      let mut _16: AsyncInt;
+      let mut _18: AsyncInt;
+      let mut _21: &AsyncInt;
+      let _22: &AsyncInt;
++     let mut _27: impl std::future::Future<Output = ()>;
++     let mut _28: std::future::ResumeTy;
++     let mut _29: std::task::Poll<()>;
++     let mut _30: isize;
++     let mut _31: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _32: &mut std::task::Context<'_>;
++     let mut _33: std::future::ResumeTy;
++     let mut _34: &mut impl std::future::Future<Output = ()>;
++     let mut _35: std::future::ResumeTy;
++     let mut _36: std::task::Poll<()>;
++     let mut _37: isize;
++     let mut _38: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _39: &mut std::task::Context<'_>;
++     let mut _40: std::future::ResumeTy;
++     let mut _41: &mut impl std::future::Future<Output = ()>;
++     let mut _42: std::pin::Pin<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>;
++     let mut _43: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35};
++     let mut _44: impl std::future::Future<Output = ()>;
++     let mut _45: std::future::ResumeTy;
++     let mut _46: std::task::Poll<()>;
++     let mut _47: isize;
++     let mut _48: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _49: &mut std::task::Context<'_>;
++     let mut _50: std::future::ResumeTy;
++     let mut _51: &mut impl std::future::Future<Output = ()>;
++     let mut _52: std::future::ResumeTy;
++     let mut _53: std::task::Poll<()>;
++     let mut _54: isize;
++     let mut _55: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _56: &mut std::task::Context<'_>;
++     let mut _57: std::future::ResumeTy;
++     let mut _58: &mut impl std::future::Future<Output = ()>;
++     let mut _59: std::pin::Pin<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>;
++     let mut _60: &mut {closure@$DIR/async_drop.rs:70:25: 70:27};
++     let mut _61: impl std::future::Future<Output = ()>;
++     let mut _62: std::future::ResumeTy;
++     let mut _63: std::task::Poll<()>;
++     let mut _64: isize;
++     let mut _65: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _66: &mut std::task::Context<'_>;
++     let mut _67: std::future::ResumeTy;
++     let mut _68: &mut impl std::future::Future<Output = ()>;
++     let mut _69: std::future::ResumeTy;
++     let mut _70: std::task::Poll<()>;
++     let mut _71: isize;
++     let mut _72: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _73: &mut std::task::Context<'_>;
++     let mut _74: std::future::ResumeTy;
++     let mut _75: &mut impl std::future::Future<Output = ()>;
++     let mut _76: std::pin::Pin<&mut AsyncReference<'_>>;
++     let mut _77: &mut AsyncReference<'_>;
++     let mut _78: impl std::future::Future<Output = ()>;
++     let mut _79: std::future::ResumeTy;
++     let mut _80: std::task::Poll<()>;
++     let mut _81: isize;
++     let mut _82: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _83: &mut std::task::Context<'_>;
++     let mut _84: std::future::ResumeTy;
++     let mut _85: &mut impl std::future::Future<Output = ()>;
++     let mut _86: std::future::ResumeTy;
++     let mut _87: std::task::Poll<()>;
++     let mut _88: isize;
++     let mut _89: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _90: &mut std::task::Context<'_>;
++     let mut _91: std::future::ResumeTy;
++     let mut _92: &mut impl std::future::Future<Output = ()>;
++     let mut _93: std::pin::Pin<&mut AsyncInt>;
++     let mut _94: &mut AsyncInt;
++     let mut _95: impl std::future::Future<Output = ()>;
++     let mut _96: std::future::ResumeTy;
++     let mut _97: std::task::Poll<()>;
++     let mut _98: isize;
++     let mut _99: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _100: &mut std::task::Context<'_>;
++     let mut _101: std::future::ResumeTy;
++     let mut _102: &mut impl std::future::Future<Output = ()>;
++     let mut _103: std::future::ResumeTy;
++     let mut _104: std::task::Poll<()>;
++     let mut _105: isize;
++     let mut _106: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _107: &mut std::task::Context<'_>;
++     let mut _108: std::future::ResumeTy;
++     let mut _109: &mut impl std::future::Future<Output = ()>;
++     let mut _110: std::pin::Pin<&mut AsyncEnum>;
++     let mut _111: &mut AsyncEnum;
++     let mut _112: impl std::future::Future<Output = ()>;
++     let mut _113: std::future::ResumeTy;
++     let mut _114: std::task::Poll<()>;
++     let mut _115: isize;
++     let mut _116: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _117: &mut std::task::Context<'_>;
++     let mut _118: std::future::ResumeTy;
++     let mut _119: &mut impl std::future::Future<Output = ()>;
++     let mut _120: std::future::ResumeTy;
++     let mut _121: std::task::Poll<()>;
++     let mut _122: isize;
++     let mut _123: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _124: &mut std::task::Context<'_>;
++     let mut _125: std::future::ResumeTy;
++     let mut _126: &mut impl std::future::Future<Output = ()>;
++     let mut _127: std::pin::Pin<&mut SyncThenAsync>;
++     let mut _128: &mut SyncThenAsync;
++     let mut _129: impl std::future::Future<Output = ()>;
++     let mut _130: std::future::ResumeTy;
++     let mut _131: std::task::Poll<()>;
++     let mut _132: isize;
++     let mut _133: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _134: &mut std::task::Context<'_>;
++     let mut _135: std::future::ResumeTy;
++     let mut _136: &mut impl std::future::Future<Output = ()>;
++     let mut _137: std::future::ResumeTy;
++     let mut _138: std::task::Poll<()>;
++     let mut _139: isize;
++     let mut _140: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _141: &mut std::task::Context<'_>;
++     let mut _142: std::future::ResumeTy;
++     let mut _143: &mut impl std::future::Future<Output = ()>;
++     let mut _144: std::pin::Pin<&mut AsyncStruct>;
++     let mut _145: &mut AsyncStruct;
++     let mut _146: impl std::future::Future<Output = ()>;
++     let mut _147: std::future::ResumeTy;
++     let mut _148: std::task::Poll<()>;
++     let mut _149: isize;
++     let mut _150: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _151: &mut std::task::Context<'_>;
++     let mut _152: std::future::ResumeTy;
++     let mut _153: &mut impl std::future::Future<Output = ()>;
++     let mut _154: std::future::ResumeTy;
++     let mut _155: std::task::Poll<()>;
++     let mut _156: isize;
++     let mut _157: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _158: &mut std::task::Context<'_>;
++     let mut _159: std::future::ResumeTy;
++     let mut _160: &mut impl std::future::Future<Output = ()>;
++     let mut _161: std::pin::Pin<&mut [AsyncInt; 2]>;
++     let mut _162: &mut [AsyncInt; 2];
++     let mut _163: impl std::future::Future<Output = ()>;
++     let mut _164: std::future::ResumeTy;
++     let mut _165: std::task::Poll<()>;
++     let mut _166: isize;
++     let mut _167: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _168: &mut std::task::Context<'_>;
++     let mut _169: std::future::ResumeTy;
++     let mut _170: &mut impl std::future::Future<Output = ()>;
++     let mut _171: std::future::ResumeTy;
++     let mut _172: std::task::Poll<()>;
++     let mut _173: isize;
++     let mut _174: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _175: &mut std::task::Context<'_>;
++     let mut _176: std::future::ResumeTy;
++     let mut _177: &mut impl std::future::Future<Output = ()>;
++     let mut _178: std::pin::Pin<&mut AsyncInt>;
++     let mut _179: &mut AsyncInt;
+      scope 1 {
+          debug sync_int => _3;
+          let _4: AsyncInt;
+          scope 2 {
+              debug async_int => _4;
+              let _5: [AsyncInt; 2];
+              scope 3 {
+                  debug tuple => _5;
+                  let _8: AsyncStruct;
+                  scope 4 {
+                      debug async_struct => _8;
+                      let _11: SyncThenAsync;
+                      scope 5 {
+                          debug async_struct_mix => _11;
+                          let _15: AsyncEnum;
+                          scope 6 {
+                              debug async_enum => _15;
+                              let _17: std::mem::ManuallyDrop<AsyncInt>;
+                              scope 7 {
+                                  debug manually_drop_async_int => _17;
+                                  let _19: AsyncInt;
+                                  scope 8 {
+                                      debug foo => _19;
+                                      let _20: AsyncReference<'_>;
+                                      scope 9 {
+                                          debug async_ref => _20;
+                                          let _23: AsyncInt;
+                                          scope 10 {
+                                              debug foo => _23;
+                                              let _24: {closure@$DIR/async_drop.rs:70:25: 70:27};
+                                              scope 11 {
+                                                  debug async_closure => _24;
+                                                  let _25: AsyncInt;
+                                                  scope 12 {
+                                                      debug foo => _25;
+                                                      let _26: {async closure@$DIR/async_drop.rs:78:27: 78:35};
+                                                      scope 13 {
+                                                          debug async_coroutine => _26;
+                                                      }
+                                                  }
+                                              }
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_3);
+          _3 = SyncInt(const 0_i32);
+          StorageLive(_4);
+          _4 = AsyncInt(const 0_i32);
+          StorageLive(_5);
+          StorageLive(_6);
+          _6 = AsyncInt(const 1_i32);
+          StorageLive(_7);
+          _7 = AsyncInt(const 2_i32);
+          _5 = [move _6, move _7];
+-         drop(_7) -> [return: bb1, unwind: bb62, drop: bb38];
++         goto -> bb1;
+      }
+  
+      bb1: {
+          StorageDead(_7);
+-         drop(_6) -> [return: bb2, unwind: bb63, drop: bb39];
++         goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_6);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = AsyncInt(const 5_i32);
+          StorageLive(_10);
+          _10 = AsyncInt(const 4_i32);
+          _8 = AsyncStruct { i: const 3_i32, a: move _10, b: move _9 };
+-         drop(_10) -> [return: bb3, unwind: bb59, drop: bb35];
++         goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_10);
+-         drop(_9) -> [return: bb4, unwind: bb60, drop: bb36];
++         goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_12);
+          _12 = AsyncInt(const 7_i32);
+          StorageLive(_13);
+          _13 = SyncInt(const 8_i32);
+          StorageLive(_14);
+          _14 = AsyncInt(const 9_i32);
+          _11 = SyncThenAsync { i: const 6_i32, a: move _12, b: move _13, c: move _14 };
+-         drop(_14) -> [return: bb5, unwind: bb55, drop: bb31];
++         goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_14);
+-         drop(_13) -> [return: bb6, unwind: bb56];
++         goto -> bb6;
+      }
+  
+      bb6: {
+          StorageDead(_13);
+-         drop(_12) -> [return: bb7, unwind: bb57, drop: bb33];
++         goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_12);
+          StorageLive(_15);
+          StorageLive(_16);
+          _16 = AsyncInt(const 10_i32);
+          _15 = AsyncEnum::A(move _16);
+-         drop(_16) -> [return: bb8, unwind: bb53, drop: bb29];
++         goto -> bb8;
+      }
+  
+      bb8: {
+          StorageDead(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          _18 = AsyncInt(const 11_i32);
+          _17 = ManuallyDrop::<AsyncInt>::new(move _18) -> [return: bb9, unwind: bb50];
+      }
+  
+      bb9: {
+          StorageDead(_18);
+          StorageLive(_19);
+          _19 = AsyncInt(const 12_i32);
+          StorageLive(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          _22 = &_19;
+          _21 = &(*_22);
+          _20 = AsyncReference::<'_> { foo: move _21 };
+          StorageDead(_21);
+          StorageDead(_22);
+          StorageLive(_23);
+          _23 = AsyncInt(const 14_i32);
+          StorageLive(_24);
+          _24 = {closure@$DIR/async_drop.rs:70:25: 70:27} { foo: move _23 };
+          StorageLive(_25);
+          _25 = AsyncInt(const 15_i32);
+          StorageLive(_26);
+          _26 = {closure@$DIR/async_drop.rs:78:27: 78:35} { foo: move _25 };
+          _0 = const ();
+-         drop(_26) -> [return: bb10, unwind: bb44, drop: bb23];
++         goto -> bb103;
+      }
+  
+      bb10: {
+          StorageDead(_26);
+-         drop(_25) -> [return: bb11, unwind: bb45, drop: bb24];
++         goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_25);
+-         drop(_24) -> [return: bb12, unwind: bb46, drop: bb25];
++         goto -> bb123;
+      }
+  
+      bb12: {
+          StorageDead(_24);
+-         drop(_23) -> [return: bb13, unwind: bb47, drop: bb26];
++         goto -> bb13;
+      }
+  
+      bb13: {
+          StorageDead(_23);
+-         drop(_20) -> [return: bb14, unwind: bb48, drop: bb27];
++         goto -> bb143;
+      }
+  
+      bb14: {
+          StorageDead(_20);
+-         drop(_19) -> [return: bb15, unwind: bb49, drop: bb28];
++         goto -> bb163;
+      }
+  
+      bb15: {
+          StorageDead(_19);
+          StorageDead(_17);
+-         drop(_15) -> [return: bb16, unwind: bb54, drop: bb30];
++         goto -> bb183;
+      }
+  
+      bb16: {
+          StorageDead(_15);
+-         drop(_11) -> [return: bb17, unwind: bb58, drop: bb34];
++         goto -> bb203;
+      }
+  
+      bb17: {
+          StorageDead(_11);
+-         drop(_8) -> [return: bb18, unwind: bb61, drop: bb37];
++         goto -> bb223;
+      }
+  
+      bb18: {
+          StorageDead(_8);
+-         drop(_5) -> [return: bb19, unwind: bb64, drop: bb40];
++         goto -> bb243;
+      }
+  
+      bb19: {
+          StorageDead(_5);
+-         drop(_4) -> [return: bb20, unwind: bb65, drop: bb41];
++         goto -> bb263;
+      }
+  
+      bb20: {
+          StorageDead(_4);
+          drop(_3) -> [return: bb21, unwind: bb66];
+      }
+  
+      bb21: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb22, drop: bb43, unwind continue];
++         drop(_1) -> [return: bb22, unwind: bb67];
+      }
+  
+      bb22: {
+          return;
+      }
+  
+      bb23: {
+          StorageDead(_26);
+-         drop(_25) -> [return: bb24, unwind: bb68];
++         goto -> bb24;
+      }
+  
+      bb24: {
+          StorageDead(_25);
+-         drop(_24) -> [return: bb25, unwind: bb69];
++         goto -> bb25;
+      }
+  
+      bb25: {
+          StorageDead(_24);
+-         drop(_23) -> [return: bb26, unwind: bb70];
++         goto -> bb26;
+      }
+  
+      bb26: {
+          StorageDead(_23);
+-         drop(_20) -> [return: bb27, unwind: bb71];
++         goto -> bb27;
+      }
+  
+      bb27: {
+          StorageDead(_20);
+-         drop(_19) -> [return: bb28, unwind: bb72];
++         goto -> bb28;
+      }
+  
+      bb28: {
+          StorageDead(_19);
+          StorageDead(_17);
+-         drop(_15) -> [return: bb30, unwind: bb73];
++         goto -> bb30;
+      }
+  
+      bb29: {
+          StorageDead(_16);
+          goto -> bb30;
+      }
+  
+      bb30: {
+          StorageDead(_15);
+-         drop(_11) -> [return: bb34, unwind: bb76];
++         goto -> bb34;
+      }
+  
+      bb31: {
+          StorageDead(_14);
+-         drop(_13) -> [return: bb32, unwind: bb74];
++         goto -> bb32;
+      }
+  
+      bb32: {
+          StorageDead(_13);
+-         drop(_12) -> [return: bb33, unwind: bb75];
++         goto -> bb33;
+      }
+  
+      bb33: {
+          StorageDead(_12);
+          goto -> bb34;
+      }
+  
+      bb34: {
+          StorageDead(_11);
+-         drop(_8) -> [return: bb37, unwind: bb78];
++         goto -> bb37;
+      }
+  
+      bb35: {
+          StorageDead(_10);
+-         drop(_9) -> [return: bb36, unwind: bb77];
++         goto -> bb36;
+      }
+  
+      bb36: {
+          StorageDead(_9);
+          goto -> bb37;
+      }
+  
+      bb37: {
+          StorageDead(_8);
+-         drop(_5) -> [return: bb40, unwind: bb80];
++         goto -> bb40;
+      }
+  
+      bb38: {
+          StorageDead(_7);
+-         drop(_6) -> [return: bb39, unwind: bb79];
++         goto -> bb39;
+      }
+  
+      bb39: {
+          StorageDead(_6);
+          goto -> bb40;
+      }
+  
+      bb40: {
+          StorageDead(_5);
+-         drop(_4) -> [return: bb41, unwind: bb81];
++         goto -> bb41;
+      }
+  
+      bb41: {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb42, unwind: bb82];
++         goto -> bb42;
+      }
+  
+      bb42: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb43, unwind continue];
++         goto -> bb43;
+      }
+  
+      bb43: {
+          coroutine_drop;
+      }
+  
+      bb44 (cleanup): {
+          StorageDead(_26);
+-         drop(_25) -> [return: bb45, unwind terminate(cleanup)];
++         goto -> bb45;
+      }
+  
+      bb45 (cleanup): {
+          StorageDead(_25);
+          drop(_24) -> [return: bb46, unwind terminate(cleanup)];
+      }
+  
+      bb46 (cleanup): {
+          StorageDead(_24);
+-         drop(_23) -> [return: bb47, unwind terminate(cleanup)];
++         goto -> bb47;
+      }
+  
+      bb47 (cleanup): {
+          StorageDead(_23);
+          drop(_20) -> [return: bb48, unwind terminate(cleanup)];
+      }
+  
+      bb48 (cleanup): {
+          StorageDead(_20);
+          drop(_19) -> [return: bb49, unwind terminate(cleanup)];
+      }
+  
+      bb49 (cleanup): {
+          StorageDead(_19);
+          goto -> bb52;
+      }
+  
+      bb50 (cleanup): {
+-         drop(_18) -> [return: bb51, unwind terminate(cleanup)];
++         goto -> bb51;
+      }
+  
+      bb51 (cleanup): {
+          StorageDead(_18);
+          goto -> bb52;
+      }
+  
+      bb52 (cleanup): {
+          StorageDead(_17);
+          drop(_15) -> [return: bb54, unwind terminate(cleanup)];
+      }
+  
+      bb53 (cleanup): {
+          StorageDead(_16);
+          goto -> bb54;
+      }
+  
+      bb54 (cleanup): {
+          StorageDead(_15);
+          drop(_11) -> [return: bb58, unwind terminate(cleanup)];
+      }
+  
+      bb55 (cleanup): {
+          StorageDead(_14);
+-         drop(_13) -> [return: bb56, unwind terminate(cleanup)];
++         goto -> bb56;
+      }
+  
+      bb56 (cleanup): {
+          StorageDead(_13);
+-         drop(_12) -> [return: bb57, unwind terminate(cleanup)];
++         goto -> bb57;
+      }
+  
+      bb57 (cleanup): {
+          StorageDead(_12);
+          goto -> bb58;
+      }
+  
+      bb58 (cleanup): {
+          StorageDead(_11);
+          drop(_8) -> [return: bb61, unwind terminate(cleanup)];
+      }
+  
+      bb59 (cleanup): {
+          StorageDead(_10);
+-         drop(_9) -> [return: bb60, unwind terminate(cleanup)];
++         goto -> bb60;
+      }
+  
+      bb60 (cleanup): {
+          StorageDead(_9);
+          goto -> bb61;
+      }
+  
+      bb61 (cleanup): {
+          StorageDead(_8);
+          drop(_5) -> [return: bb64, unwind terminate(cleanup)];
+      }
+  
+      bb62 (cleanup): {
+          StorageDead(_7);
+-         drop(_6) -> [return: bb63, unwind terminate(cleanup)];
++         goto -> bb63;
+      }
+  
+      bb63 (cleanup): {
+          StorageDead(_6);
+          goto -> bb64;
+      }
+  
+      bb64 (cleanup): {
+          StorageDead(_5);
+          drop(_4) -> [return: bb65, unwind terminate(cleanup)];
+      }
+  
+      bb65 (cleanup): {
+          StorageDead(_4);
+          drop(_3) -> [return: bb66, unwind terminate(cleanup)];
+      }
+  
+      bb66 (cleanup): {
+          StorageDead(_3);
+          drop(_1) -> [return: bb67, unwind terminate(cleanup)];
+      }
+  
+      bb67 (cleanup): {
+          resume;
+      }
+  
+      bb68 (cleanup): {
+          StorageDead(_25);
+-         drop(_24) -> [return: bb69, unwind terminate(cleanup)];
++         goto -> bb69;
+      }
+  
+      bb69 (cleanup): {
+          StorageDead(_24);
+-         drop(_23) -> [return: bb70, unwind terminate(cleanup)];
++         goto -> bb70;
+      }
+  
+      bb70 (cleanup): {
+          StorageDead(_23);
+-         drop(_20) -> [return: bb71, unwind terminate(cleanup)];
++         goto -> bb71;
+      }
+  
+      bb71 (cleanup): {
+          StorageDead(_20);
+-         drop(_19) -> [return: bb72, unwind terminate(cleanup)];
++         goto -> bb72;
+      }
+  
+      bb72 (cleanup): {
+          StorageDead(_19);
+          StorageDead(_17);
+-         drop(_15) -> [return: bb73, unwind terminate(cleanup)];
++         goto -> bb73;
+      }
+  
+      bb73 (cleanup): {
+          StorageDead(_15);
+-         drop(_11) -> [return: bb76, unwind terminate(cleanup)];
++         goto -> bb76;
+      }
+  
+      bb74 (cleanup): {
+          StorageDead(_13);
+-         drop(_12) -> [return: bb75, unwind terminate(cleanup)];
++         goto -> bb75;
+      }
+  
+      bb75 (cleanup): {
+          StorageDead(_12);
+          goto -> bb76;
+      }
+  
+      bb76 (cleanup): {
+          StorageDead(_11);
+-         drop(_8) -> [return: bb78, unwind terminate(cleanup)];
++         goto -> bb78;
+      }
+  
+      bb77 (cleanup): {
+          StorageDead(_9);
+          goto -> bb78;
+      }
+  
+      bb78 (cleanup): {
+          StorageDead(_8);
+-         drop(_5) -> [return: bb80, unwind terminate(cleanup)];
++         goto -> bb80;
+      }
+  
+      bb79 (cleanup): {
+          StorageDead(_6);
+          goto -> bb80;
+      }
+  
+      bb80 (cleanup): {
+          StorageDead(_5);
+-         drop(_4) -> [return: bb81, unwind terminate(cleanup)];
++         goto -> bb81;
+      }
+  
+      bb81 (cleanup): {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb82, unwind terminate(cleanup)];
++         goto -> bb82;
+      }
+  
+      bb82 (cleanup): {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb67, unwind terminate(cleanup)];
++         goto -> bb67;
++     }
++ 
++     bb83: {
++         StorageDead(_27);
++         goto -> bb10;
++     }
++ 
++     bb84: {
++         StorageDead(_27);
++         goto -> bb23;
++     }
++ 
++     bb85 (cleanup): {
++         StorageDead(_27);
++         goto -> bb44;
++     }
++ 
++     bb86: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb86, unwind: bb85];
++     }
++ 
++     bb87: {
++         _2 = move _28;
++         StorageDead(_28);
++         goto -> bb86;
++     }
++ 
++     bb88: {
++         _2 = move _28;
++         StorageDead(_28);
++         goto -> bb94;
++     }
++ 
++     bb89: {
++         StorageLive(_28);
++         _28 = yield(const ()) -> [resume: bb87, drop: bb88];
++     }
++ 
++     bb90: {
++         unreachable;
++     }
++ 
++     bb91: {
++         _30 = discriminant(_29);
++         switchInt(move _30) -> [0: bb84, 1: bb89, otherwise: bb90];
++     }
++ 
++     bb92: {
++         _29 = <impl Future<Output = ()> as Future>::poll(move _31, move _32) -> [return: bb91, unwind: bb85];
++     }
++ 
++     bb93: {
++         _33 = move _2;
++         _32 = std::future::get_context::<'_, '_>(move _33) -> [return: bb92, unwind: bb85];
++     }
++ 
++     bb94: {
++         _34 = &mut _27;
++         _31 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _34) -> [return: bb93, unwind: bb85];
++     }
++ 
++     bb95: {
++         _2 = move _35;
++         StorageDead(_35);
++         goto -> bb101;
++     }
++ 
++     bb96: {
++         _2 = move _35;
++         StorageDead(_35);
++         goto -> bb94;
++     }
++ 
++     bb97: {
++         StorageLive(_35);
++         _35 = yield(const ()) -> [resume: bb95, drop: bb96];
++     }
++ 
++     bb98: {
++         _37 = discriminant(_36);
++         switchInt(move _37) -> [0: bb83, 1: bb97, otherwise: bb90];
++     }
++ 
++     bb99: {
++         _36 = <impl Future<Output = ()> as Future>::poll(move _38, move _39) -> [return: bb98, unwind: bb85];
++     }
++ 
++     bb100: {
++         _40 = move _2;
++         _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb99, unwind: bb85];
++     }
++ 
++     bb101: {
++         _41 = &mut _27;
++         _38 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _41) -> [return: bb100, unwind: bb85];
++     }
++ 
++     bb102: {
++         StorageLive(_27);
++         _27 = async_drop_in_place::<{async closure@$DIR/async_drop.rs:78:27: 78:35}>(copy (_42.0: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35})) -> [return: bb101, unwind: bb85];
++     }
++ 
++     bb103: {
++         _43 = &mut _26;
++         _42 = Pin::<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>::new_unchecked(move _43) -> [return: bb102, unwind: bb44];
++     }
++ 
++     bb104: {
++         StorageDead(_44);
++         goto -> bb12;
++     }
++ 
++     bb105: {
++         StorageDead(_44);
++         goto -> bb25;
++     }
++ 
++     bb106 (cleanup): {
++         StorageDead(_44);
++         goto -> bb46;
++     }
++ 
++     bb107: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb107, unwind: bb106];
++     }
++ 
++     bb108: {
++         _2 = move _45;
++         StorageDead(_45);
++         goto -> bb107;
++     }
++ 
++     bb109: {
++         _2 = move _45;
++         StorageDead(_45);
++         goto -> bb114;
++     }
++ 
++     bb110: {
++         StorageLive(_45);
++         _45 = yield(const ()) -> [resume: bb108, drop: bb109];
++     }
++ 
++     bb111: {
++         _47 = discriminant(_46);
++         switchInt(move _47) -> [0: bb105, 1: bb110, otherwise: bb90];
++     }
++ 
++     bb112: {
++         _46 = <impl Future<Output = ()> as Future>::poll(move _48, move _49) -> [return: bb111, unwind: bb106];
++     }
++ 
++     bb113: {
++         _50 = move _2;
++         _49 = std::future::get_context::<'_, '_>(move _50) -> [return: bb112, unwind: bb106];
++     }
++ 
++     bb114: {
++         _51 = &mut _44;
++         _48 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _51) -> [return: bb113, unwind: bb106];
++     }
++ 
++     bb115: {
++         _2 = move _52;
++         StorageDead(_52);
++         goto -> bb121;
++     }
++ 
++     bb116: {
++         _2 = move _52;
++         StorageDead(_52);
++         goto -> bb114;
++     }
++ 
++     bb117: {
++         StorageLive(_52);
++         _52 = yield(const ()) -> [resume: bb115, drop: bb116];
++     }
++ 
++     bb118: {
++         _54 = discriminant(_53);
++         switchInt(move _54) -> [0: bb104, 1: bb117, otherwise: bb90];
++     }
++ 
++     bb119: {
++         _53 = <impl Future<Output = ()> as Future>::poll(move _55, move _56) -> [return: bb118, unwind: bb106];
++     }
++ 
++     bb120: {
++         _57 = move _2;
++         _56 = std::future::get_context::<'_, '_>(move _57) -> [return: bb119, unwind: bb106];
++     }
++ 
++     bb121: {
++         _58 = &mut _44;
++         _55 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _58) -> [return: bb120, unwind: bb106];
++     }
++ 
++     bb122: {
++         StorageLive(_44);
++         _44 = async_drop_in_place::<{closure@$DIR/async_drop.rs:70:25: 70:27}>(copy (_59.0: &mut {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb121, unwind: bb106];
++     }
++ 
++     bb123: {
++         _60 = &mut _24;
++         _59 = Pin::<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>::new_unchecked(move _60) -> [return: bb122, unwind: bb46];
++     }
++ 
++     bb124: {
++         StorageDead(_61);
++         goto -> bb14;
++     }
++ 
++     bb125: {
++         StorageDead(_61);
++         goto -> bb27;
++     }
++ 
++     bb126 (cleanup): {
++         StorageDead(_61);
++         goto -> bb48;
++     }
++ 
++     bb127: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb127, unwind: bb126];
++     }
++ 
++     bb128: {
++         _2 = move _62;
++         StorageDead(_62);
++         goto -> bb127;
++     }
++ 
++     bb129: {
++         _2 = move _62;
++         StorageDead(_62);
++         goto -> bb134;
++     }
++ 
++     bb130: {
++         StorageLive(_62);
++         _62 = yield(const ()) -> [resume: bb128, drop: bb129];
++     }
++ 
++     bb131: {
++         _64 = discriminant(_63);
++         switchInt(move _64) -> [0: bb125, 1: bb130, otherwise: bb90];
++     }
++ 
++     bb132: {
++         _63 = <impl Future<Output = ()> as Future>::poll(move _65, move _66) -> [return: bb131, unwind: bb126];
++     }
++ 
++     bb133: {
++         _67 = move _2;
++         _66 = std::future::get_context::<'_, '_>(move _67) -> [return: bb132, unwind: bb126];
++     }
++ 
++     bb134: {
++         _68 = &mut _61;
++         _65 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _68) -> [return: bb133, unwind: bb126];
++     }
++ 
++     bb135: {
++         _2 = move _69;
++         StorageDead(_69);
++         goto -> bb141;
++     }
++ 
++     bb136: {
++         _2 = move _69;
++         StorageDead(_69);
++         goto -> bb134;
++     }
++ 
++     bb137: {
++         StorageLive(_69);
++         _69 = yield(const ()) -> [resume: bb135, drop: bb136];
++     }
++ 
++     bb138: {
++         _71 = discriminant(_70);
++         switchInt(move _71) -> [0: bb124, 1: bb137, otherwise: bb90];
++     }
++ 
++     bb139: {
++         _70 = <impl Future<Output = ()> as Future>::poll(move _72, move _73) -> [return: bb138, unwind: bb126];
++     }
++ 
++     bb140: {
++         _74 = move _2;
++         _73 = std::future::get_context::<'_, '_>(move _74) -> [return: bb139, unwind: bb126];
++     }
++ 
++     bb141: {
++         _75 = &mut _61;
++         _72 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _75) -> [return: bb140, unwind: bb126];
++     }
++ 
++     bb142: {
++         StorageLive(_61);
++         _61 = async_drop_in_place::<AsyncReference<'_>>(copy (_76.0: &mut AsyncReference<'_>)) -> [return: bb141, unwind: bb126];
++     }
++ 
++     bb143: {
++         _77 = &mut _20;
++         _76 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _77) -> [return: bb142, unwind: bb48];
++     }
++ 
++     bb144: {
++         StorageDead(_78);
++         goto -> bb15;
++     }
++ 
++     bb145: {
++         StorageDead(_78);
++         goto -> bb28;
++     }
++ 
++     bb146 (cleanup): {
++         StorageDead(_78);
++         goto -> bb49;
++     }
++ 
++     bb147: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb147, unwind: bb146];
++     }
++ 
++     bb148: {
++         _2 = move _79;
++         StorageDead(_79);
++         goto -> bb147;
++     }
++ 
++     bb149: {
++         _2 = move _79;
++         StorageDead(_79);
++         goto -> bb154;
++     }
++ 
++     bb150: {
++         StorageLive(_79);
++         _79 = yield(const ()) -> [resume: bb148, drop: bb149];
++     }
++ 
++     bb151: {
++         _81 = discriminant(_80);
++         switchInt(move _81) -> [0: bb145, 1: bb150, otherwise: bb90];
++     }
++ 
++     bb152: {
++         _80 = <impl Future<Output = ()> as Future>::poll(move _82, move _83) -> [return: bb151, unwind: bb146];
++     }
++ 
++     bb153: {
++         _84 = move _2;
++         _83 = std::future::get_context::<'_, '_>(move _84) -> [return: bb152, unwind: bb146];
++     }
++ 
++     bb154: {
++         _85 = &mut _78;
++         _82 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _85) -> [return: bb153, unwind: bb146];
++     }
++ 
++     bb155: {
++         _2 = move _86;
++         StorageDead(_86);
++         goto -> bb161;
++     }
++ 
++     bb156: {
++         _2 = move _86;
++         StorageDead(_86);
++         goto -> bb154;
++     }
++ 
++     bb157: {
++         StorageLive(_86);
++         _86 = yield(const ()) -> [resume: bb155, drop: bb156];
++     }
++ 
++     bb158: {
++         _88 = discriminant(_87);
++         switchInt(move _88) -> [0: bb144, 1: bb157, otherwise: bb90];
++     }
++ 
++     bb159: {
++         _87 = <impl Future<Output = ()> as Future>::poll(move _89, move _90) -> [return: bb158, unwind: bb146];
++     }
++ 
++     bb160: {
++         _91 = move _2;
++         _90 = std::future::get_context::<'_, '_>(move _91) -> [return: bb159, unwind: bb146];
++     }
++ 
++     bb161: {
++         _92 = &mut _78;
++         _89 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _92) -> [return: bb160, unwind: bb146];
++     }
++ 
++     bb162: {
++         StorageLive(_78);
++         _78 = async_drop_in_place::<AsyncInt>(copy (_93.0: &mut AsyncInt)) -> [return: bb161, unwind: bb146];
++     }
++ 
++     bb163: {
++         _94 = &mut _19;
++         _93 = Pin::<&mut AsyncInt>::new_unchecked(move _94) -> [return: bb162, unwind: bb49];
++     }
++ 
++     bb164: {
++         StorageDead(_95);
++         goto -> bb16;
++     }
++ 
++     bb165: {
++         StorageDead(_95);
++         goto -> bb30;
++     }
++ 
++     bb166 (cleanup): {
++         StorageDead(_95);
++         goto -> bb54;
++     }
++ 
++     bb167: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb167, unwind: bb166];
++     }
++ 
++     bb168: {
++         _2 = move _96;
++         StorageDead(_96);
++         goto -> bb167;
++     }
++ 
++     bb169: {
++         _2 = move _96;
++         StorageDead(_96);
++         goto -> bb174;
++     }
++ 
++     bb170: {
++         StorageLive(_96);
++         _96 = yield(const ()) -> [resume: bb168, drop: bb169];
++     }
++ 
++     bb171: {
++         _98 = discriminant(_97);
++         switchInt(move _98) -> [0: bb165, 1: bb170, otherwise: bb90];
++     }
++ 
++     bb172: {
++         _97 = <impl Future<Output = ()> as Future>::poll(move _99, move _100) -> [return: bb171, unwind: bb166];
++     }
++ 
++     bb173: {
++         _101 = move _2;
++         _100 = std::future::get_context::<'_, '_>(move _101) -> [return: bb172, unwind: bb166];
++     }
++ 
++     bb174: {
++         _102 = &mut _95;
++         _99 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _102) -> [return: bb173, unwind: bb166];
++     }
++ 
++     bb175: {
++         _2 = move _103;
++         StorageDead(_103);
++         goto -> bb181;
++     }
++ 
++     bb176: {
++         _2 = move _103;
++         StorageDead(_103);
++         goto -> bb174;
++     }
++ 
++     bb177: {
++         StorageLive(_103);
++         _103 = yield(const ()) -> [resume: bb175, drop: bb176];
++     }
++ 
++     bb178: {
++         _105 = discriminant(_104);
++         switchInt(move _105) -> [0: bb164, 1: bb177, otherwise: bb90];
++     }
++ 
++     bb179: {
++         _104 = <impl Future<Output = ()> as Future>::poll(move _106, move _107) -> [return: bb178, unwind: bb166];
++     }
++ 
++     bb180: {
++         _108 = move _2;
++         _107 = std::future::get_context::<'_, '_>(move _108) -> [return: bb179, unwind: bb166];
++     }
++ 
++     bb181: {
++         _109 = &mut _95;
++         _106 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _109) -> [return: bb180, unwind: bb166];
++     }
++ 
++     bb182: {
++         StorageLive(_95);
++         _95 = async_drop_in_place::<AsyncEnum>(copy (_110.0: &mut AsyncEnum)) -> [return: bb181, unwind: bb166];
++     }
++ 
++     bb183: {
++         _111 = &mut _15;
++         _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb182, unwind: bb54];
++     }
++ 
++     bb184: {
++         StorageDead(_112);
++         goto -> bb17;
++     }
++ 
++     bb185: {
++         StorageDead(_112);
++         goto -> bb34;
++     }
++ 
++     bb186 (cleanup): {
++         StorageDead(_112);
++         goto -> bb58;
++     }
++ 
++     bb187: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb187, unwind: bb186];
++     }
++ 
++     bb188: {
++         _2 = move _113;
++         StorageDead(_113);
++         goto -> bb187;
++     }
++ 
++     bb189: {
++         _2 = move _113;
++         StorageDead(_113);
++         goto -> bb194;
++     }
++ 
++     bb190: {
++         StorageLive(_113);
++         _113 = yield(const ()) -> [resume: bb188, drop: bb189];
++     }
++ 
++     bb191: {
++         _115 = discriminant(_114);
++         switchInt(move _115) -> [0: bb185, 1: bb190, otherwise: bb90];
++     }
++ 
++     bb192: {
++         _114 = <impl Future<Output = ()> as Future>::poll(move _116, move _117) -> [return: bb191, unwind: bb186];
++     }
++ 
++     bb193: {
++         _118 = move _2;
++         _117 = std::future::get_context::<'_, '_>(move _118) -> [return: bb192, unwind: bb186];
++     }
++ 
++     bb194: {
++         _119 = &mut _112;
++         _116 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _119) -> [return: bb193, unwind: bb186];
++     }
++ 
++     bb195: {
++         _2 = move _120;
++         StorageDead(_120);
++         goto -> bb201;
++     }
++ 
++     bb196: {
++         _2 = move _120;
++         StorageDead(_120);
++         goto -> bb194;
++     }
++ 
++     bb197: {
++         StorageLive(_120);
++         _120 = yield(const ()) -> [resume: bb195, drop: bb196];
++     }
++ 
++     bb198: {
++         _122 = discriminant(_121);
++         switchInt(move _122) -> [0: bb184, 1: bb197, otherwise: bb90];
++     }
++ 
++     bb199: {
++         _121 = <impl Future<Output = ()> as Future>::poll(move _123, move _124) -> [return: bb198, unwind: bb186];
++     }
++ 
++     bb200: {
++         _125 = move _2;
++         _124 = std::future::get_context::<'_, '_>(move _125) -> [return: bb199, unwind: bb186];
++     }
++ 
++     bb201: {
++         _126 = &mut _112;
++         _123 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _126) -> [return: bb200, unwind: bb186];
++     }
++ 
++     bb202: {
++         StorageLive(_112);
++         _112 = async_drop_in_place::<SyncThenAsync>(copy (_127.0: &mut SyncThenAsync)) -> [return: bb201, unwind: bb186];
++     }
++ 
++     bb203: {
++         _128 = &mut _11;
++         _127 = Pin::<&mut SyncThenAsync>::new_unchecked(move _128) -> [return: bb202, unwind: bb58];
++     }
++ 
++     bb204: {
++         StorageDead(_129);
++         goto -> bb18;
++     }
++ 
++     bb205: {
++         StorageDead(_129);
++         goto -> bb37;
++     }
++ 
++     bb206 (cleanup): {
++         StorageDead(_129);
++         goto -> bb61;
++     }
++ 
++     bb207: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb207, unwind: bb206];
++     }
++ 
++     bb208: {
++         _2 = move _130;
++         StorageDead(_130);
++         goto -> bb207;
++     }
++ 
++     bb209: {
++         _2 = move _130;
++         StorageDead(_130);
++         goto -> bb214;
++     }
++ 
++     bb210: {
++         StorageLive(_130);
++         _130 = yield(const ()) -> [resume: bb208, drop: bb209];
++     }
++ 
++     bb211: {
++         _132 = discriminant(_131);
++         switchInt(move _132) -> [0: bb205, 1: bb210, otherwise: bb90];
++     }
++ 
++     bb212: {
++         _131 = <impl Future<Output = ()> as Future>::poll(move _133, move _134) -> [return: bb211, unwind: bb206];
++     }
++ 
++     bb213: {
++         _135 = move _2;
++         _134 = std::future::get_context::<'_, '_>(move _135) -> [return: bb212, unwind: bb206];
++     }
++ 
++     bb214: {
++         _136 = &mut _129;
++         _133 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _136) -> [return: bb213, unwind: bb206];
++     }
++ 
++     bb215: {
++         _2 = move _137;
++         StorageDead(_137);
++         goto -> bb221;
++     }
++ 
++     bb216: {
++         _2 = move _137;
++         StorageDead(_137);
++         goto -> bb214;
++     }
++ 
++     bb217: {
++         StorageLive(_137);
++         _137 = yield(const ()) -> [resume: bb215, drop: bb216];
++     }
++ 
++     bb218: {
++         _139 = discriminant(_138);
++         switchInt(move _139) -> [0: bb204, 1: bb217, otherwise: bb90];
++     }
++ 
++     bb219: {
++         _138 = <impl Future<Output = ()> as Future>::poll(move _140, move _141) -> [return: bb218, unwind: bb206];
++     }
++ 
++     bb220: {
++         _142 = move _2;
++         _141 = std::future::get_context::<'_, '_>(move _142) -> [return: bb219, unwind: bb206];
++     }
++ 
++     bb221: {
++         _143 = &mut _129;
++         _140 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _143) -> [return: bb220, unwind: bb206];
++     }
++ 
++     bb222: {
++         StorageLive(_129);
++         _129 = async_drop_in_place::<AsyncStruct>(copy (_144.0: &mut AsyncStruct)) -> [return: bb221, unwind: bb206];
++     }
++ 
++     bb223: {
++         _145 = &mut _8;
++         _144 = Pin::<&mut AsyncStruct>::new_unchecked(move _145) -> [return: bb222, unwind: bb61];
++     }
++ 
++     bb224: {
++         StorageDead(_146);
++         goto -> bb19;
++     }
++ 
++     bb225: {
++         StorageDead(_146);
++         goto -> bb40;
++     }
++ 
++     bb226 (cleanup): {
++         StorageDead(_146);
++         goto -> bb64;
++     }
++ 
++     bb227: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb227, unwind: bb226];
++     }
++ 
++     bb228: {
++         _2 = move _147;
++         StorageDead(_147);
++         goto -> bb227;
++     }
++ 
++     bb229: {
++         _2 = move _147;
++         StorageDead(_147);
++         goto -> bb234;
++     }
++ 
++     bb230: {
++         StorageLive(_147);
++         _147 = yield(const ()) -> [resume: bb228, drop: bb229];
++     }
++ 
++     bb231: {
++         _149 = discriminant(_148);
++         switchInt(move _149) -> [0: bb225, 1: bb230, otherwise: bb90];
++     }
++ 
++     bb232: {
++         _148 = <impl Future<Output = ()> as Future>::poll(move _150, move _151) -> [return: bb231, unwind: bb226];
++     }
++ 
++     bb233: {
++         _152 = move _2;
++         _151 = std::future::get_context::<'_, '_>(move _152) -> [return: bb232, unwind: bb226];
++     }
++ 
++     bb234: {
++         _153 = &mut _146;
++         _150 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _153) -> [return: bb233, unwind: bb226];
++     }
++ 
++     bb235: {
++         _2 = move _154;
++         StorageDead(_154);
++         goto -> bb241;
++     }
++ 
++     bb236: {
++         _2 = move _154;
++         StorageDead(_154);
++         goto -> bb234;
++     }
++ 
++     bb237: {
++         StorageLive(_154);
++         _154 = yield(const ()) -> [resume: bb235, drop: bb236];
++     }
++ 
++     bb238: {
++         _156 = discriminant(_155);
++         switchInt(move _156) -> [0: bb224, 1: bb237, otherwise: bb90];
++     }
++ 
++     bb239: {
++         _155 = <impl Future<Output = ()> as Future>::poll(move _157, move _158) -> [return: bb238, unwind: bb226];
++     }
++ 
++     bb240: {
++         _159 = move _2;
++         _158 = std::future::get_context::<'_, '_>(move _159) -> [return: bb239, unwind: bb226];
++     }
++ 
++     bb241: {
++         _160 = &mut _146;
++         _157 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _160) -> [return: bb240, unwind: bb226];
++     }
++ 
++     bb242: {
++         StorageLive(_146);
++         _146 = async_drop_in_place::<[AsyncInt; 2]>(copy (_161.0: &mut [AsyncInt; 2])) -> [return: bb241, unwind: bb226];
++     }
++ 
++     bb243: {
++         _162 = &mut _5;
++         _161 = Pin::<&mut [AsyncInt; 2]>::new_unchecked(move _162) -> [return: bb242, unwind: bb64];
++     }
++ 
++     bb244: {
++         StorageDead(_163);
++         goto -> bb20;
++     }
++ 
++     bb245: {
++         StorageDead(_163);
++         goto -> bb41;
++     }
++ 
++     bb246 (cleanup): {
++         StorageDead(_163);
++         goto -> bb65;
++     }
++ 
++     bb247: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb247, unwind: bb246];
++     }
++ 
++     bb248: {
++         _2 = move _164;
++         StorageDead(_164);
++         goto -> bb247;
++     }
++ 
++     bb249: {
++         _2 = move _164;
++         StorageDead(_164);
++         goto -> bb254;
++     }
++ 
++     bb250: {
++         StorageLive(_164);
++         _164 = yield(const ()) -> [resume: bb248, drop: bb249];
++     }
++ 
++     bb251: {
++         _166 = discriminant(_165);
++         switchInt(move _166) -> [0: bb245, 1: bb250, otherwise: bb90];
++     }
++ 
++     bb252: {
++         _165 = <impl Future<Output = ()> as Future>::poll(move _167, move _168) -> [return: bb251, unwind: bb246];
++     }
++ 
++     bb253: {
++         _169 = move _2;
++         _168 = std::future::get_context::<'_, '_>(move _169) -> [return: bb252, unwind: bb246];
++     }
++ 
++     bb254: {
++         _170 = &mut _163;
++         _167 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _170) -> [return: bb253, unwind: bb246];
++     }
++ 
++     bb255: {
++         _2 = move _171;
++         StorageDead(_171);
++         goto -> bb261;
++     }
++ 
++     bb256: {
++         _2 = move _171;
++         StorageDead(_171);
++         goto -> bb254;
++     }
++ 
++     bb257: {
++         StorageLive(_171);
++         _171 = yield(const ()) -> [resume: bb255, drop: bb256];
++     }
++ 
++     bb258: {
++         _173 = discriminant(_172);
++         switchInt(move _173) -> [0: bb244, 1: bb257, otherwise: bb90];
++     }
++ 
++     bb259: {
++         _172 = <impl Future<Output = ()> as Future>::poll(move _174, move _175) -> [return: bb258, unwind: bb246];
++     }
++ 
++     bb260: {
++         _176 = move _2;
++         _175 = std::future::get_context::<'_, '_>(move _176) -> [return: bb259, unwind: bb246];
++     }
++ 
++     bb261: {
++         _177 = &mut _163;
++         _174 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _177) -> [return: bb260, unwind: bb246];
++     }
++ 
++     bb262: {
++         StorageLive(_163);
++         _163 = async_drop_in_place::<AsyncInt>(copy (_178.0: &mut AsyncInt)) -> [return: bb261, unwind: bb246];
++     }
++ 
++     bb263: {
++         _179 = &mut _4;
++         _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb262, unwind: bb65];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..b0e6100
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.elaborate_drops-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,2004 @@
+- // MIR for `elaborate_drops::{closure#0}` before StateTransform
++ // MIR for `elaborate_drops::{closure#0}` after StateTransform
+  
+- fn elaborate_drops::{closure#0}(_1: {async fn body of elaborate_drops()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn elaborate_drops::{closure#0}(_1: Pin<&mut {async fn body of elaborate_drops()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: ();
++         field _s1: SyncInt;
++         field _s2: AsyncInt;
++         field _s3: [AsyncInt; 2];
++         field _s4: AsyncStruct;
++         field _s5: SyncThenAsync;
++         field _s6: AsyncEnum;
++         field _s7: AsyncInt;
++         field _s8: AsyncReference<'_>;
++         field _s9: {closure@$DIR/async_drop.rs:70:25: 70:27};
++         field _s10: {async closure@$DIR/async_drop.rs:78:27: 78:35};
++         field _s11: impl Future<Output = ()>;
++         field _s12: impl Future<Output = ()>;
++         field _s13: impl Future<Output = ()>;
++         field _s14: impl Future<Output = ()>;
++         field _s15: impl Future<Output = ()>;
++         field _s16: impl Future<Output = ()>;
++         field _s17: impl Future<Output = ()>;
++         field _s18: impl Future<Output = ()>;
++         field _s19: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11],
++             Suspend1 (4): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11],
++             Suspend2 (5): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s12],
++             Suspend3 (6): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s12],
++             Suspend4 (7): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s13],
++             Suspend5 (8): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s13],
++             Suspend6 (9): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s14],
++             Suspend7 (10): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s14],
++             Suspend8 (11): [_s1, _s2, _s3, _s4, _s5, _s6, _s15],
++             Suspend9 (12): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s15],
++             Suspend10(13): [_s1, _s2, _s3, _s4, _s5, _s16],
++             Suspend11(14): [_s0, _s1, _s2, _s3, _s4, _s5, _s16],
++             Suspend12(15): [_s1, _s2, _s3, _s4, _s17],
++             Suspend13(16): [_s0, _s1, _s2, _s3, _s4, _s17],
++             Suspend14(17): [_s1, _s2, _s3, _s18],
++             Suspend15(18): [_s0, _s1, _s2, _s3, _s18],
++             Suspend16(19): [_s1, _s2, _s19],
++             Suspend17(20): [_s0, _s1, _s2, _s19],
++         }
++         storage_conflicts = BitMatrix(20x20) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s0, _s6), (_s0, _s7), (_s0, _s8), (_s0, _s9), (_s0, _s10), (_s0, _s11), (_s0, _s12), (_s0, _s13), (_s0, _s14), (_s0, _s15), (_s0, _s16), (_s0, _s17), (_s0, _s18), (_s0, _s19), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s1, _s5), (_s1, _s6), (_s1, _s7), (_s1, _s8), (_s1, _s9), (_s1, _s10), (_s1, _s11), (_s1, _s12), (_s1, _s13), (_s1, _s14), (_s1, _s15), (_s1, _s16), (_s1, _s17), (_s1, _s18), (_s1, _s19), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s2, _s5), (_s2, _s6), (_s2, _s7), (_s2, _s8), (_s2, _s9), (_s2, _s10), (_s2, _s11), (_s2, _s12), (_s2, _s13), (_s2, _s14), (_s2, _s15), (_s2, _s16), (_s2, _s17), (_s2, _s18), (_s2, _s19), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s3, _s4), (_s3, _s5), (_s3, _s6), (_s3, _s7), (_s3, _s8), (_s3, _s9), (_s3, _s10), (_s3, _s11), (_s3, _s12), (_s3, _s13), (_s3, _s14), (_s3, _s15), (_s3, _s16), (_s3, _s17), (_s3, _s18), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s3), (_s4, _s4), (_s4, _s5), (_s4, _s6), (_s4, _s7), (_s4, _s8), (_s4, _s9), (_s4, _s10), (_s4, _s11), (_s4, _s12), (_s4, _s13), (_s4, _s14), (_s4, _s15), (_s4, _s16), (_s4, _s17), (_s5, _s0), (_s5, _s1), (_s5, _s2), (_s5, _s3), (_s5, _s4), (_s5, _s5), (_s5, _s6), (_s5, _s7), (_s5, _s8), (_s5, _s9), (_s5, _s10), (_s5, _s11), (_s5, _s12), (_s5, _s13), (_s5, _s14), (_s5, _s15), (_s5, _s16), (_s6, _s0), (_s6, _s1), (_s6, _s2), (_s6, _s3), (_s6, _s4), (_s6, _s5), (_s6, _s6), (_s6, _s7), (_s6, _s8), (_s6, _s9), (_s6, _s10), (_s6, _s11), (_s6, _s12), (_s6, _s13), (_s6, _s14), (_s6, _s15), (_s7, _s0), (_s7, _s1), (_s7, _s2), (_s7, _s3), (_s7, _s4), (_s7, _s5), (_s7, _s6), (_s7, _s7), (_s7, _s8), (_s7, _s9), (_s7, _s10), (_s7, _s11), (_s7, _s12), (_s7, _s13), (_s7, _s14), (_s8, _s0), (_s8, _s1), (_s8, _s2), (_s8, _s3), (_s8, _s4), (_s8, _s5), (_s8, _s6), (_s8, _s7), (_s8, _s8), (_s8, _s9), (_s8, _s10), (_s8, _s11), (_s8, _s12), (_s8, _s13), (_s9, _s0), (_s9, _s1), (_s9, _s2), (_s9, _s3), (_s9, _s4), (_s9, _s5), (_s9, _s6), (_s9, _s7), (_s9, _s8), (_s9, _s9), (_s9, _s10), (_s9, _s11), (_s9, _s12), (_s10, _s0), (_s10, _s1), (_s10, _s2), (_s10, _s3), (_s10, _s4), (_s10, _s5), (_s10, _s6), (_s10, _s7), (_s10, _s8), (_s10, _s9), (_s10, _s10), (_s10, _s11), (_s11, _s0), (_s11, _s1), (_s11, _s2), (_s11, _s3), (_s11, _s4), (_s11, _s5), (_s11, _s6), (_s11, _s7), (_s11, _s8), (_s11, _s9), (_s11, _s10), (_s11, _s11), (_s12, _s0), (_s12, _s1), (_s12, _s2), (_s12, _s3), (_s12, _s4), (_s12, _s5), (_s12, _s6), (_s12, _s7), (_s12, _s8), (_s12, _s9), (_s12, _s12), (_s13, _s0), (_s13, _s1), (_s13, _s2), (_s13, _s3), (_s13, _s4), (_s13, _s5), (_s13, _s6), (_s13, _s7), (_s13, _s8), (_s13, _s13), (_s14, _s0), (_s14, _s1), (_s14, _s2), (_s14, _s3), (_s14, _s4), (_s14, _s5), (_s14, _s6), (_s14, _s7), (_s14, _s14), (_s15, _s0), (_s15, _s1), (_s15, _s2), (_s15, _s3), (_s15, _s4), (_s15, _s5), (_s15, _s6), (_s15, _s15), (_s16, _s0), (_s16, _s1), (_s16, _s2), (_s16, _s3), (_s16, _s4), (_s16, _s5), (_s16, _s16), (_s17, _s0), (_s17, _s1), (_s17, _s2), (_s17, _s3), (_s17, _s4), (_s17, _s17), (_s18, _s0), (_s18, _s1), (_s18, _s2), (_s18, _s3), (_s18, _s18), (_s19, _s0), (_s19, _s1), (_s19, _s2), (_s19, _s19)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug sync_int => _s1;
++     let mut _0: std::task::Poll<()>;
+      let _3: SyncInt;
+      let mut _6: AsyncInt;
+      let mut _7: AsyncInt;
+      let mut _9: AsyncInt;
+      let mut _10: AsyncInt;
+      let mut _12: AsyncInt;
+      let mut _13: SyncInt;
+      let mut _14: AsyncInt;
+      let mut _16: AsyncInt;
+      let mut _18: AsyncInt;
+      let mut _21: &AsyncInt;
+      let _22: &AsyncInt;
+      let mut _27: impl std::future::Future<Output = ()>;
+-     let mut _28: std::future::ResumeTy;
++     let mut _28: &mut std::task::Context<'_>;
+      let mut _29: std::task::Poll<()>;
+      let mut _30: isize;
+      let mut _31: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _32: &mut std::task::Context<'_>;
+-     let mut _33: std::future::ResumeTy;
++     let mut _33: &mut std::task::Context<'_>;
+      let mut _34: &mut impl std::future::Future<Output = ()>;
+-     let mut _35: std::future::ResumeTy;
++     let mut _35: &mut std::task::Context<'_>;
+      let mut _36: std::task::Poll<()>;
+      let mut _37: isize;
+      let mut _38: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _39: &mut std::task::Context<'_>;
+-     let mut _40: std::future::ResumeTy;
++     let mut _40: &mut std::task::Context<'_>;
+      let mut _41: &mut impl std::future::Future<Output = ()>;
+      let mut _42: std::pin::Pin<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>;
+      let mut _43: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35};
+      let mut _44: impl std::future::Future<Output = ()>;
+-     let mut _45: std::future::ResumeTy;
++     let mut _45: &mut std::task::Context<'_>;
+      let mut _46: std::task::Poll<()>;
+      let mut _47: isize;
+      let mut _48: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _49: &mut std::task::Context<'_>;
+-     let mut _50: std::future::ResumeTy;
++     let mut _50: &mut std::task::Context<'_>;
+      let mut _51: &mut impl std::future::Future<Output = ()>;
+-     let mut _52: std::future::ResumeTy;
++     let mut _52: &mut std::task::Context<'_>;
+      let mut _53: std::task::Poll<()>;
+      let mut _54: isize;
+      let mut _55: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _56: &mut std::task::Context<'_>;
+-     let mut _57: std::future::ResumeTy;
++     let mut _57: &mut std::task::Context<'_>;
+      let mut _58: &mut impl std::future::Future<Output = ()>;
+      let mut _59: std::pin::Pin<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>;
+      let mut _60: &mut {closure@$DIR/async_drop.rs:70:25: 70:27};
+      let mut _61: impl std::future::Future<Output = ()>;
+-     let mut _62: std::future::ResumeTy;
++     let mut _62: &mut std::task::Context<'_>;
+      let mut _63: std::task::Poll<()>;
+      let mut _64: isize;
+      let mut _65: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _66: &mut std::task::Context<'_>;
+-     let mut _67: std::future::ResumeTy;
++     let mut _67: &mut std::task::Context<'_>;
+      let mut _68: &mut impl std::future::Future<Output = ()>;
+-     let mut _69: std::future::ResumeTy;
++     let mut _69: &mut std::task::Context<'_>;
+      let mut _70: std::task::Poll<()>;
+      let mut _71: isize;
+      let mut _72: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _73: &mut std::task::Context<'_>;
+-     let mut _74: std::future::ResumeTy;
++     let mut _74: &mut std::task::Context<'_>;
+      let mut _75: &mut impl std::future::Future<Output = ()>;
+      let mut _76: std::pin::Pin<&mut AsyncReference<'_>>;
+      let mut _77: &mut AsyncReference<'_>;
+      let mut _78: impl std::future::Future<Output = ()>;
+-     let mut _79: std::future::ResumeTy;
++     let mut _79: &mut std::task::Context<'_>;
+      let mut _80: std::task::Poll<()>;
+      let mut _81: isize;
+      let mut _82: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _83: &mut std::task::Context<'_>;
+-     let mut _84: std::future::ResumeTy;
++     let mut _84: &mut std::task::Context<'_>;
+      let mut _85: &mut impl std::future::Future<Output = ()>;
+-     let mut _86: std::future::ResumeTy;
++     let mut _86: &mut std::task::Context<'_>;
+      let mut _87: std::task::Poll<()>;
+      let mut _88: isize;
+      let mut _89: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _90: &mut std::task::Context<'_>;
+-     let mut _91: std::future::ResumeTy;
++     let mut _91: &mut std::task::Context<'_>;
+      let mut _92: &mut impl std::future::Future<Output = ()>;
+      let mut _93: std::pin::Pin<&mut AsyncInt>;
+      let mut _94: &mut AsyncInt;
+      let mut _95: impl std::future::Future<Output = ()>;
+-     let mut _96: std::future::ResumeTy;
++     let mut _96: &mut std::task::Context<'_>;
+      let mut _97: std::task::Poll<()>;
+      let mut _98: isize;
+      let mut _99: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _100: &mut std::task::Context<'_>;
+-     let mut _101: std::future::ResumeTy;
++     let mut _101: &mut std::task::Context<'_>;
+      let mut _102: &mut impl std::future::Future<Output = ()>;
+-     let mut _103: std::future::ResumeTy;
++     let mut _103: &mut std::task::Context<'_>;
+      let mut _104: std::task::Poll<()>;
+      let mut _105: isize;
+      let mut _106: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _107: &mut std::task::Context<'_>;
+-     let mut _108: std::future::ResumeTy;
++     let mut _108: &mut std::task::Context<'_>;
+      let mut _109: &mut impl std::future::Future<Output = ()>;
+      let mut _110: std::pin::Pin<&mut AsyncEnum>;
+      let mut _111: &mut AsyncEnum;
+      let mut _112: impl std::future::Future<Output = ()>;
+-     let mut _113: std::future::ResumeTy;
++     let mut _113: &mut std::task::Context<'_>;
+      let mut _114: std::task::Poll<()>;
+      let mut _115: isize;
+      let mut _116: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _117: &mut std::task::Context<'_>;
+-     let mut _118: std::future::ResumeTy;
++     let mut _118: &mut std::task::Context<'_>;
+      let mut _119: &mut impl std::future::Future<Output = ()>;
+-     let mut _120: std::future::ResumeTy;
++     let mut _120: &mut std::task::Context<'_>;
+      let mut _121: std::task::Poll<()>;
+      let mut _122: isize;
+      let mut _123: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _124: &mut std::task::Context<'_>;
+-     let mut _125: std::future::ResumeTy;
++     let mut _125: &mut std::task::Context<'_>;
+      let mut _126: &mut impl std::future::Future<Output = ()>;
+      let mut _127: std::pin::Pin<&mut SyncThenAsync>;
+      let mut _128: &mut SyncThenAsync;
+      let mut _129: impl std::future::Future<Output = ()>;
+-     let mut _130: std::future::ResumeTy;
++     let mut _130: &mut std::task::Context<'_>;
+      let mut _131: std::task::Poll<()>;
+      let mut _132: isize;
+      let mut _133: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _134: &mut std::task::Context<'_>;
+-     let mut _135: std::future::ResumeTy;
++     let mut _135: &mut std::task::Context<'_>;
+      let mut _136: &mut impl std::future::Future<Output = ()>;
+-     let mut _137: std::future::ResumeTy;
++     let mut _137: &mut std::task::Context<'_>;
+      let mut _138: std::task::Poll<()>;
+      let mut _139: isize;
+      let mut _140: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _141: &mut std::task::Context<'_>;
+-     let mut _142: std::future::ResumeTy;
++     let mut _142: &mut std::task::Context<'_>;
+      let mut _143: &mut impl std::future::Future<Output = ()>;
+      let mut _144: std::pin::Pin<&mut AsyncStruct>;
+      let mut _145: &mut AsyncStruct;
+      let mut _146: impl std::future::Future<Output = ()>;
+-     let mut _147: std::future::ResumeTy;
++     let mut _147: &mut std::task::Context<'_>;
+      let mut _148: std::task::Poll<()>;
+      let mut _149: isize;
+      let mut _150: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _151: &mut std::task::Context<'_>;
+-     let mut _152: std::future::ResumeTy;
++     let mut _152: &mut std::task::Context<'_>;
+      let mut _153: &mut impl std::future::Future<Output = ()>;
+-     let mut _154: std::future::ResumeTy;
++     let mut _154: &mut std::task::Context<'_>;
+      let mut _155: std::task::Poll<()>;
+      let mut _156: isize;
+      let mut _157: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _158: &mut std::task::Context<'_>;
+-     let mut _159: std::future::ResumeTy;
++     let mut _159: &mut std::task::Context<'_>;
+      let mut _160: &mut impl std::future::Future<Output = ()>;
+      let mut _161: std::pin::Pin<&mut [AsyncInt; 2]>;
+      let mut _162: &mut [AsyncInt; 2];
+      let mut _163: impl std::future::Future<Output = ()>;
+-     let mut _164: std::future::ResumeTy;
++     let mut _164: &mut std::task::Context<'_>;
+      let mut _165: std::task::Poll<()>;
+      let mut _166: isize;
+      let mut _167: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _168: &mut std::task::Context<'_>;
+-     let mut _169: std::future::ResumeTy;
++     let mut _169: &mut std::task::Context<'_>;
+      let mut _170: &mut impl std::future::Future<Output = ()>;
+-     let mut _171: std::future::ResumeTy;
++     let mut _171: &mut std::task::Context<'_>;
+      let mut _172: std::task::Poll<()>;
+      let mut _173: isize;
+      let mut _174: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _175: &mut std::task::Context<'_>;
+-     let mut _176: std::future::ResumeTy;
++     let mut _176: &mut std::task::Context<'_>;
+      let mut _177: &mut impl std::future::Future<Output = ()>;
+      let mut _178: std::pin::Pin<&mut AsyncInt>;
+      let mut _179: &mut AsyncInt;
++     let mut _180: ();
++     let mut _181: u32;
++     let mut _182: &mut {async fn body of elaborate_drops()};
+      scope 1 {
+-         debug sync_int => _3;
++         debug sync_int => (((*_182) as variant#20).1: SyncInt);
++         coroutine debug async_int => _s2;
+          let _4: AsyncInt;
+          scope 2 {
+-             debug async_int => _4;
++             debug async_int => (((*_182) as variant#20).2: AsyncInt);
++             coroutine debug tuple => _s3;
+              let _5: [AsyncInt; 2];
+              scope 3 {
+-                 debug tuple => _5;
++                 debug tuple => (((*_182) as variant#18).3: [AsyncInt; 2]);
++                 coroutine debug async_struct => _s4;
+                  let _8: AsyncStruct;
+                  scope 4 {
+-                     debug async_struct => _8;
++                     debug async_struct => (((*_182) as variant#16).4: AsyncStruct);
++                     coroutine debug async_struct_mix => _s5;
+                      let _11: SyncThenAsync;
+                      scope 5 {
+-                         debug async_struct_mix => _11;
++                         debug async_struct_mix => (((*_182) as variant#14).5: SyncThenAsync);
++                         coroutine debug async_enum => _s6;
+                          let _15: AsyncEnum;
+                          scope 6 {
+-                             debug async_enum => _15;
++                             debug async_enum => (((*_182) as variant#12).6: AsyncEnum);
+                              let _17: std::mem::ManuallyDrop<AsyncInt>;
+                              scope 7 {
+                                  debug manually_drop_async_int => _17;
++                                 coroutine debug foo => _s7;
+                                  let _19: AsyncInt;
+                                  scope 8 {
+-                                     debug foo => _19;
++                                     debug foo => (((*_182) as variant#10).7: AsyncInt);
++                                     coroutine debug async_ref => _s8;
+                                      let _20: AsyncReference<'_>;
+                                      scope 9 {
+-                                         debug async_ref => _20;
++                                         debug async_ref => (((*_182) as variant#8).8: AsyncReference<'_>);
+                                          let _23: AsyncInt;
+                                          scope 10 {
+                                              debug foo => _23;
++                                             coroutine debug async_closure => _s9;
+                                              let _24: {closure@$DIR/async_drop.rs:70:25: 70:27};
+                                              scope 11 {
+-                                                 debug async_closure => _24;
++                                                 debug async_closure => (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27});
+                                                  let _25: AsyncInt;
+                                                  scope 12 {
+                                                      debug foo => _25;
++                                                     coroutine debug async_coroutine => _s10;
+                                                      let _26: {async closure@$DIR/async_drop.rs:78:27: 78:35};
+                                                      scope 13 {
+-                                                         debug async_coroutine => _26;
++                                                         debug async_coroutine => (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35});
+                                                      }
+                                                  }
+                                              }
+                                          }
+                                      }
+                                  }
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = SyncInt(const 0_i32);
+-         StorageLive(_4);
+-         _4 = AsyncInt(const 0_i32);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = AsyncInt(const 1_i32);
+-         StorageLive(_7);
+-         _7 = AsyncInt(const 2_i32);
+-         _5 = [move _6, move _7];
+-         goto -> bb1;
++         _182 = copy (_1.0: &mut {async fn body of elaborate_drops()});
++         _181 = discriminant((*_182));
++         switchInt(move _181) -> [0: bb170, 1: bb169, 2: bb168, 3: bb150, 4: bb151, 5: bb152, 6: bb153, 7: bb154, 8: bb155, 9: bb156, 10: bb157, 11: bb158, 12: bb159, 13: bb160, 14: bb161, 15: bb162, 16: bb163, 17: bb164, 18: bb165, 19: bb166, 20: bb167, otherwise: bb43];
+      }
+  
+      bb1: {
+          StorageDead(_7);
+          goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_6);
+-         StorageLive(_8);
++         nop;
+          StorageLive(_9);
+          _9 = AsyncInt(const 5_i32);
+          StorageLive(_10);
+          _10 = AsyncInt(const 4_i32);
+-         _8 = AsyncStruct { i: const 3_i32, a: move _10, b: move _9 };
++         (((*_182) as variant#16).4: AsyncStruct) = AsyncStruct { i: const 3_i32, a: move _10, b: move _9 };
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_10);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_9);
+-         StorageLive(_11);
++         nop;
+          StorageLive(_12);
+          _12 = AsyncInt(const 7_i32);
+          StorageLive(_13);
+          _13 = SyncInt(const 8_i32);
+          StorageLive(_14);
+          _14 = AsyncInt(const 9_i32);
+-         _11 = SyncThenAsync { i: const 6_i32, a: move _12, b: move _13, c: move _14 };
++         (((*_182) as variant#14).5: SyncThenAsync) = SyncThenAsync { i: const 6_i32, a: move _12, b: move _13, c: move _14 };
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_14);
+          goto -> bb6;
+      }
+  
+      bb6: {
+          StorageDead(_13);
+          goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_12);
+-         StorageLive(_15);
++         nop;
+          StorageLive(_16);
+          _16 = AsyncInt(const 10_i32);
+-         _15 = AsyncEnum::A(move _16);
++         (((*_182) as variant#12).6: AsyncEnum) = AsyncEnum::A(move _16);
+          goto -> bb8;
+      }
+  
+      bb8: {
+          StorageDead(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          _18 = AsyncInt(const 11_i32);
+-         _17 = ManuallyDrop::<AsyncInt>::new(move _18) -> [return: bb9, unwind: bb42];
++         _17 = ManuallyDrop::<AsyncInt>::new(move _18) -> [return: bb9, unwind: bb29];
+      }
+  
+      bb9: {
+          StorageDead(_18);
+-         StorageLive(_19);
+-         _19 = AsyncInt(const 12_i32);
+-         StorageLive(_20);
++         nop;
++         (((*_182) as variant#10).7: AsyncInt) = AsyncInt(const 12_i32);
++         nop;
+          StorageLive(_21);
+          StorageLive(_22);
+-         _22 = &_19;
++         _22 = &(((*_182) as variant#10).7: AsyncInt);
+          _21 = &(*_22);
+-         _20 = AsyncReference::<'_> { foo: move _21 };
++         (((*_182) as variant#8).8: AsyncReference<'_>) = AsyncReference::<'_> { foo: move _21 };
+          StorageDead(_21);
+          StorageDead(_22);
+          StorageLive(_23);
+          _23 = AsyncInt(const 14_i32);
+-         StorageLive(_24);
+-         _24 = {closure@$DIR/async_drop.rs:70:25: 70:27} { foo: move _23 };
++         nop;
++         (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27}) = {closure@$DIR/async_drop.rs:70:25: 70:27} { foo: move _23 };
+          StorageLive(_25);
+          _25 = AsyncInt(const 15_i32);
+-         StorageLive(_26);
+-         _26 = {closure@$DIR/async_drop.rs:78:27: 78:35} { foo: move _25 };
+-         _0 = const ();
+-         goto -> bb72;
++         nop;
++         (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35}) = {closure@$DIR/async_drop.rs:78:27: 78:35} { foo: move _25 };
++         (((*_182) as variant#20).0: ()) = const ();
++         goto -> bb51;
+      }
+  
+      bb10: {
+-         StorageDead(_26);
++         nop;
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_25);
+-         goto -> bb92;
++         goto -> bb63;
+      }
+  
+      bb12: {
+-         StorageDead(_24);
++         nop;
+          goto -> bb13;
+      }
+  
+      bb13: {
+          StorageDead(_23);
+-         goto -> bb112;
++         goto -> bb75;
+      }
+  
+      bb14: {
+-         StorageDead(_20);
+-         goto -> bb132;
++         nop;
++         goto -> bb87;
+      }
+  
+      bb15: {
+-         StorageDead(_19);
++         nop;
+          StorageDead(_17);
+-         goto -> bb152;
++         goto -> bb99;
+      }
+  
+      bb16: {
+-         StorageDead(_15);
+-         goto -> bb172;
++         nop;
++         goto -> bb111;
+      }
+  
+      bb17: {
+-         StorageDead(_11);
+-         goto -> bb192;
++         nop;
++         goto -> bb123;
+      }
+  
+      bb18: {
+-         StorageDead(_8);
+-         goto -> bb212;
++         nop;
++         goto -> bb135;
+      }
+  
+      bb19: {
+-         StorageDead(_5);
+-         goto -> bb232;
++         nop;
++         goto -> bb147;
+      }
+  
+      bb20: {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb21, unwind: bb50];
++         nop;
++         drop((((*_182) as variant#20).1: SyncInt)) -> [return: bb21, unwind: bb37];
+      }
+  
+      bb21: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb22, unwind: bb51];
++         nop;
++         goto -> bb148;
+      }
+  
+      bb22: {
++         _0 = Poll::<()>::Ready(move (((*_182) as variant#20).0: ()));
++         discriminant((*_182)) = 1;
+          return;
+      }
+  
+-     bb23: {
+-         StorageDead(_26);
++     bb23 (cleanup): {
++         nop;
+          goto -> bb24;
+      }
+  
+-     bb24: {
++     bb24 (cleanup): {
+          StorageDead(_25);
+-         goto -> bb25;
++         drop((((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb25, unwind terminate(cleanup)];
+      }
+  
+-     bb25: {
+-         StorageDead(_24);
++     bb25 (cleanup): {
++         nop;
+          goto -> bb26;
+      }
+  
+-     bb26: {
++     bb26 (cleanup): {
+          StorageDead(_23);
+-         goto -> bb27;
++         drop((((*_182) as variant#8).8: AsyncReference<'_>)) -> [return: bb27, unwind terminate(cleanup)];
+      }
+  
+-     bb27: {
+-         StorageDead(_20);
+-         goto -> bb28;
++     bb27 (cleanup): {
++         nop;
++         drop((((*_182) as variant#10).7: AsyncInt)) -> [return: bb28, unwind terminate(cleanup)];
+      }
+  
+-     bb28: {
+-         StorageDead(_19);
+-         StorageDead(_17);
+-         goto -> bb29;
++     bb28 (cleanup): {
++         nop;
++         goto -> bb31;
+      }
+  
+-     bb29: {
+-         StorageDead(_15);
++     bb29 (cleanup): {
+          goto -> bb30;
+      }
+  
+-     bb30: {
+-         StorageDead(_11);
++     bb30 (cleanup): {
++         StorageDead(_18);
+          goto -> bb31;
+      }
+  
+-     bb31: {
+-         StorageDead(_8);
+-         goto -> bb32;
++     bb31 (cleanup): {
++         StorageDead(_17);
++         drop((((*_182) as variant#12).6: AsyncEnum)) -> [return: bb32, unwind terminate(cleanup)];
+      }
+  
+-     bb32: {
+-         StorageDead(_5);
+-         goto -> bb33;
++     bb32 (cleanup): {
++         nop;
++         drop((((*_182) as variant#14).5: SyncThenAsync)) -> [return: bb33, unwind terminate(cleanup)];
+      }
+  
+-     bb33: {
+-         StorageDead(_4);
+-         goto -> bb34;
++     bb33 (cleanup): {
++         nop;
++         drop((((*_182) as variant#16).4: AsyncStruct)) -> [return: bb34, unwind terminate(cleanup)];
+      }
+  
+-     bb34: {
+-         StorageDead(_3);
+-         goto -> bb35;
++     bb34 (cleanup): {
++         nop;
++         drop((((*_182) as variant#18).3: [AsyncInt; 2])) -> [return: bb35, unwind terminate(cleanup)];
+      }
+  
+-     bb35: {
+-         coroutine_drop;
++     bb35 (cleanup): {
++         nop;
++         drop((((*_182) as variant#20).2: AsyncInt)) -> [return: bb36, unwind terminate(cleanup)];
+      }
+  
+      bb36 (cleanup): {
+-         StorageDead(_26);
+-         goto -> bb37;
++         nop;
++         drop((((*_182) as variant#20).1: SyncInt)) -> [return: bb37, unwind terminate(cleanup)];
+      }
+  
+      bb37 (cleanup): {
+-         StorageDead(_25);
+-         drop(_24) -> [return: bb38, unwind terminate(cleanup)];
++         nop;
++         goto -> bb38;
+      }
+  
+      bb38 (cleanup): {
+-         StorageDead(_24);
+-         goto -> bb39;
++         goto -> bb149;
+      }
+  
+-     bb39 (cleanup): {
+-         StorageDead(_23);
+-         drop(_20) -> [return: bb40, unwind terminate(cleanup)];
++     bb39: {
++         nop;
++         goto -> bb10;
+      }
+  
+      bb40 (cleanup): {
+-         StorageDead(_20);
+-         drop(_19) -> [return: bb41, unwind terminate(cleanup)];
++         nop;
++         goto -> bb23;
+      }
+  
+-     bb41 (cleanup): {
+-         StorageDead(_19);
+-         goto -> bb44;
++     bb41: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb41, unwind: bb40];
+      }
+  
+-     bb42 (cleanup): {
+-         goto -> bb43;
++     bb42: {
++         _2 = move _28;
++         StorageDead(_28);
++         goto -> bb41;
+      }
+  
+-     bb43 (cleanup): {
+-         StorageDead(_18);
+-         goto -> bb44;
++     bb43: {
++         unreachable;
+      }
+  
+-     bb44 (cleanup): {
+-         StorageDead(_17);
+-         drop(_15) -> [return: bb45, unwind terminate(cleanup)];
++     bb44: {
++         _2 = move _35;
++         StorageDead(_35);
++         goto -> bb49;
+      }
+  
+-     bb45 (cleanup): {
+-         StorageDead(_15);
+-         drop(_11) -> [return: bb46, unwind terminate(cleanup)];
++     bb45: {
++         StorageLive(_35);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_17);
++         StorageDead(_23);
++         StorageDead(_25);
++         StorageDead(_35);
++         discriminant((*_182)) = 4;
++         return;
+      }
+  
+-     bb46 (cleanup): {
+-         StorageDead(_11);
+-         drop(_8) -> [return: bb47, unwind terminate(cleanup)];
++     bb46: {
++         _37 = discriminant(_36);
++         switchInt(move _37) -> [0: bb39, 1: bb45, otherwise: bb43];
+      }
+  
+-     bb47 (cleanup): {
+-         StorageDead(_8);
+-         drop(_5) -> [return: bb48, unwind terminate(cleanup)];
++     bb47: {
++         _36 = <impl Future<Output = ()> as Future>::poll(move _38, move _39) -> [return: bb46, unwind: bb40];
+      }
+  
+-     bb48 (cleanup): {
+-         StorageDead(_5);
+-         drop(_4) -> [return: bb49, unwind terminate(cleanup)];
++     bb48: {
++         _40 = move _2;
++         _39 = move _40;
++         goto -> bb47;
+      }
+  
+-     bb49 (cleanup): {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb50, unwind terminate(cleanup)];
++     bb49: {
++         _41 = &mut (((*_182) as variant#4).11: impl std::future::Future<Output = ()>);
++         _38 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _41) -> [return: bb48, unwind: bb40];
+      }
+  
+-     bb50 (cleanup): {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb51, unwind terminate(cleanup)];
++     bb50: {
++         nop;
++         (((*_182) as variant#4).11: impl std::future::Future<Output = ()>) = async_drop_in_place::<{async closure@$DIR/async_drop.rs:78:27: 78:35}>(copy (_42.0: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35})) -> [return: bb49, unwind: bb40];
+      }
+  
+-     bb51 (cleanup): {
+-         resume;
++     bb51: {
++         _43 = &mut (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35});
++         _42 = Pin::<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>::new_unchecked(move _43) -> [return: bb50, unwind: bb23];
+      }
+  
+      bb52: {
+-         StorageDead(_27);
+-         goto -> bb10;
++         nop;
++         goto -> bb12;
+      }
+  
+-     bb53: {
+-         StorageDead(_27);
+-         goto -> bb23;
++     bb53 (cleanup): {
++         nop;
++         goto -> bb25;
+      }
+  
+-     bb54 (cleanup): {
+-         StorageDead(_27);
+-         goto -> bb36;
++     bb54: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb54, unwind: bb53];
+      }
+  
+      bb55: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb55, unwind: bb54];
++         _2 = move _45;
++         StorageDead(_45);
++         goto -> bb54;
+      }
+  
+      bb56: {
+-         _2 = move _28;
+-         StorageDead(_28);
+-         goto -> bb55;
++         _2 = move _52;
++         StorageDead(_52);
++         goto -> bb61;
+      }
+  
+      bb57: {
+-         _2 = move _28;
+-         StorageDead(_28);
+-         goto -> bb63;
++         StorageLive(_52);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_17);
++         StorageDead(_23);
++         StorageDead(_52);
++         discriminant((*_182)) = 6;
++         return;
+      }
+  
+      bb58: {
+-         StorageLive(_28);
+-         _28 = yield(const ()) -> [resume: bb56, drop: bb57];
++         _54 = discriminant(_53);
++         switchInt(move _54) -> [0: bb52, 1: bb57, otherwise: bb43];
+      }
+  
+      bb59: {
+-         unreachable;
++         _53 = <impl Future<Output = ()> as Future>::poll(move _55, move _56) -> [return: bb58, unwind: bb53];
+      }
+  
+      bb60: {
+-         _30 = discriminant(_29);
+-         switchInt(move _30) -> [0: bb53, 1: bb58, otherwise: bb59];
++         _57 = move _2;
++         _56 = move _57;
++         goto -> bb59;
+      }
+  
+      bb61: {
+-         _29 = <impl Future<Output = ()> as Future>::poll(move _31, move _32) -> [return: bb60, unwind: bb54];
++         _58 = &mut (((*_182) as variant#6).10: impl std::future::Future<Output = ()>);
++         _55 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _58) -> [return: bb60, unwind: bb53];
+      }
+  
+      bb62: {
+-         _33 = move _2;
+-         _32 = std::future::get_context::<'_, '_>(move _33) -> [return: bb61, unwind: bb54];
++         nop;
++         (((*_182) as variant#6).10: impl std::future::Future<Output = ()>) = async_drop_in_place::<{closure@$DIR/async_drop.rs:70:25: 70:27}>(copy (_59.0: &mut {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb61, unwind: bb53];
+      }
+  
+      bb63: {
+-         _34 = &mut _27;
+-         _31 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _34) -> [return: bb62, unwind: bb54];
++         _60 = &mut (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27});
++         _59 = Pin::<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>::new_unchecked(move _60) -> [return: bb62, unwind: bb25];
+      }
+  
+      bb64: {
+-         _2 = move _35;
+-         StorageDead(_35);
+-         goto -> bb70;
++         nop;
++         goto -> bb14;
+      }
+  
+-     bb65: {
+-         _2 = move _35;
+-         StorageDead(_35);
+-         goto -> bb63;
++     bb65 (cleanup): {
++         nop;
++         goto -> bb27;
+      }
+  
+      bb66: {
+-         StorageLive(_35);
+-         _35 = yield(const ()) -> [resume: bb64, drop: bb65];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb66, unwind: bb65];
+      }
+  
+      bb67: {
+-         _37 = discriminant(_36);
+-         switchInt(move _37) -> [0: bb52, 1: bb66, otherwise: bb59];
++         _2 = move _62;
++         StorageDead(_62);
++         goto -> bb66;
+      }
+  
+      bb68: {
+-         _36 = <impl Future<Output = ()> as Future>::poll(move _38, move _39) -> [return: bb67, unwind: bb54];
++         _2 = move _69;
++         StorageDead(_69);
++         goto -> bb73;
+      }
+  
+      bb69: {
+-         _40 = move _2;
+-         _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb68, unwind: bb54];
++         StorageLive(_69);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_17);
++         StorageDead(_69);
++         discriminant((*_182)) = 8;
++         return;
+      }
+  
+      bb70: {
+-         _41 = &mut _27;
+-         _38 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _41) -> [return: bb69, unwind: bb54];
++         _71 = discriminant(_70);
++         switchInt(move _71) -> [0: bb64, 1: bb69, otherwise: bb43];
+      }
+  
+      bb71: {
+-         StorageLive(_27);
+-         _27 = async_drop_in_place::<{async closure@$DIR/async_drop.rs:78:27: 78:35}>(copy (_42.0: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35})) -> [return: bb70, unwind: bb54];
++         _70 = <impl Future<Output = ()> as Future>::poll(move _72, move _73) -> [return: bb70, unwind: bb65];
+      }
+  
+      bb72: {
+-         _43 = &mut _26;
+-         _42 = Pin::<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>::new_unchecked(move _43) -> [return: bb71, unwind: bb36];
++         _74 = move _2;
++         _73 = move _74;
++         goto -> bb71;
+      }
+  
+      bb73: {
+-         StorageDead(_44);
+-         goto -> bb12;
++         _75 = &mut (((*_182) as variant#8).9: impl std::future::Future<Output = ()>);
++         _72 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _75) -> [return: bb72, unwind: bb65];
+      }
+  
+      bb74: {
+-         StorageDead(_44);
+-         goto -> bb25;
++         nop;
++         (((*_182) as variant#8).9: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncReference<'_>>(copy (_76.0: &mut AsyncReference<'_>)) -> [return: bb73, unwind: bb65];
+      }
+  
+-     bb75 (cleanup): {
+-         StorageDead(_44);
+-         goto -> bb38;
++     bb75: {
++         _77 = &mut (((*_182) as variant#8).8: AsyncReference<'_>);
++         _76 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _77) -> [return: bb74, unwind: bb27];
+      }
+  
+      bb76: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb76, unwind: bb75];
++         nop;
++         goto -> bb15;
+      }
+  
+-     bb77: {
+-         _2 = move _45;
+-         StorageDead(_45);
+-         goto -> bb76;
++     bb77 (cleanup): {
++         nop;
++         goto -> bb28;
+      }
+  
+      bb78: {
+-         _2 = move _45;
+-         StorageDead(_45);
+-         goto -> bb83;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb78, unwind: bb77];
+      }
+  
+      bb79: {
+-         StorageLive(_45);
+-         _45 = yield(const ()) -> [resume: bb77, drop: bb78];
++         _2 = move _79;
++         StorageDead(_79);
++         goto -> bb78;
+      }
+  
+      bb80: {
+-         _47 = discriminant(_46);
+-         switchInt(move _47) -> [0: bb74, 1: bb79, otherwise: bb59];
++         _2 = move _86;
++         StorageDead(_86);
++         goto -> bb85;
+      }
+  
+      bb81: {
+-         _46 = <impl Future<Output = ()> as Future>::poll(move _48, move _49) -> [return: bb80, unwind: bb75];
++         StorageLive(_86);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_17);
++         StorageDead(_86);
++         discriminant((*_182)) = 10;
++         return;
+      }
+  
+      bb82: {
+-         _50 = move _2;
+-         _49 = std::future::get_context::<'_, '_>(move _50) -> [return: bb81, unwind: bb75];
++         _88 = discriminant(_87);
++         switchInt(move _88) -> [0: bb76, 1: bb81, otherwise: bb43];
+      }
+  
+      bb83: {
+-         _51 = &mut _44;
+-         _48 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _51) -> [return: bb82, unwind: bb75];
++         _87 = <impl Future<Output = ()> as Future>::poll(move _89, move _90) -> [return: bb82, unwind: bb77];
+      }
+  
+      bb84: {
+-         _2 = move _52;
+-         StorageDead(_52);
+-         goto -> bb90;
++         _91 = move _2;
++         _90 = move _91;
++         goto -> bb83;
+      }
+  
+      bb85: {
+-         _2 = move _52;
+-         StorageDead(_52);
+-         goto -> bb83;
++         _92 = &mut (((*_182) as variant#10).8: impl std::future::Future<Output = ()>);
++         _89 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _92) -> [return: bb84, unwind: bb77];
+      }
+  
+      bb86: {
+-         StorageLive(_52);
+-         _52 = yield(const ()) -> [resume: bb84, drop: bb85];
++         nop;
++         (((*_182) as variant#10).8: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_93.0: &mut AsyncInt)) -> [return: bb85, unwind: bb77];
+      }
+  
+      bb87: {
+-         _54 = discriminant(_53);
+-         switchInt(move _54) -> [0: bb73, 1: bb86, otherwise: bb59];
++         _94 = &mut (((*_182) as variant#10).7: AsyncInt);
++         _93 = Pin::<&mut AsyncInt>::new_unchecked(move _94) -> [return: bb86, unwind: bb28];
+      }
+  
+      bb88: {
+-         _53 = <impl Future<Output = ()> as Future>::poll(move _55, move _56) -> [return: bb87, unwind: bb75];
++         nop;
++         goto -> bb16;
+      }
+  
+-     bb89: {
+-         _57 = move _2;
+-         _56 = std::future::get_context::<'_, '_>(move _57) -> [return: bb88, unwind: bb75];
++     bb89 (cleanup): {
++         nop;
++         goto -> bb32;
+      }
+  
+      bb90: {
+-         _58 = &mut _44;
+-         _55 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _58) -> [return: bb89, unwind: bb75];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb90, unwind: bb89];
+      }
+  
+      bb91: {
+-         StorageLive(_44);
+-         _44 = async_drop_in_place::<{closure@$DIR/async_drop.rs:70:25: 70:27}>(copy (_59.0: &mut {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb90, unwind: bb75];
++         _2 = move _96;
++         StorageDead(_96);
++         goto -> bb90;
+      }
+  
+      bb92: {
+-         _60 = &mut _24;
+-         _59 = Pin::<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>::new_unchecked(move _60) -> [return: bb91, unwind: bb38];
++         _2 = move _103;
++         StorageDead(_103);
++         goto -> bb97;
+      }
+  
+      bb93: {
+-         StorageDead(_61);
+-         goto -> bb14;
++         StorageLive(_103);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_103);
++         discriminant((*_182)) = 12;
++         return;
+      }
+  
+      bb94: {
+-         StorageDead(_61);
+-         goto -> bb27;
++         _105 = discriminant(_104);
++         switchInt(move _105) -> [0: bb88, 1: bb93, otherwise: bb43];
+      }
+  
+-     bb95 (cleanup): {
+-         StorageDead(_61);
+-         goto -> bb40;
++     bb95: {
++         _104 = <impl Future<Output = ()> as Future>::poll(move _106, move _107) -> [return: bb94, unwind: bb89];
+      }
+  
+      bb96: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb96, unwind: bb95];
++         _108 = move _2;
++         _107 = move _108;
++         goto -> bb95;
+      }
+  
+      bb97: {
+-         _2 = move _62;
+-         StorageDead(_62);
+-         goto -> bb96;
++         _109 = &mut (((*_182) as variant#12).7: impl std::future::Future<Output = ()>);
++         _106 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _109) -> [return: bb96, unwind: bb89];
+      }
+  
+      bb98: {
+-         _2 = move _62;
+-         StorageDead(_62);
+-         goto -> bb103;
++         nop;
++         (((*_182) as variant#12).7: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncEnum>(copy (_110.0: &mut AsyncEnum)) -> [return: bb97, unwind: bb89];
+      }
+  
+      bb99: {
+-         StorageLive(_62);
+-         _62 = yield(const ()) -> [resume: bb97, drop: bb98];
++         _111 = &mut (((*_182) as variant#12).6: AsyncEnum);
++         _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb98, unwind: bb32];
+      }
+  
+      bb100: {
+-         _64 = discriminant(_63);
+-         switchInt(move _64) -> [0: bb94, 1: bb99, otherwise: bb59];
++         nop;
++         goto -> bb17;
+      }
+  
+-     bb101: {
+-         _63 = <impl Future<Output = ()> as Future>::poll(move _65, move _66) -> [return: bb100, unwind: bb95];
++     bb101 (cleanup): {
++         nop;
++         goto -> bb33;
+      }
+  
+      bb102: {
+-         _67 = move _2;
+-         _66 = std::future::get_context::<'_, '_>(move _67) -> [return: bb101, unwind: bb95];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb102, unwind: bb101];
+      }
+  
+      bb103: {
+-         _68 = &mut _61;
+-         _65 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _68) -> [return: bb102, unwind: bb95];
++         _2 = move _113;
++         StorageDead(_113);
++         goto -> bb102;
+      }
+  
+      bb104: {
+-         _2 = move _69;
+-         StorageDead(_69);
+-         goto -> bb110;
++         _2 = move _120;
++         StorageDead(_120);
++         goto -> bb109;
+      }
+  
+      bb105: {
+-         _2 = move _69;
+-         StorageDead(_69);
+-         goto -> bb103;
++         StorageLive(_120);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_120);
++         discriminant((*_182)) = 14;
++         return;
+      }
+  
+      bb106: {
+-         StorageLive(_69);
+-         _69 = yield(const ()) -> [resume: bb104, drop: bb105];
++         _122 = discriminant(_121);
++         switchInt(move _122) -> [0: bb100, 1: bb105, otherwise: bb43];
+      }
+  
+      bb107: {
+-         _71 = discriminant(_70);
+-         switchInt(move _71) -> [0: bb93, 1: bb106, otherwise: bb59];
++         _121 = <impl Future<Output = ()> as Future>::poll(move _123, move _124) -> [return: bb106, unwind: bb101];
+      }
+  
+      bb108: {
+-         _70 = <impl Future<Output = ()> as Future>::poll(move _72, move _73) -> [return: bb107, unwind: bb95];
++         _125 = move _2;
++         _124 = move _125;
++         goto -> bb107;
+      }
+  
+      bb109: {
+-         _74 = move _2;
+-         _73 = std::future::get_context::<'_, '_>(move _74) -> [return: bb108, unwind: bb95];
++         _126 = &mut (((*_182) as variant#14).6: impl std::future::Future<Output = ()>);
++         _123 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _126) -> [return: bb108, unwind: bb101];
+      }
+  
+      bb110: {
+-         _75 = &mut _61;
+-         _72 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _75) -> [return: bb109, unwind: bb95];
++         nop;
++         (((*_182) as variant#14).6: impl std::future::Future<Output = ()>) = async_drop_in_place::<SyncThenAsync>(copy (_127.0: &mut SyncThenAsync)) -> [return: bb109, unwind: bb101];
+      }
+  
+      bb111: {
+-         StorageLive(_61);
+-         _61 = async_drop_in_place::<AsyncReference<'_>>(copy (_76.0: &mut AsyncReference<'_>)) -> [return: bb110, unwind: bb95];
++         _128 = &mut (((*_182) as variant#14).5: SyncThenAsync);
++         _127 = Pin::<&mut SyncThenAsync>::new_unchecked(move _128) -> [return: bb110, unwind: bb33];
+      }
+  
+      bb112: {
+-         _77 = &mut _20;
+-         _76 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _77) -> [return: bb111, unwind: bb40];
++         nop;
++         goto -> bb18;
+      }
+  
+-     bb113: {
+-         StorageDead(_78);
+-         goto -> bb15;
++     bb113 (cleanup): {
++         nop;
++         goto -> bb34;
+      }
+  
+      bb114: {
+-         StorageDead(_78);
+-         goto -> bb28;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb114, unwind: bb113];
+      }
+  
+-     bb115 (cleanup): {
+-         StorageDead(_78);
+-         goto -> bb41;
++     bb115: {
++         _2 = move _130;
++         StorageDead(_130);
++         goto -> bb114;
+      }
+  
+      bb116: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb116, unwind: bb115];
++         _2 = move _137;
++         StorageDead(_137);
++         goto -> bb121;
+      }
+  
+      bb117: {
+-         _2 = move _79;
+-         StorageDead(_79);
+-         goto -> bb116;
++         StorageLive(_137);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_137);
++         discriminant((*_182)) = 16;
++         return;
+      }
+  
+      bb118: {
+-         _2 = move _79;
+-         StorageDead(_79);
+-         goto -> bb123;
++         _139 = discriminant(_138);
++         switchInt(move _139) -> [0: bb112, 1: bb117, otherwise: bb43];
+      }
+  
+      bb119: {
+-         StorageLive(_79);
+-         _79 = yield(const ()) -> [resume: bb117, drop: bb118];
++         _138 = <impl Future<Output = ()> as Future>::poll(move _140, move _141) -> [return: bb118, unwind: bb113];
+      }
+  
+      bb120: {
+-         _81 = discriminant(_80);
+-         switchInt(move _81) -> [0: bb114, 1: bb119, otherwise: bb59];
++         _142 = move _2;
++         _141 = move _142;
++         goto -> bb119;
+      }
+  
+      bb121: {
+-         _80 = <impl Future<Output = ()> as Future>::poll(move _82, move _83) -> [return: bb120, unwind: bb115];
++         _143 = &mut (((*_182) as variant#16).5: impl std::future::Future<Output = ()>);
++         _140 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _143) -> [return: bb120, unwind: bb113];
+      }
+  
+      bb122: {
+-         _84 = move _2;
+-         _83 = std::future::get_context::<'_, '_>(move _84) -> [return: bb121, unwind: bb115];
++         nop;
++         (((*_182) as variant#16).5: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncStruct>(copy (_144.0: &mut AsyncStruct)) -> [return: bb121, unwind: bb113];
+      }
+  
+      bb123: {
+-         _85 = &mut _78;
+-         _82 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _85) -> [return: bb122, unwind: bb115];
++         _145 = &mut (((*_182) as variant#16).4: AsyncStruct);
++         _144 = Pin::<&mut AsyncStruct>::new_unchecked(move _145) -> [return: bb122, unwind: bb34];
+      }
+  
+      bb124: {
+-         _2 = move _86;
+-         StorageDead(_86);
+-         goto -> bb130;
++         nop;
++         goto -> bb19;
+      }
+  
+-     bb125: {
+-         _2 = move _86;
+-         StorageDead(_86);
+-         goto -> bb123;
++     bb125 (cleanup): {
++         nop;
++         goto -> bb35;
+      }
+  
+      bb126: {
+-         StorageLive(_86);
+-         _86 = yield(const ()) -> [resume: bb124, drop: bb125];
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb126, unwind: bb125];
+      }
+  
+      bb127: {
+-         _88 = discriminant(_87);
+-         switchInt(move _88) -> [0: bb113, 1: bb126, otherwise: bb59];
++         _2 = move _147;
++         StorageDead(_147);
++         goto -> bb126;
+      }
+  
+      bb128: {
+-         _87 = <impl Future<Output = ()> as Future>::poll(move _89, move _90) -> [return: bb127, unwind: bb115];
++         _2 = move _154;
++         StorageDead(_154);
++         goto -> bb133;
+      }
+  
+      bb129: {
+-         _91 = move _2;
+-         _90 = std::future::get_context::<'_, '_>(move _91) -> [return: bb128, unwind: bb115];
++         StorageLive(_154);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_154);
++         discriminant((*_182)) = 18;
++         return;
+      }
+  
+      bb130: {
+-         _92 = &mut _78;
+-         _89 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _92) -> [return: bb129, unwind: bb115];
++         _156 = discriminant(_155);
++         switchInt(move _156) -> [0: bb124, 1: bb129, otherwise: bb43];
+      }
+  
+      bb131: {
+-         StorageLive(_78);
+-         _78 = async_drop_in_place::<AsyncInt>(copy (_93.0: &mut AsyncInt)) -> [return: bb130, unwind: bb115];
++         _155 = <impl Future<Output = ()> as Future>::poll(move _157, move _158) -> [return: bb130, unwind: bb125];
+      }
+  
+      bb132: {
+-         _94 = &mut _19;
+-         _93 = Pin::<&mut AsyncInt>::new_unchecked(move _94) -> [return: bb131, unwind: bb41];
++         _159 = move _2;
++         _158 = move _159;
++         goto -> bb131;
+      }
+  
+      bb133: {
+-         StorageDead(_95);
+-         goto -> bb16;
++         _160 = &mut (((*_182) as variant#18).4: impl std::future::Future<Output = ()>);
++         _157 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _160) -> [return: bb132, unwind: bb125];
+      }
+  
+      bb134: {
+-         StorageDead(_95);
+-         goto -> bb29;
++         nop;
++         (((*_182) as variant#18).4: impl std::future::Future<Output = ()>) = async_drop_in_place::<[AsyncInt; 2]>(copy (_161.0: &mut [AsyncInt; 2])) -> [return: bb133, unwind: bb125];
+      }
+  
+-     bb135 (cleanup): {
+-         StorageDead(_95);
+-         goto -> bb45;
++     bb135: {
++         _162 = &mut (((*_182) as variant#18).3: [AsyncInt; 2]);
++         _161 = Pin::<&mut [AsyncInt; 2]>::new_unchecked(move _162) -> [return: bb134, unwind: bb35];
+      }
+  
+      bb136: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb136, unwind: bb135];
++         nop;
++         goto -> bb20;
+      }
+  
+-     bb137: {
+-         _2 = move _96;
+-         StorageDead(_96);
+-         goto -> bb136;
++     bb137 (cleanup): {
++         nop;
++         goto -> bb36;
+      }
+  
+      bb138: {
+-         _2 = move _96;
+-         StorageDead(_96);
+-         goto -> bb143;
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb138, unwind: bb137];
+      }
+  
+      bb139: {
+-         StorageLive(_96);
+-         _96 = yield(const ()) -> [resume: bb137, drop: bb138];
++         _2 = move _164;
++         StorageDead(_164);
++         goto -> bb138;
+      }
+  
+      bb140: {
+-         _98 = discriminant(_97);
+-         switchInt(move _98) -> [0: bb134, 1: bb139, otherwise: bb59];
++         _2 = move _171;
++         StorageDead(_171);
++         goto -> bb145;
+      }
+  
+      bb141: {
+-         _97 = <impl Future<Output = ()> as Future>::poll(move _99, move _100) -> [return: bb140, unwind: bb135];
++         StorageLive(_171);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_171);
++         discriminant((*_182)) = 20;
++         return;
+      }
+  
+      bb142: {
+-         _101 = move _2;
+-         _100 = std::future::get_context::<'_, '_>(move _101) -> [return: bb141, unwind: bb135];
++         _173 = discriminant(_172);
++         switchInt(move _173) -> [0: bb136, 1: bb141, otherwise: bb43];
+      }
+  
+      bb143: {
+-         _102 = &mut _95;
+-         _99 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _102) -> [return: bb142, unwind: bb135];
++         _172 = <impl Future<Output = ()> as Future>::poll(move _174, move _175) -> [return: bb142, unwind: bb137];
+      }
+  
+      bb144: {
+-         _2 = move _103;
+-         StorageDead(_103);
+-         goto -> bb150;
++         _176 = move _2;
++         _175 = move _176;
++         goto -> bb143;
+      }
+  
+      bb145: {
+-         _2 = move _103;
+-         StorageDead(_103);
+-         goto -> bb143;
++         _177 = &mut (((*_182) as variant#20).3: impl std::future::Future<Output = ()>);
++         _174 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _177) -> [return: bb144, unwind: bb137];
+      }
+  
+      bb146: {
+-         StorageLive(_103);
+-         _103 = yield(const ()) -> [resume: bb144, drop: bb145];
++         nop;
++         (((*_182) as variant#20).3: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_178.0: &mut AsyncInt)) -> [return: bb145, unwind: bb137];
+      }
+  
+      bb147: {
+-         _105 = discriminant(_104);
+-         switchInt(move _105) -> [0: bb133, 1: bb146, otherwise: bb59];
++         _179 = &mut (((*_182) as variant#20).2: AsyncInt);
++         _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb146, unwind: bb36];
+      }
+  
+      bb148: {
+-         _104 = <impl Future<Output = ()> as Future>::poll(move _106, move _107) -> [return: bb147, unwind: bb135];
++         goto -> bb22;
+      }
+  
+-     bb149: {
+-         _108 = move _2;
+-         _107 = std::future::get_context::<'_, '_>(move _108) -> [return: bb148, unwind: bb135];
++     bb149 (cleanup): {
++         discriminant((*_182)) = 2;
++         resume;
+      }
+  
+      bb150: {
+-         _109 = &mut _95;
+-         _106 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _109) -> [return: bb149, unwind: bb135];
++         StorageLive(_17);
++         StorageLive(_23);
++         StorageLive(_25);
++         StorageLive(_28);
++         _28 = move _2;
++         goto -> bb42;
+      }
+  
+      bb151: {
+-         StorageLive(_95);
+-         _95 = async_drop_in_place::<AsyncEnum>(copy (_110.0: &mut AsyncEnum)) -> [return: bb150, unwind: bb135];
++         StorageLive(_17);
++         StorageLive(_23);
++         StorageLive(_25);
++         StorageLive(_35);
++         _35 = move _2;
++         goto -> bb44;
+      }
+  
+      bb152: {
+-         _111 = &mut _15;
+-         _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb151, unwind: bb45];
++         StorageLive(_17);
++         StorageLive(_23);
++         StorageLive(_45);
++         _45 = move _2;
++         goto -> bb55;
+      }
+  
+      bb153: {
+-         StorageDead(_112);
+-         goto -> bb17;
++         StorageLive(_17);
++         StorageLive(_23);
++         StorageLive(_52);
++         _52 = move _2;
++         goto -> bb56;
+      }
+  
+      bb154: {
+-         StorageDead(_112);
+-         goto -> bb30;
++         StorageLive(_17);
++         StorageLive(_62);
++         _62 = move _2;
++         goto -> bb67;
+      }
+  
+-     bb155 (cleanup): {
+-         StorageDead(_112);
+-         goto -> bb46;
++     bb155: {
++         StorageLive(_17);
++         StorageLive(_69);
++         _69 = move _2;
++         goto -> bb68;
+      }
+  
+      bb156: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb156, unwind: bb155];
++         StorageLive(_17);
++         StorageLive(_79);
++         _79 = move _2;
++         goto -> bb79;
+      }
+  
+      bb157: {
+-         _2 = move _113;
+-         StorageDead(_113);
+-         goto -> bb156;
++         StorageLive(_17);
++         StorageLive(_86);
++         _86 = move _2;
++         goto -> bb80;
+      }
+  
+      bb158: {
+-         _2 = move _113;
+-         StorageDead(_113);
+-         goto -> bb163;
++         StorageLive(_96);
++         _96 = move _2;
++         goto -> bb91;
+      }
+  
+      bb159: {
+-         StorageLive(_113);
+-         _113 = yield(const ()) -> [resume: bb157, drop: bb158];
++         StorageLive(_103);
++         _103 = move _2;
++         goto -> bb92;
+      }
+  
+      bb160: {
+-         _115 = discriminant(_114);
+-         switchInt(move _115) -> [0: bb154, 1: bb159, otherwise: bb59];
++         StorageLive(_113);
++         _113 = move _2;
++         goto -> bb103;
+      }
+  
+      bb161: {
+-         _114 = <impl Future<Output = ()> as Future>::poll(move _116, move _117) -> [return: bb160, unwind: bb155];
++         StorageLive(_120);
++         _120 = move _2;
++         goto -> bb104;
+      }
+  
+      bb162: {
+-         _118 = move _2;
+-         _117 = std::future::get_context::<'_, '_>(move _118) -> [return: bb161, unwind: bb155];
++         StorageLive(_130);
++         _130 = move _2;
++         goto -> bb115;
+      }
+  
+      bb163: {
+-         _119 = &mut _112;
+-         _116 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _119) -> [return: bb162, unwind: bb155];
++         StorageLive(_137);
++         _137 = move _2;
++         goto -> bb116;
+      }
+  
+      bb164: {
+-         _2 = move _120;
+-         StorageDead(_120);
+-         goto -> bb170;
++         StorageLive(_147);
++         _147 = move _2;
++         goto -> bb127;
+      }
+  
+      bb165: {
+-         _2 = move _120;
+-         StorageDead(_120);
+-         goto -> bb163;
++         StorageLive(_154);
++         _154 = move _2;
++         goto -> bb128;
+      }
+  
+      bb166: {
+-         StorageLive(_120);
+-         _120 = yield(const ()) -> [resume: bb164, drop: bb165];
++         StorageLive(_164);
++         _164 = move _2;
++         goto -> bb139;
+      }
+  
+      bb167: {
+-         _122 = discriminant(_121);
+-         switchInt(move _122) -> [0: bb153, 1: bb166, otherwise: bb59];
++         StorageLive(_171);
++         _171 = move _2;
++         goto -> bb140;
+      }
+  
+      bb168: {
+-         _121 = <impl Future<Output = ()> as Future>::poll(move _123, move _124) -> [return: bb167, unwind: bb155];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb168, unwind continue];
+      }
+  
+      bb169: {
+-         _125 = move _2;
+-         _124 = std::future::get_context::<'_, '_>(move _125) -> [return: bb168, unwind: bb155];
++         assert(const false, "`async fn` resumed after completion") -> [success: bb169, unwind continue];
+      }
+  
+      bb170: {
+-         _126 = &mut _112;
+-         _123 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _126) -> [return: bb169, unwind: bb155];
+-     }
+- 
+-     bb171: {
+-         StorageLive(_112);
+-         _112 = async_drop_in_place::<SyncThenAsync>(copy (_127.0: &mut SyncThenAsync)) -> [return: bb170, unwind: bb155];
+-     }
+- 
+-     bb172: {
+-         _128 = &mut _11;
+-         _127 = Pin::<&mut SyncThenAsync>::new_unchecked(move _128) -> [return: bb171, unwind: bb46];
+-     }
+- 
+-     bb173: {
+-         StorageDead(_129);
+-         goto -> bb18;
+-     }
+- 
+-     bb174: {
+-         StorageDead(_129);
+-         goto -> bb31;
+-     }
+- 
+-     bb175 (cleanup): {
+-         StorageDead(_129);
+-         goto -> bb47;
+-     }
+- 
+-     bb176: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb176, unwind: bb175];
+-     }
+- 
+-     bb177: {
+-         _2 = move _130;
+-         StorageDead(_130);
+-         goto -> bb176;
+-     }
+- 
+-     bb178: {
+-         _2 = move _130;
+-         StorageDead(_130);
+-         goto -> bb183;
+-     }
+- 
+-     bb179: {
+-         StorageLive(_130);
+-         _130 = yield(const ()) -> [resume: bb177, drop: bb178];
+-     }
+- 
+-     bb180: {
+-         _132 = discriminant(_131);
+-         switchInt(move _132) -> [0: bb174, 1: bb179, otherwise: bb59];
+-     }
+- 
+-     bb181: {
+-         _131 = <impl Future<Output = ()> as Future>::poll(move _133, move _134) -> [return: bb180, unwind: bb175];
+-     }
+- 
+-     bb182: {
+-         _135 = move _2;
+-         _134 = std::future::get_context::<'_, '_>(move _135) -> [return: bb181, unwind: bb175];
+-     }
+- 
+-     bb183: {
+-         _136 = &mut _129;
+-         _133 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _136) -> [return: bb182, unwind: bb175];
+-     }
+- 
+-     bb184: {
+-         _2 = move _137;
+-         StorageDead(_137);
+-         goto -> bb190;
+-     }
+- 
+-     bb185: {
+-         _2 = move _137;
+-         StorageDead(_137);
+-         goto -> bb183;
+-     }
+- 
+-     bb186: {
+-         StorageLive(_137);
+-         _137 = yield(const ()) -> [resume: bb184, drop: bb185];
+-     }
+- 
+-     bb187: {
+-         _139 = discriminant(_138);
+-         switchInt(move _139) -> [0: bb173, 1: bb186, otherwise: bb59];
+-     }
+- 
+-     bb188: {
+-         _138 = <impl Future<Output = ()> as Future>::poll(move _140, move _141) -> [return: bb187, unwind: bb175];
+-     }
+- 
+-     bb189: {
+-         _142 = move _2;
+-         _141 = std::future::get_context::<'_, '_>(move _142) -> [return: bb188, unwind: bb175];
+-     }
+- 
+-     bb190: {
+-         _143 = &mut _129;
+-         _140 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _143) -> [return: bb189, unwind: bb175];
+-     }
+- 
+-     bb191: {
+-         StorageLive(_129);
+-         _129 = async_drop_in_place::<AsyncStruct>(copy (_144.0: &mut AsyncStruct)) -> [return: bb190, unwind: bb175];
+-     }
+- 
+-     bb192: {
+-         _145 = &mut _8;
+-         _144 = Pin::<&mut AsyncStruct>::new_unchecked(move _145) -> [return: bb191, unwind: bb47];
+-     }
+- 
+-     bb193: {
+-         StorageDead(_146);
+-         goto -> bb19;
+-     }
+- 
+-     bb194: {
+-         StorageDead(_146);
+-         goto -> bb32;
+-     }
+- 
+-     bb195 (cleanup): {
+-         StorageDead(_146);
+-         goto -> bb48;
+-     }
+- 
+-     bb196: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb196, unwind: bb195];
+-     }
+- 
+-     bb197: {
+-         _2 = move _147;
+-         StorageDead(_147);
+-         goto -> bb196;
+-     }
+- 
+-     bb198: {
+-         _2 = move _147;
+-         StorageDead(_147);
+-         goto -> bb203;
+-     }
+- 
+-     bb199: {
+-         StorageLive(_147);
+-         _147 = yield(const ()) -> [resume: bb197, drop: bb198];
+-     }
+- 
+-     bb200: {
+-         _149 = discriminant(_148);
+-         switchInt(move _149) -> [0: bb194, 1: bb199, otherwise: bb59];
+-     }
+- 
+-     bb201: {
+-         _148 = <impl Future<Output = ()> as Future>::poll(move _150, move _151) -> [return: bb200, unwind: bb195];
+-     }
+- 
+-     bb202: {
+-         _152 = move _2;
+-         _151 = std::future::get_context::<'_, '_>(move _152) -> [return: bb201, unwind: bb195];
+-     }
+- 
+-     bb203: {
+-         _153 = &mut _146;
+-         _150 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _153) -> [return: bb202, unwind: bb195];
+-     }
+- 
+-     bb204: {
+-         _2 = move _154;
+-         StorageDead(_154);
+-         goto -> bb210;
+-     }
+- 
+-     bb205: {
+-         _2 = move _154;
+-         StorageDead(_154);
+-         goto -> bb203;
+-     }
+- 
+-     bb206: {
+-         StorageLive(_154);
+-         _154 = yield(const ()) -> [resume: bb204, drop: bb205];
+-     }
+- 
+-     bb207: {
+-         _156 = discriminant(_155);
+-         switchInt(move _156) -> [0: bb193, 1: bb206, otherwise: bb59];
+-     }
+- 
+-     bb208: {
+-         _155 = <impl Future<Output = ()> as Future>::poll(move _157, move _158) -> [return: bb207, unwind: bb195];
+-     }
+- 
+-     bb209: {
+-         _159 = move _2;
+-         _158 = std::future::get_context::<'_, '_>(move _159) -> [return: bb208, unwind: bb195];
+-     }
+- 
+-     bb210: {
+-         _160 = &mut _146;
+-         _157 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _160) -> [return: bb209, unwind: bb195];
+-     }
+- 
+-     bb211: {
+-         StorageLive(_146);
+-         _146 = async_drop_in_place::<[AsyncInt; 2]>(copy (_161.0: &mut [AsyncInt; 2])) -> [return: bb210, unwind: bb195];
+-     }
+- 
+-     bb212: {
+-         _162 = &mut _5;
+-         _161 = Pin::<&mut [AsyncInt; 2]>::new_unchecked(move _162) -> [return: bb211, unwind: bb48];
+-     }
+- 
+-     bb213: {
+-         StorageDead(_163);
+-         goto -> bb20;
+-     }
+- 
+-     bb214: {
+-         StorageDead(_163);
+-         goto -> bb33;
+-     }
+- 
+-     bb215 (cleanup): {
+-         StorageDead(_163);
+-         goto -> bb49;
+-     }
+- 
+-     bb216: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb216, unwind: bb215];
+-     }
+- 
+-     bb217: {
+-         _2 = move _164;
+-         StorageDead(_164);
+-         goto -> bb216;
+-     }
+- 
+-     bb218: {
+-         _2 = move _164;
+-         StorageDead(_164);
+-         goto -> bb223;
+-     }
+- 
+-     bb219: {
+-         StorageLive(_164);
+-         _164 = yield(const ()) -> [resume: bb217, drop: bb218];
+-     }
+- 
+-     bb220: {
+-         _166 = discriminant(_165);
+-         switchInt(move _166) -> [0: bb214, 1: bb219, otherwise: bb59];
+-     }
+- 
+-     bb221: {
+-         _165 = <impl Future<Output = ()> as Future>::poll(move _167, move _168) -> [return: bb220, unwind: bb215];
+-     }
+- 
+-     bb222: {
+-         _169 = move _2;
+-         _168 = std::future::get_context::<'_, '_>(move _169) -> [return: bb221, unwind: bb215];
+-     }
+- 
+-     bb223: {
+-         _170 = &mut _163;
+-         _167 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _170) -> [return: bb222, unwind: bb215];
+-     }
+- 
+-     bb224: {
+-         _2 = move _171;
+-         StorageDead(_171);
+-         goto -> bb230;
+-     }
+- 
+-     bb225: {
+-         _2 = move _171;
+-         StorageDead(_171);
+-         goto -> bb223;
+-     }
+- 
+-     bb226: {
+-         StorageLive(_171);
+-         _171 = yield(const ()) -> [resume: bb224, drop: bb225];
+-     }
+- 
+-     bb227: {
+-         _173 = discriminant(_172);
+-         switchInt(move _173) -> [0: bb213, 1: bb226, otherwise: bb59];
+-     }
+- 
+-     bb228: {
+-         _172 = <impl Future<Output = ()> as Future>::poll(move _174, move _175) -> [return: bb227, unwind: bb215];
+-     }
+- 
+-     bb229: {
+-         _176 = move _2;
+-         _175 = std::future::get_context::<'_, '_>(move _176) -> [return: bb228, unwind: bb215];
+-     }
+- 
+-     bb230: {
+-         _177 = &mut _163;
+-         _174 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _177) -> [return: bb229, unwind: bb215];
+-     }
+- 
+-     bb231: {
+-         StorageLive(_163);
+-         _163 = async_drop_in_place::<AsyncInt>(copy (_178.0: &mut AsyncInt)) -> [return: bb230, unwind: bb215];
+-     }
+- 
+-     bb232: {
+-         _179 = &mut _4;
+-         _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb231, unwind: bb49];
++         nop;
++         (((*_182) as variant#20).1: SyncInt) = SyncInt(const 0_i32);
++         nop;
++         (((*_182) as variant#20).2: AsyncInt) = AsyncInt(const 0_i32);
++         nop;
++         StorageLive(_6);
++         _6 = AsyncInt(const 1_i32);
++         StorageLive(_7);
++         _7 = AsyncInt(const 2_i32);
++         (((*_182) as variant#18).3: [AsyncInt; 2]) = [move _6, move _7];
++         goto -> bb1;
+      }
+  }
+  
diff --git a/tests/mir-opt/coroutine/async_drop.rs b/tests/mir-opt/coroutine/async_drop.rs
new file mode 100644
index 0000000..506baac
--- /dev/null
+++ b/tests/mir-opt/coroutine/async_drop.rs
@@ -0,0 +1,258 @@
+//@ skip-filecheck
+//@ compile-flags: -Zmir-opt-level=0
+//@ needs-unwind
+//@ edition: 2024
+
+// WARNING: If you would ever want to modify this test,
+// please consider modifying rustc's async drop test at
+// `tests/ui/async-await/async-drop/async-drop-initial.rs`.
+
+#![feature(async_drop, impl_trait_in_assoc_type)]
+#![allow(incomplete_features, dead_code, unused_variables)]
+
+// FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests
+use core::future::{AsyncDrop, Future, async_drop_in_place};
+use core::hint::black_box;
+use core::mem::{self, ManuallyDrop};
+use core::pin::{Pin, pin};
+use core::task::{Context, Poll, Waker};
+
+async fn test_async_drop<T>(x: T) {
+    let mut x = mem::MaybeUninit::new(x);
+    let dtor = pin!(unsafe { async_drop_in_place(&mut *x.as_mut_ptr()) });
+    test_idempotency(dtor).await;
+}
+
+fn test_idempotency<T>(mut x: Pin<&mut T>) -> impl Future<Output = ()> + '_
+where
+    T: Future<Output = ()>,
+{
+    core::future::poll_fn(move |cx| {
+        assert_eq!(x.as_mut().poll(cx), Poll::Ready(()));
+        assert_eq!(x.as_mut().poll(cx), Poll::Ready(()));
+        Poll::Ready(())
+    })
+}
+
+// EMIT_MIR async_drop.simple-{closure#0}.ElaborateDrops.diff
+// EMIT_MIR async_drop.simple-{closure#0}.StateTransform.diff
+// EMIT_MIR async_drop.simple-{closure#0}.coroutine_drop_async.0.mir
+async fn simple() {
+    let sync_int = SyncInt(0);
+    let async_int = AsyncInt(0);
+}
+
+// EMIT_MIR async_drop.double-{closure#0}.ElaborateDrops.diff
+// EMIT_MIR async_drop.double-{closure#0}.StateTransform.diff
+// EMIT_MIR async_drop.double-{closure#0}.coroutine_drop_async.0.mir
+async fn double() {
+    let sync_int = SyncInt(0);
+    let async_int = AsyncInt(0);
+    let async_int_again = AsyncInt(0);
+}
+
+// EMIT_MIR async_drop.elaborate_drops-{closure#0}.ElaborateDrops.diff
+// EMIT_MIR async_drop.elaborate_drops-{closure#0}.StateTransform.diff
+async fn elaborate_drops() {
+    let sync_int = SyncInt(0);
+    let async_int = AsyncInt(0);
+    let tuple = [AsyncInt(1), AsyncInt(2)];
+
+    let async_struct = AsyncStruct { b: AsyncInt(5), a: AsyncInt(4), i: 3 };
+    let async_struct_mix = SyncThenAsync { i: 6, a: AsyncInt(7), b: SyncInt(8), c: AsyncInt(9) };
+    let async_enum = AsyncEnum::A(AsyncInt(10));
+
+    let manually_drop_async_int = ManuallyDrop::new(AsyncInt(11));
+    let foo = AsyncInt(12);
+    let async_ref = AsyncReference { foo: &foo };
+
+    let foo = AsyncInt(14);
+    let async_closure = || {
+        black_box(foo);
+        let foo = AsyncInt(13);
+        foo
+    };
+
+    // We test dropping the coroutine, not running it.
+    let foo = AsyncInt(15);
+    let async_coroutine = async || {
+        black_box(foo);
+        let foo = AsyncInt(16);
+        // Await point there, but this is async closure so it's fine
+        black_box(core::future::ready(())).await;
+        foo
+    };
+}
+
+fn main() {
+    let waker = Waker::noop();
+    let mut cx = Context::from_waker(&waker);
+
+    let i = 13;
+    let fut = pin!(async {
+        elaborate_drops().await;
+
+        test_async_drop(Int(0)).await;
+        test_async_drop(AsyncInt(0)).await;
+        test_async_drop([AsyncInt(1), AsyncInt(2)]).await;
+        test_async_drop((AsyncInt(3), AsyncInt(4))).await;
+        test_async_drop(5).await;
+        let j = 42;
+        test_async_drop(&i).await;
+        test_async_drop(&j).await;
+        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }).await;
+        test_async_drop(ManuallyDrop::new(AsyncInt(9))).await;
+
+        let foo = AsyncInt(10);
+        test_async_drop(AsyncReference { foo: &foo }).await;
+
+        let foo = AsyncInt(11);
+        test_async_drop(|| {
+            black_box(foo);
+            let foo = AsyncInt(10);
+            foo
+        })
+        .await;
+
+        test_async_drop(AsyncEnum::A(AsyncInt(12))).await;
+        test_async_drop(AsyncEnum::B(SyncInt(13))).await;
+
+        test_async_drop(SyncInt(14)).await;
+        test_async_drop(SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) })
+            .await;
+
+        let mut ptr19 = mem::MaybeUninit::new(AsyncInt(19));
+        let async_drop_fut = pin!(unsafe { async_drop_in_place(&mut *ptr19.as_mut_ptr()) });
+        test_idempotency(async_drop_fut).await;
+
+        let foo = AsyncInt(20);
+        test_async_drop(async || {
+            black_box(foo);
+            let foo = AsyncInt(19);
+            // Await point there, but this is async closure so it's fine
+            black_box(core::future::ready(())).await;
+            foo
+        })
+        .await;
+    });
+    let res = fut.poll(&mut cx);
+    assert_eq!(res, Poll::Ready(()));
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.StateTransform.diff
+struct AsyncInt(i32);
+
+impl Drop for AsyncInt {
+    fn drop(&mut self) {
+        println!("AsyncInt::drop: {}", self.0);
+    }
+}
+impl AsyncDrop for AsyncInt {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncInt::async_drop: {}", self.0);
+    }
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.StateTransform.diff
+struct SyncInt(i32);
+
+impl Drop for SyncInt {
+    fn drop(&mut self) {
+        println!("SyncInt::drop: {}", self.0);
+    }
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.StateTransform.diff
+struct SyncThenAsync {
+    i: i32,
+    a: AsyncInt,
+    b: SyncInt,
+    c: AsyncInt,
+}
+
+impl Drop for SyncThenAsync {
+    fn drop(&mut self) {
+        println!("SyncThenAsync::drop: {}", self.i);
+    }
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.StateTransform.diff
+struct AsyncReference<'a> {
+    foo: &'a AsyncInt,
+}
+
+impl Drop for AsyncReference<'_> {
+    fn drop(&mut self) {
+        println!("AsyncReference::drop: {}", self.foo.0);
+    }
+}
+impl AsyncDrop for AsyncReference<'_> {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncReference::async_drop: {}", self.foo.0);
+    }
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.Int.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.Int.StateTransform.diff
+struct Int(i32);
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.StateTransform.diff
+struct AsyncStruct {
+    i: i32,
+    a: AsyncInt,
+    b: AsyncInt,
+}
+
+impl Drop for AsyncStruct {
+    fn drop(&mut self) {
+        println!("AsyncStruct::drop: {}", self.i);
+    }
+}
+impl AsyncDrop for AsyncStruct {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncStruct::async_drop: {}", self.i);
+    }
+}
+
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir
+// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.StateTransform.diff
+enum AsyncEnum {
+    A(AsyncInt),
+    B(SyncInt),
+}
+
+impl Drop for AsyncEnum {
+    fn drop(&mut self) {
+        let new_self = match self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::drop: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::drop: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
+    }
+}
+impl AsyncDrop for AsyncEnum {
+    async fn drop(mut self: Pin<&mut Self>) {
+        let new_self = match &*self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::async_drop: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::async_drop: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.ElaborateDrops.diff" "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.ElaborateDrops.diff"
new file mode 100644
index 0000000..0e18ddf
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.ElaborateDrops.diff"
@@ -0,0 +1,201 @@
+- // MIR for `simple::{closure#0}` before ElaborateDrops
++ // MIR for `simple::{closure#0}` after ElaborateDrops
+  
+  fn simple::{closure#0}(_1: {async fn body of simple()}, _2: std::future::ResumeTy) -> ()
+  yields ()
+   {
+      debug _task_context => _2;
+      let mut _0: ();
+      let _3: SyncInt;
++     let mut _5: impl std::future::Future<Output = ()>;
++     let mut _6: std::future::ResumeTy;
++     let mut _7: std::task::Poll<()>;
++     let mut _8: isize;
++     let mut _9: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _10: &mut std::task::Context<'_>;
++     let mut _11: std::future::ResumeTy;
++     let mut _12: &mut impl std::future::Future<Output = ()>;
++     let mut _13: std::future::ResumeTy;
++     let mut _14: std::task::Poll<()>;
++     let mut _15: isize;
++     let mut _16: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
++     let mut _17: &mut std::task::Context<'_>;
++     let mut _18: std::future::ResumeTy;
++     let mut _19: &mut impl std::future::Future<Output = ()>;
++     let mut _20: std::pin::Pin<&mut AsyncInt>;
++     let mut _21: &mut AsyncInt;
+      scope 1 {
+          debug sync_int => _3;
+          let _4: AsyncInt;
+          scope 2 {
+              debug async_int => _4;
+          }
+      }
+  
+      bb0: {
+          StorageLive(_3);
+          _3 = SyncInt(const 0_i32);
+          StorageLive(_4);
+          _4 = AsyncInt(const 0_i32);
+          _0 = const ();
+-         drop(_4) -> [return: bb1, unwind: bb7, drop: bb4];
++         goto -> bb31;
+      }
+  
+      bb1: {
+          StorageDead(_4);
+          drop(_3) -> [return: bb2, unwind: bb8];
+      }
+  
+      bb2: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb3, drop: bb6, unwind continue];
++         drop(_1) -> [return: bb3, unwind: bb9];
+      }
+  
+      bb3: {
+          return;
+      }
+  
+      bb4: {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb5, unwind: bb10];
++         goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb6, unwind continue];
++         goto -> bb6;
+      }
+  
+      bb6: {
+          coroutine_drop;
+      }
+  
+      bb7 (cleanup): {
+          StorageDead(_4);
+          drop(_3) -> [return: bb8, unwind terminate(cleanup)];
+      }
+  
+      bb8 (cleanup): {
+          StorageDead(_3);
+          drop(_1) -> [return: bb9, unwind terminate(cleanup)];
+      }
+  
+      bb9 (cleanup): {
+          resume;
+      }
+  
+      bb10 (cleanup): {
+          StorageDead(_3);
+-         drop(_1) -> [return: bb9, unwind terminate(cleanup)];
++         goto -> bb9;
++     }
++ 
++     bb11: {
++         StorageDead(_5);
++         goto -> bb1;
++     }
++ 
++     bb12: {
++         StorageDead(_5);
++         goto -> bb4;
++     }
++ 
++     bb13 (cleanup): {
++         StorageDead(_5);
++         goto -> bb7;
++     }
++ 
++     bb14: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb14, unwind: bb13];
++     }
++ 
++     bb15: {
++         _2 = move _6;
++         StorageDead(_6);
++         goto -> bb14;
++     }
++ 
++     bb16: {
++         _2 = move _6;
++         StorageDead(_6);
++         goto -> bb22;
++     }
++ 
++     bb17: {
++         StorageLive(_6);
++         _6 = yield(const ()) -> [resume: bb15, drop: bb16];
++     }
++ 
++     bb18: {
++         unreachable;
++     }
++ 
++     bb19: {
++         _8 = discriminant(_7);
++         switchInt(move _8) -> [0: bb12, 1: bb17, otherwise: bb18];
++     }
++ 
++     bb20: {
++         _7 = <impl Future<Output = ()> as Future>::poll(move _9, move _10) -> [return: bb19, unwind: bb13];
++     }
++ 
++     bb21: {
++         _11 = move _2;
++         _10 = std::future::get_context::<'_, '_>(move _11) -> [return: bb20, unwind: bb13];
++     }
++ 
++     bb22: {
++         _12 = &mut _5;
++         _9 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _12) -> [return: bb21, unwind: bb13];
++     }
++ 
++     bb23: {
++         _2 = move _13;
++         StorageDead(_13);
++         goto -> bb29;
++     }
++ 
++     bb24: {
++         _2 = move _13;
++         StorageDead(_13);
++         goto -> bb22;
++     }
++ 
++     bb25: {
++         StorageLive(_13);
++         _13 = yield(const ()) -> [resume: bb23, drop: bb24];
++     }
++ 
++     bb26: {
++         _15 = discriminant(_14);
++         switchInt(move _15) -> [0: bb11, 1: bb25, otherwise: bb18];
++     }
++ 
++     bb27: {
++         _14 = <impl Future<Output = ()> as Future>::poll(move _16, move _17) -> [return: bb26, unwind: bb13];
++     }
++ 
++     bb28: {
++         _18 = move _2;
++         _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb27, unwind: bb13];
++     }
++ 
++     bb29: {
++         _19 = &mut _5;
++         _16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _19) -> [return: bb28, unwind: bb13];
++     }
++ 
++     bb30: {
++         StorageLive(_5);
++         _5 = async_drop_in_place::<AsyncInt>(copy (_20.0: &mut AsyncInt)) -> [return: bb29, unwind: bb13];
++     }
++ 
++     bb31: {
++         _21 = &mut _4;
++         _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb30, unwind: bb7];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..0f2b3ab
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,284 @@
+- // MIR for `simple::{closure#0}` before StateTransform
++ // MIR for `simple::{closure#0}` after StateTransform
+  
+- fn simple::{closure#0}(_1: {async fn body of simple()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: ();
++         field _s1: SyncInt;
++         field _s2: AsyncInt;
++         field _s3: impl Future<Output = ()>;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1, _s2, _s3],
++             Suspend1 (4): [_s0, _s1, _s2, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug sync_int => _s1;
++     let mut _0: std::task::Poll<()>;
+      let _3: SyncInt;
+      let mut _5: impl std::future::Future<Output = ()>;
+-     let mut _6: std::future::ResumeTy;
++     let mut _6: &mut std::task::Context<'_>;
+      let mut _7: std::task::Poll<()>;
+      let mut _8: isize;
+      let mut _9: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _10: &mut std::task::Context<'_>;
+-     let mut _11: std::future::ResumeTy;
++     let mut _11: &mut std::task::Context<'_>;
+      let mut _12: &mut impl std::future::Future<Output = ()>;
+-     let mut _13: std::future::ResumeTy;
++     let mut _13: &mut std::task::Context<'_>;
+      let mut _14: std::task::Poll<()>;
+      let mut _15: isize;
+      let mut _16: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+      let mut _17: &mut std::task::Context<'_>;
+-     let mut _18: std::future::ResumeTy;
++     let mut _18: &mut std::task::Context<'_>;
+      let mut _19: &mut impl std::future::Future<Output = ()>;
+      let mut _20: std::pin::Pin<&mut AsyncInt>;
+      let mut _21: &mut AsyncInt;
++     let mut _22: ();
++     let mut _23: u32;
++     let mut _24: &mut {async fn body of simple()};
+      scope 1 {
+-         debug sync_int => _3;
++         debug sync_int => (((*_24) as variant#4).1: SyncInt);
++         coroutine debug async_int => _s2;
+          let _4: AsyncInt;
+          scope 2 {
+-             debug async_int => _4;
++             debug async_int => (((*_24) as variant#4).2: AsyncInt);
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = SyncInt(const 0_i32);
+-         StorageLive(_4);
+-         _4 = AsyncInt(const 0_i32);
+-         _0 = const ();
+-         goto -> bb30;
++         _24 = copy (_1.0: &mut {async fn body of simple()});
++         _23 = discriminant((*_24));
++         switchInt(move _23) -> [0: bb26, 1: bb25, 2: bb24, 3: bb22, 4: bb23, otherwise: bb11];
+      }
+  
+      bb1: {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb2, unwind: bb8];
++         nop;
++         drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb2, unwind: bb5];
+      }
+  
+      bb2: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb3, unwind: bb9];
++         nop;
++         goto -> bb20;
+      }
+  
+      bb3: {
++         _0 = Poll::<()>::Ready(move (((*_24) as variant#4).0: ()));
++         discriminant((*_24)) = 1;
+          return;
+      }
+  
+-     bb4: {
+-         StorageDead(_4);
+-         goto -> bb5;
++     bb4 (cleanup): {
++         nop;
++         drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb5, unwind terminate(cleanup)];
+      }
+  
+-     bb5: {
+-         StorageDead(_3);
++     bb5 (cleanup): {
++         nop;
+          goto -> bb6;
+      }
+  
+-     bb6: {
+-         coroutine_drop;
++     bb6 (cleanup): {
++         goto -> bb21;
+      }
+  
+-     bb7 (cleanup): {
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb8, unwind terminate(cleanup)];
++     bb7: {
++         nop;
++         goto -> bb1;
+      }
+  
+      bb8 (cleanup): {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb9, unwind terminate(cleanup)];
++         nop;
++         goto -> bb4;
+      }
+  
+-     bb9 (cleanup): {
+-         resume;
++     bb9: {
++         assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8];
+      }
+  
+      bb10: {
+-         StorageDead(_5);
+-         goto -> bb1;
++         _2 = move _6;
++         StorageDead(_6);
++         goto -> bb9;
+      }
+  
+      bb11: {
+-         StorageDead(_5);
+-         goto -> bb4;
++         unreachable;
+      }
+  
+-     bb12 (cleanup): {
+-         StorageDead(_5);
+-         goto -> bb7;
++     bb12: {
++         _2 = move _13;
++         StorageDead(_13);
++         goto -> bb17;
+      }
+  
+      bb13: {
+-         assert(const false, "`async fn` resumed after async drop") -> [success: bb13, unwind: bb12];
++         StorageLive(_13);
++         _0 = Poll::<()>::Pending;
++         StorageDead(_13);
++         discriminant((*_24)) = 4;
++         return;
+      }
+  
+      bb14: {
+-         _2 = move _6;
+-         StorageDead(_6);
+-         goto -> bb13;
++         _15 = discriminant(_14);
++         switchInt(move _15) -> [0: bb7, 1: bb13, otherwise: bb11];
+      }
+  
+      bb15: {
+-         _2 = move _6;
+-         StorageDead(_6);
+-         goto -> bb21;
++         _14 = <impl Future<Output = ()> as Future>::poll(move _16, move _17) -> [return: bb14, unwind: bb8];
+      }
+  
+      bb16: {
+-         StorageLive(_6);
+-         _6 = yield(const ()) -> [resume: bb14, drop: bb15];
++         _18 = move _2;
++         _17 = move _18;
++         goto -> bb15;
+      }
+  
+      bb17: {
+-         unreachable;
++         _19 = &mut (((*_24) as variant#4).3: impl std::future::Future<Output = ()>);
++         _16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _19) -> [return: bb16, unwind: bb8];
+      }
+  
+      bb18: {
+-         _8 = discriminant(_7);
+-         switchInt(move _8) -> [0: bb11, 1: bb16, otherwise: bb17];
++         nop;
++         (((*_24) as variant#4).3: impl std::future::Future<Output = ()>) = async_drop_in_place::<AsyncInt>(copy (_20.0: &mut AsyncInt)) -> [return: bb17, unwind: bb8];
+      }
+  
+      bb19: {
+-         _7 = <impl Future<Output = ()> as Future>::poll(move _9, move _10) -> [return: bb18, unwind: bb12];
++         _21 = &mut (((*_24) as variant#4).2: AsyncInt);
++         _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb18, unwind: bb4];
+      }
+  
+      bb20: {
+-         _11 = move _2;
+-         _10 = std::future::get_context::<'_, '_>(move _11) -> [return: bb19, unwind: bb12];
++         goto -> bb3;
+      }
+  
+-     bb21: {
+-         _12 = &mut _5;
+-         _9 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _12) -> [return: bb20, unwind: bb12];
++     bb21 (cleanup): {
++         discriminant((*_24)) = 2;
++         resume;
+      }
+  
+      bb22: {
+-         _2 = move _13;
+-         StorageDead(_13);
+-         goto -> bb28;
++         StorageLive(_6);
++         _6 = move _2;
++         goto -> bb10;
+      }
+  
+      bb23: {
+-         _2 = move _13;
+-         StorageDead(_13);
+-         goto -> bb21;
++         StorageLive(_13);
++         _13 = move _2;
++         goto -> bb12;
+      }
+  
+      bb24: {
+-         StorageLive(_13);
+-         _13 = yield(const ()) -> [resume: bb22, drop: bb23];
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb24, unwind continue];
+      }
+  
+      bb25: {
+-         _15 = discriminant(_14);
+-         switchInt(move _15) -> [0: bb10, 1: bb24, otherwise: bb17];
++         assert(const false, "`async fn` resumed after completion") -> [success: bb25, unwind continue];
+      }
+  
+      bb26: {
+-         _14 = <impl Future<Output = ()> as Future>::poll(move _16, move _17) -> [return: bb25, unwind: bb12];
+-     }
+- 
+-     bb27: {
+-         _18 = move _2;
+-         _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb26, unwind: bb12];
+-     }
+- 
+-     bb28: {
+-         _19 = &mut _5;
+-         _16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _19) -> [return: bb27, unwind: bb12];
+-     }
+- 
+-     bb29: {
+-         StorageLive(_5);
+-         _5 = async_drop_in_place::<AsyncInt>(copy (_20.0: &mut AsyncInt)) -> [return: bb28, unwind: bb12];
+-     }
+- 
+-     bb30: {
+-         _21 = &mut _4;
+-         _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb29, unwind: bb7];
++         nop;
++         (((*_24) as variant#4).1: SyncInt) = SyncInt(const 0_i32);
++         nop;
++         (((*_24) as variant#4).2: AsyncInt) = AsyncInt(const 0_i32);
++         (((*_24) as variant#4).0: ()) = const ();
++         goto -> bb19;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.coroutine_drop_async.0.mir" "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.coroutine_drop_async.0.mir"
new file mode 100644
index 0000000..bc3def6
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop.simple-\173closure\0430\175.coroutine_drop_async.0.mir"
@@ -0,0 +1,162 @@
+// MIR for `simple::{closure#0}` 0 coroutine_drop_async
+
+fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _2;
+    let mut _0: std::task::Poll<()>;
+    let _3: SyncInt;
+    let mut _5: impl std::future::Future<Output = ()>;
+    let mut _6: &mut std::task::Context<'_>;
+    let mut _7: std::task::Poll<()>;
+    let mut _8: isize;
+    let mut _9: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _10: &mut std::task::Context<'_>;
+    let mut _11: &mut std::task::Context<'_>;
+    let mut _12: &mut impl std::future::Future<Output = ()>;
+    let mut _13: &mut std::task::Context<'_>;
+    let mut _14: std::task::Poll<()>;
+    let mut _15: isize;
+    let mut _16: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: &mut impl std::future::Future<Output = ()>;
+    let mut _20: std::pin::Pin<&mut AsyncInt>;
+    let mut _21: &mut AsyncInt;
+    let mut _22: ();
+    let mut _23: u32;
+    let mut _24: &mut {async fn body of simple()};
+    scope 1 {
+        debug sync_int => (((*_24) as variant#4).1: SyncInt);
+        let _4: AsyncInt;
+        scope 2 {
+            debug async_int => (((*_24) as variant#4).2: AsyncInt);
+        }
+    }
+
+    bb0: {
+        _24 = copy (_1.0: &mut {async fn body of simple()});
+        _23 = discriminant((*_24));
+        switchInt(move _23) -> [0: bb18, 2: bb23, 3: bb21, 4: bb22, otherwise: bb24];
+    }
+
+    bb1: {
+        nop;
+        goto -> bb2;
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb4 (cleanup): {
+        nop;
+        drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb5, unwind terminate(cleanup)];
+    }
+
+    bb5 (cleanup): {
+        nop;
+        goto -> bb6;
+    }
+
+    bb6 (cleanup): {
+        goto -> bb20;
+    }
+
+    bb7: {
+        nop;
+        goto -> bb1;
+    }
+
+    bb8 (cleanup): {
+        nop;
+        goto -> bb4;
+    }
+
+    bb9: {
+        _2 = move _6;
+        StorageDead(_6);
+        goto -> bb15;
+    }
+
+    bb10: {
+        StorageLive(_6);
+        _0 = Poll::<()>::Pending;
+        StorageDead(_6);
+        discriminant((*_24)) = 3;
+        return;
+    }
+
+    bb11: {
+        unreachable;
+    }
+
+    bb12: {
+        _8 = discriminant(_7);
+        switchInt(move _8) -> [0: bb7, 1: bb10, otherwise: bb11];
+    }
+
+    bb13: {
+        _7 = <impl Future<Output = ()> as Future>::poll(move _9, move _10) -> [return: bb12, unwind: bb8];
+    }
+
+    bb14: {
+        _11 = move _2;
+        _10 = move _11;
+        goto -> bb13;
+    }
+
+    bb15: {
+        _12 = &mut (((*_24) as variant#4).3: impl std::future::Future<Output = ()>);
+        _9 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _12) -> [return: bb14, unwind: bb8];
+    }
+
+    bb16: {
+        _2 = move _13;
+        StorageDead(_13);
+        goto -> bb15;
+    }
+
+    bb17: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb18: {
+        goto -> bb19;
+    }
+
+    bb19: {
+        goto -> bb17;
+    }
+
+    bb20 (cleanup): {
+        discriminant((*_24)) = 2;
+        resume;
+    }
+
+    bb21: {
+        StorageLive(_6);
+        _6 = move _2;
+        goto -> bb9;
+    }
+
+    bb22: {
+        StorageLive(_13);
+        _13 = move _2;
+        goto -> bb16;
+    }
+
+    bb23: {
+        assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue];
+    }
+
+    bb24: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir" "b/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir"
new file mode 100644
index 0000000..1790b35
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-abort.mir"
@@ -0,0 +1,130 @@
+// MIR for `a::{closure#0}` 0 coroutine_drop_async
+
+fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _2;
+    debug x => ((*_23).0: T);
+    let mut _0: std::task::Poll<()>;
+    let _3: T;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: &mut std::task::Context<'_>;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: &mut std::task::Context<'_>;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: &mut std::task::Context<'_>;
+    let mut _13: std::task::Poll<()>;
+    let mut _14: isize;
+    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut impl std::future::Future<Output = ()>;
+    let mut _19: std::pin::Pin<&mut T>;
+    let mut _20: &mut T;
+    let mut _21: ();
+    let mut _22: u32;
+    let mut _23: &mut {async fn body of a<T>()};
+    scope 1 {
+        debug x => (((*_23) as variant#4).1: T);
+    }
+
+    bb0: {
+        _23 = copy (_1.0: &mut {async fn body of a<T>()});
+        _22 = discriminant((*_23));
+        switchInt(move _22) -> [0: bb13, 3: bb16, 4: bb17, otherwise: bb18];
+    }
+
+    bb1: {
+        nop;
+        goto -> bb2;
+    }
+
+    bb2: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb3: {
+        nop;
+        goto -> bb1;
+    }
+
+    bb4: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb10;
+    }
+
+    bb5: {
+        StorageLive(_5);
+        _0 = Poll::<()>::Pending;
+        StorageDead(_5);
+        discriminant((*_23)) = 3;
+        return;
+    }
+
+    bb6: {
+        unreachable;
+    }
+
+    bb7: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb3, 1: bb5, otherwise: bb6];
+    }
+
+    bb8: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb7, unwind unreachable];
+    }
+
+    bb9: {
+        _10 = move _2;
+        _9 = move _10;
+        goto -> bb8;
+    }
+
+    bb10: {
+        _11 = &mut (((*_23) as variant#4).2: impl std::future::Future<Output = ()>);
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb9, unwind unreachable];
+    }
+
+    bb11: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb10;
+    }
+
+    bb12: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb13: {
+        goto -> bb15;
+    }
+
+    bb14: {
+        goto -> bb12;
+    }
+
+    bb15: {
+        drop(((*_23).0: T)) -> [return: bb14, unwind unreachable];
+    }
+
+    bb16: {
+        StorageLive(_5);
+        _5 = move _2;
+        goto -> bb4;
+    }
+
+    bb17: {
+        StorageLive(_12);
+        _12 = move _2;
+        goto -> bb11;
+    }
+
+    bb18: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir" "b/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir"
new file mode 100644
index 0000000..83bfc39
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop_live_dead.a-\173closure\0430\175.coroutine_drop_async.0.panic-unwind.mir"
@@ -0,0 +1,157 @@
+// MIR for `a::{closure#0}` 0 coroutine_drop_async
+
+fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _2;
+    debug x => ((*_23).0: T);
+    let mut _0: std::task::Poll<()>;
+    let _3: T;
+    let mut _4: impl std::future::Future<Output = ()>;
+    let mut _5: &mut std::task::Context<'_>;
+    let mut _6: std::task::Poll<()>;
+    let mut _7: isize;
+    let mut _8: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _9: &mut std::task::Context<'_>;
+    let mut _10: &mut std::task::Context<'_>;
+    let mut _11: &mut impl std::future::Future<Output = ()>;
+    let mut _12: &mut std::task::Context<'_>;
+    let mut _13: std::task::Poll<()>;
+    let mut _14: isize;
+    let mut _15: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut impl std::future::Future<Output = ()>;
+    let mut _19: std::pin::Pin<&mut T>;
+    let mut _20: &mut T;
+    let mut _21: ();
+    let mut _22: u32;
+    let mut _23: &mut {async fn body of a<T>()};
+    scope 1 {
+        debug x => (((*_23) as variant#4).1: T);
+    }
+
+    bb0: {
+        _23 = copy (_1.0: &mut {async fn body of a<T>()});
+        _22 = discriminant((*_23));
+        switchInt(move _22) -> [0: bb17, 2: bb23, 3: bb21, 4: bb22, otherwise: bb24];
+    }
+
+    bb1: {
+        nop;
+        goto -> bb2;
+    }
+
+    bb2: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb3 (cleanup): {
+        nop;
+        goto -> bb15;
+    }
+
+    bb4 (cleanup): {
+        goto -> bb20;
+    }
+
+    bb5: {
+        nop;
+        goto -> bb1;
+    }
+
+    bb6 (cleanup): {
+        nop;
+        goto -> bb3;
+    }
+
+    bb7: {
+        _2 = move _5;
+        StorageDead(_5);
+        goto -> bb13;
+    }
+
+    bb8: {
+        StorageLive(_5);
+        _0 = Poll::<()>::Pending;
+        StorageDead(_5);
+        discriminant((*_23)) = 3;
+        return;
+    }
+
+    bb9: {
+        unreachable;
+    }
+
+    bb10: {
+        _7 = discriminant(_6);
+        switchInt(move _7) -> [0: bb5, 1: bb8, otherwise: bb9];
+    }
+
+    bb11: {
+        _6 = <impl Future<Output = ()> as Future>::poll(move _8, move _9) -> [return: bb10, unwind: bb6];
+    }
+
+    bb12: {
+        _10 = move _2;
+        _9 = move _10;
+        goto -> bb11;
+    }
+
+    bb13: {
+        _11 = &mut (((*_23) as variant#4).2: impl std::future::Future<Output = ()>);
+        _8 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb12, unwind: bb6];
+    }
+
+    bb14: {
+        _2 = move _12;
+        StorageDead(_12);
+        goto -> bb13;
+    }
+
+    bb15 (cleanup): {
+        goto -> bb4;
+    }
+
+    bb16: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+
+    bb17: {
+        goto -> bb19;
+    }
+
+    bb18: {
+        goto -> bb16;
+    }
+
+    bb19: {
+        drop(((*_23).0: T)) -> [return: bb18, unwind: bb4];
+    }
+
+    bb20 (cleanup): {
+        discriminant((*_23)) = 2;
+        resume;
+    }
+
+    bb21: {
+        StorageLive(_5);
+        _5 = move _2;
+        goto -> bb7;
+    }
+
+    bb22: {
+        StorageLive(_12);
+        _12 = move _2;
+        goto -> bb14;
+    }
+
+    bb23: {
+        assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue];
+    }
+
+    bb24: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git a/tests/mir-opt/async_drop_live_dead.rs b/tests/mir-opt/coroutine/async_drop_live_dead.rs
similarity index 100%
rename from tests/mir-opt/async_drop_live_dead.rs
rename to tests/mir-opt/coroutine/async_drop_live_dead.rs
diff --git "a/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir" "b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir"
new file mode 100644
index 0000000..3d1ee14
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-\173closure\0430\175.\133Foo;1\135.MentionedItems.after.mir"
@@ -0,0 +1,272 @@
+// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems
+
+fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: std::future::ResumeTy) -> ()
+yields ()
+ {
+    let mut _0: ();
+    let mut _3: &mut [Foo; 1];
+    let mut _4: *mut [Foo; 1];
+    let mut _5: *mut [Foo];
+    let mut _6: usize;
+    let mut _7: usize;
+    let mut _8: *mut Foo;
+    let mut _9: bool;
+    let mut _10: *mut Foo;
+    let mut _11: bool;
+    let mut _12: impl std::future::Future<Output = ()>;
+    let mut _13: std::future::ResumeTy;
+    let mut _14: std::task::Poll<()>;
+    let mut _15: isize;
+    let mut _16: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: std::future::ResumeTy;
+    let mut _19: &mut impl std::future::Future<Output = ()>;
+    let mut _20: std::pin::Pin<&mut Foo>;
+    let mut _21: &mut Foo;
+    let mut _22: *mut Foo;
+    let mut _23: bool;
+    let mut _24: impl std::future::Future<Output = ()>;
+    let mut _25: std::future::ResumeTy;
+    let mut _26: std::task::Poll<()>;
+    let mut _27: isize;
+    let mut _28: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _29: &mut std::task::Context<'_>;
+    let mut _30: std::future::ResumeTy;
+    let mut _31: &mut impl std::future::Future<Output = ()>;
+    let mut _32: std::future::ResumeTy;
+    let mut _33: std::task::Poll<()>;
+    let mut _34: isize;
+    let mut _35: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
+    let mut _36: &mut std::task::Context<'_>;
+    let mut _37: std::future::ResumeTy;
+    let mut _38: &mut impl std::future::Future<Output = ()>;
+    let mut _39: std::pin::Pin<&mut Foo>;
+    let mut _40: &mut Foo;
+
+    bb0: {
+        _3 = move (_1.0: &mut [Foo; 1]);
+        goto -> bb44;
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+
+    bb3 (cleanup): {
+        _8 = &raw mut (*_5)[_7];
+        _7 = Add(move _7, const 1_usize);
+        drop((*_8)) -> [return: bb4, unwind terminate(cleanup)];
+    }
+
+    bb4 (cleanup): {
+        _9 = Eq(copy _7, copy _6);
+        switchInt(move _9) -> [0: bb3, otherwise: bb2];
+    }
+
+    bb5: {
+        _10 = &raw mut (*_5)[_7];
+        _7 = Add(move _7, const 1_usize);
+        goto -> bb19;
+    }
+
+    bb6: {
+        _11 = Eq(copy _7, copy _6);
+        switchInt(move _11) -> [0: bb5, otherwise: bb1];
+    }
+
+    bb7: {
+        StorageDead(_12);
+        goto -> bb6;
+    }
+
+    bb8 (cleanup): {
+        StorageDead(_12);
+        goto -> bb4;
+    }
+
+    bb9: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8];
+    }
+
+    bb10: {
+        _2 = move _13;
+        StorageDead(_13);
+        goto -> bb9;
+    }
+
+    bb11: {
+        _2 = move _13;
+        StorageDead(_13);
+        goto -> bb17;
+    }
+
+    bb12: {
+        StorageLive(_13);
+        _13 = yield(const ()) -> [resume: bb10, drop: bb11];
+    }
+
+    bb13: {
+        unreachable;
+    }
+
+    bb14: {
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb7, 1: bb12, otherwise: bb13];
+    }
+
+    bb15: {
+        _14 = <impl Future<Output = ()> as Future>::poll(move _16, move _17) -> [return: bb14, unwind: bb8];
+    }
+
+    bb16: {
+        _18 = move _2;
+        _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb15, unwind: bb8];
+    }
+
+    bb17: {
+        _19 = &mut _12;
+        _16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _19) -> [return: bb16, unwind: bb8];
+    }
+
+    bb18: {
+        StorageLive(_12);
+        _12 = async_drop_in_place::<Foo>(copy (_20.0: &mut Foo)) -> [return: bb17, unwind: bb8];
+    }
+
+    bb19: {
+        _21 = &mut (*_10);
+        _20 = Pin::<&mut Foo>::new_unchecked(move _21) -> [return: bb18, unwind: bb4];
+    }
+
+    bb20: {
+        _22 = &raw mut (*_5)[_7];
+        _7 = Add(move _7, const 1_usize);
+        goto -> bb41;
+    }
+
+    bb21: {
+        _23 = Eq(copy _7, copy _6);
+        switchInt(move _23) -> [0: bb20, otherwise: bb1];
+    }
+
+    bb22: {
+        StorageDead(_24);
+        goto -> bb21;
+    }
+
+    bb23: {
+        StorageDead(_24);
+        goto -> bb6;
+    }
+
+    bb24 (cleanup): {
+        StorageDead(_24);
+        goto -> bb4;
+    }
+
+    bb25: {
+        assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24];
+    }
+
+    bb26: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb25;
+    }
+
+    bb27: {
+        _2 = move _25;
+        StorageDead(_25);
+        goto -> bb32;
+    }
+
+    bb28: {
+        StorageLive(_25);
+        _25 = yield(const ()) -> [resume: bb26, drop: bb27];
+    }
+
+    bb29: {
+        _27 = discriminant(_26);
+        switchInt(move _27) -> [0: bb23, 1: bb28, otherwise: bb13];
+    }
+
+    bb30: {
+        _26 = <impl Future<Output = ()> as Future>::poll(move _28, move _29) -> [return: bb29, unwind: bb24];
+    }
+
+    bb31: {
+        _30 = move _2;
+        _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb30, unwind: bb24];
+    }
+
+    bb32: {
+        _31 = &mut _24;
+        _28 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _31) -> [return: bb31, unwind: bb24];
+    }
+
+    bb33: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb39;
+    }
+
+    bb34: {
+        _2 = move _32;
+        StorageDead(_32);
+        goto -> bb32;
+    }
+
+    bb35: {
+        StorageLive(_32);
+        _32 = yield(const ()) -> [resume: bb33, drop: bb34];
+    }
+
+    bb36: {
+        _34 = discriminant(_33);
+        switchInt(move _34) -> [0: bb22, 1: bb35, otherwise: bb13];
+    }
+
+    bb37: {
+        _33 = <impl Future<Output = ()> as Future>::poll(move _35, move _36) -> [return: bb36, unwind: bb24];
+    }
+
+    bb38: {
+        _37 = move _2;
+        _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb37, unwind: bb24];
+    }
+
+    bb39: {
+        _38 = &mut _24;
+        _35 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _38) -> [return: bb38, unwind: bb24];
+    }
+
+    bb40: {
+        StorageLive(_24);
+        _24 = async_drop_in_place::<Foo>(copy (_39.0: &mut Foo)) -> [return: bb39, unwind: bb24];
+    }
+
+    bb41: {
+        _40 = &mut (*_22);
+        _39 = Pin::<&mut Foo>::new_unchecked(move _40) -> [return: bb40, unwind: bb4];
+    }
+
+    bb42: {
+        _6 = PtrMetadata(copy _5);
+        _7 = const 0_usize;
+        goto -> bb21;
+    }
+
+    bb43: {
+        goto -> bb42;
+    }
+
+    bb44: {
+        _4 = &raw mut (*_3);
+        _5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit));
+        goto -> bb43;
+    }
+}
diff --git a/tests/mir-opt/async_drop_mir_pin.rs b/tests/mir-opt/coroutine/async_drop_mir_pin.rs
similarity index 100%
rename from tests/mir-opt/async_drop_mir_pin.rs
rename to tests/mir-opt/coroutine/async_drop_mir_pin.rs
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..3619637
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,80 @@
+- // MIR for `add::{closure#0}::{closure#0}` before StateTransform
++ // MIR for `add::{closure#0}::{closure#0}` after StateTransform
+  
+- fn add::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:34:13: 34:18}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn add::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     debug x => (*(_1.0: &u32));
+-     debug y => (*(_1.1: &u32));
+-     let mut _0: u32;
++     debug x => (*((*_9).0: &u32));
++     debug y => (*((*_9).1: &u32));
++     let mut _0: std::task::Poll<u32>;
+      let mut _3: u32;
+      let mut _4: u32;
+      let mut _5: &u32;
+      let mut _6: &u32;
++     let mut _7: u32;
++     let mut _8: u32;
++     let mut _9: &mut {async block@$DIR/async_fn.rs:34:13: 34:18};
+  
+      bb0: {
+-         StorageLive(_3);
+-         _5 = no_retag copy (_1.0: &u32);
+-         _3 = copy (*_5);
+-         StorageLive(_4);
+-         _6 = no_retag copy (_1.1: &u32);
+-         _4 = copy (*_6);
+-         _0 = Add(move _3, move _4);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:34:13: 34:18});
++         _8 = discriminant((*_9));
++         switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<u32>::Ready(move _7);
++         discriminant((*_9)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         StorageLive(_3);
++         _5 = no_retag copy ((*_9).0: &u32);
++         _3 = copy (*_5);
++         StorageLive(_4);
++         _6 = no_retag copy ((*_9).1: &u32);
++         _4 = copy (*_6);
++         _7 = Add(move _3, move _4);
++         StorageDead(_4);
++         StorageDead(_3);
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..0439d4c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,36 @@
+// MIR for `add::{closure#0}::{closure#0}` 0 coroutine_drop
+
+fn add::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}) -> () {
+    debug _task_context => _2;
+    debug x => (*((*_1).0: &u32));
+    debug y => (*((*_1).1: &u32));
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let mut _3: u32;
+    let mut _4: u32;
+    let mut _5: &u32;
+    let mut _6: &u32;
+    let mut _7: u32;
+    let mut _8: u32;
+
+    bb0: {
+        _8 = discriminant((*_1));
+        switchInt(move _8) -> [0: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2: {
+        goto -> bb3;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..0c8f25d
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,14 @@
+// MIR for `add::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn add::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:34:13: 34:18}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..472d469
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,371 @@
+- // MIR for `add::{closure#0}` before StateTransform
++ // MIR for `add::{closure#0}` after StateTransform
+  
+- fn add::{closure#0}(_1: {async fn body of add()}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn add::{closure#0}(_1: Pin<&mut {async fn body of add()}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         field _s0: u32;
++         field _s1: u32;
++         field _s2: {async block@$DIR/async_fn.rs:34:13: 34:18};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s2],
++         }
++         storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)}
++     }
+      debug _task_context => _2;
+-     debug x => (_1.0: u32);
+-     debug y => (_1.1: u32);
+-     let mut _0: u32;
++     debug x => ((*_27).0: u32);
++     debug y => ((*_27).1: u32);
++     coroutine debug x => _s0;
++     let mut _0: std::task::Poll<u32>;
+      let _3: u32;
+      let mut _6: &u32;
+      let mut _7: &u32;
+      let mut _8: {async block@$DIR/async_fn.rs:34:13: 34:18};
+      let mut _9: {async block@$DIR/async_fn.rs:34:13: 34:18};
+      let mut _11: ();
+      let _12: ();
+      let mut _13: std::task::Poll<u32>;
+      let mut _14: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>;
+      let mut _15: &mut {async block@$DIR/async_fn.rs:34:13: 34:18};
+      let mut _16: &mut {async block@$DIR/async_fn.rs:34:13: 34:18};
+      let mut _17: &mut std::task::Context<'_>;
+      let mut _18: &mut std::task::Context<'_>;
+-     let mut _19: std::future::ResumeTy;
++     let mut _19: &mut std::task::Context<'_>;
+      let mut _20: isize;
+      let mut _22: !;
+-     let mut _23: std::future::ResumeTy;
++     let mut _23: &mut std::task::Context<'_>;
+      let mut _24: ();
++     let mut _25: u32;
++     let mut _26: u32;
++     let mut _27: &mut {async fn body of add()};
+      scope 1 {
+-         debug x => _3;
++         debug x => (((*_27) as variant#3).0: u32);
++         coroutine debug y => _s1;
+          let _4: u32;
+          scope 2 {
+-             debug y => _4;
++             debug y => (((*_27) as variant#3).1: u32);
+              let _5: {async block@$DIR/async_fn.rs:34:13: 34:18};
+              scope 3 {
+                  debug a => _5;
++                 coroutine debug __awaitee => _s2;
+                  let mut _10: {async block@$DIR/async_fn.rs:34:13: 34:18};
+                  scope 4 {
+-                     debug __awaitee => _10;
++                     debug __awaitee => (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18});
+                      let _21: u32;
+                      scope 5 {
+                          debug result => _21;
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = copy (_1.0: u32);
+-         StorageLive(_4);
+-         _4 = copy (_1.1: u32);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = &_3;
+-         StorageLive(_7);
+-         _7 = &_4;
+-         _5 = {coroutine@$DIR/async_fn.rs:34:13: 34:18 (#0)} { x: move _6, y: move _7 };
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageLive(_8);
+-         StorageLive(_9);
+-         _9 = move _5;
+-         _8 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as IntoFuture>::into_future(move _9) -> [return: bb1, unwind: bb24];
++         _27 = copy (_1.0: &mut {async fn body of add()});
++         _26 = discriminant((*_27));
++         switchInt(move _26) -> [0: bb28, 1: bb27, 2: bb26, 3: bb25, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageDead(_9);
+          PlaceMention(_8);
+-         StorageLive(_10);
+-         _10 = move _8;
++         nop;
++         (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18}) = move _8;
+          goto -> bb2;
+      }
+  
+      bb2: {
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+          StorageLive(_16);
+-         _16 = &mut _10;
++         _16 = &mut (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18});
+          _15 = &mut (*_16);
+-         _14 = Pin::<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>::new_unchecked(move _15) -> [return: bb3, unwind: bb21];
++         _14 = Pin::<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>::new_unchecked(move _15) -> [return: bb3, unwind: bb15];
+      }
+  
+      bb3: {
+          StorageDead(_15);
+          StorageLive(_17);
+          StorageLive(_18);
+          StorageLive(_19);
+          _19 = copy _2;
+-         _18 = std::future::get_context::<'_, '_>(move _19) -> [return: bb4, unwind: bb19];
++         _18 = move _19;
++         goto -> bb4;
+      }
+  
+      bb4: {
+          _17 = &mut (*_18);
+          StorageDead(_19);
+-         _13 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as Future>::poll(move _14, move _17) -> [return: bb5, unwind: bb20];
++         _13 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as Future>::poll(move _14, move _17) -> [return: bb5, unwind: bb14];
+      }
+  
+      bb5: {
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_14);
+          PlaceMention(_13);
+          _20 = discriminant(_13);
+          switchInt(move _20) -> [0: bb8, 1: bb7, otherwise: bb6];
+      }
+  
+      bb6: {
+          unreachable;
+      }
+  
+      bb7: {
+          _12 = const ();
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageLive(_23);
+          StorageLive(_24);
+          _24 = ();
+-         _23 = yield(move _24) -> [resume: bb9, drop: bb14];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_5);
++         StorageDead(_8);
++         StorageDead(_23);
++         StorageDead(_24);
++         discriminant((*_27)) = 3;
++         return;
+      }
+  
+      bb8: {
+          StorageLive(_21);
+          _21 = copy ((_13 as Ready).0: u32);
+-         _0 = copy _21;
++         _25 = copy _21;
+          StorageDead(_21);
+          StorageDead(_13);
+          StorageDead(_12);
+-         drop(_10) -> [return: bb10, unwind: bb23];
++         drop((((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb10, unwind: bb17];
+      }
+  
+      bb9: {
+          StorageDead(_24);
+          _2 = move _23;
+          StorageDead(_23);
+          _11 = const ();
+          goto -> bb2;
+      }
+  
+      bb10: {
+-         StorageDead(_10);
++         nop;
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_8);
+          goto -> bb12;
+      }
+  
+      bb12: {
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb13, unwind: bb28];
++         nop;
++         nop;
++         goto -> bb23;
+      }
+  
+      bb13: {
++         _0 = Poll::<u32>::Ready(move _25);
++         discriminant((*_27)) = 1;
+          return;
+      }
+  
+-     bb14: {
+-         StorageDead(_24);
+-         StorageDead(_23);
+-         drop(_10) -> [return: bb15, unwind: bb29];
++     bb14 (cleanup): {
++         StorageDead(_18);
++         StorageDead(_17);
++         goto -> bb16;
+      }
+  
+-     bb15: {
+-         StorageDead(_10);
++     bb15 (cleanup): {
++         StorageDead(_15);
+          goto -> bb16;
+      }
+  
+-     bb16: {
+-         StorageDead(_8);
+-         goto -> bb17;
++     bb16 (cleanup): {
++         StorageDead(_16);
++         StorageDead(_14);
++         StorageDead(_13);
++         StorageDead(_12);
++         drop((((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb17, unwind terminate(cleanup)];
+      }
+  
+-     bb17: {
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb18, unwind: bb28];
++     bb17 (cleanup): {
++         nop;
++         goto -> bb20;
+      }
+  
+-     bb18: {
+-         coroutine_drop;
++     bb18 (cleanup): {
++         goto -> bb19;
+      }
+  
+      bb19 (cleanup): {
+-         StorageDead(_19);
++         StorageDead(_9);
+          goto -> bb20;
+      }
+  
+      bb20 (cleanup): {
+-         StorageDead(_18);
+-         StorageDead(_17);
+-         goto -> bb22;
++         StorageDead(_8);
++         goto -> bb21;
+      }
+  
+      bb21 (cleanup): {
+-         StorageDead(_15);
++         StorageDead(_5);
++         nop;
++         nop;
+          goto -> bb22;
+      }
+  
+      bb22 (cleanup): {
+-         StorageDead(_16);
+-         StorageDead(_14);
+-         StorageDead(_13);
+-         StorageDead(_12);
+-         drop(_10) -> [return: bb23, unwind terminate(cleanup)];
++         goto -> bb24;
+      }
+  
+-     bb23 (cleanup): {
+-         StorageDead(_10);
+-         goto -> bb26;
++     bb23: {
++         goto -> bb13;
+      }
+  
+      bb24 (cleanup): {
+-         goto -> bb25;
++         discriminant((*_27)) = 2;
++         resume;
+      }
+  
+-     bb25 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb26;
++     bb25: {
++         StorageLive(_5);
++         StorageLive(_8);
++         StorageLive(_23);
++         StorageLive(_24);
++         _23 = move _2;
++         goto -> bb9;
+      }
+  
+-     bb26 (cleanup): {
+-         StorageDead(_8);
+-         goto -> bb27;
++     bb26: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb26, unwind continue];
+      }
+  
+-     bb27 (cleanup): {
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb28, unwind terminate(cleanup)];
++     bb27: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb27, unwind continue];
+      }
+  
+-     bb28 (cleanup): {
+-         resume;
+-     }
+- 
+-     bb29 (cleanup): {
+-         StorageDead(_10);
+-         goto -> bb30;
+-     }
+- 
+-     bb30 (cleanup): {
+-         StorageDead(_8);
+-         goto -> bb31;
+-     }
+- 
+-     bb31 (cleanup): {
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb28, unwind terminate(cleanup)];
++     bb28: {
++         nop;
++         (((*_27) as variant#3).0: u32) = copy ((*_27).0: u32);
++         nop;
++         (((*_27) as variant#3).1: u32) = copy ((*_27).1: u32);
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = &(((*_27) as variant#3).0: u32);
++         StorageLive(_7);
++         _7 = &(((*_27) as variant#3).1: u32);
++         _5 = {coroutine@$DIR/async_fn.rs:34:13: 34:18 (#0)} { x: move _6, y: move _7 };
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageLive(_8);
++         StorageLive(_9);
++         _9 = move _5;
++         _8 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as IntoFuture>::into_future(move _9) -> [return: bb1, unwind: bb18];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..ecff837
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,129 @@
+// MIR for `add::{closure#0}` 0 coroutine_drop
+
+fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () {
+    debug _task_context => _2;
+    debug x => ((*_1).0: u32);
+    debug y => ((*_1).1: u32);
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: u32;
+    let mut _6: &u32;
+    let mut _7: &u32;
+    let mut _8: {async block@$DIR/async_fn.rs:34:13: 34:18};
+    let mut _9: {async block@$DIR/async_fn.rs:34:13: 34:18};
+    let mut _11: ();
+    let _12: ();
+    let mut _13: std::task::Poll<u32>;
+    let mut _14: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>;
+    let mut _15: &mut {async block@$DIR/async_fn.rs:34:13: 34:18};
+    let mut _16: &mut {async block@$DIR/async_fn.rs:34:13: 34:18};
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: isize;
+    let mut _22: !;
+    let mut _23: &mut std::task::Context<'_>;
+    let mut _24: ();
+    let mut _25: u32;
+    let mut _26: u32;
+    scope 1 {
+        debug x => (((*_1) as variant#3).0: u32);
+        let _4: u32;
+        scope 2 {
+            debug y => (((*_1) as variant#3).1: u32);
+            let _5: {async block@$DIR/async_fn.rs:34:13: 34:18};
+            scope 3 {
+                debug a => _5;
+                let mut _10: {async block@$DIR/async_fn.rs:34:13: 34:18};
+                scope 4 {
+                    debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18});
+                    let _21: u32;
+                    scope 5 {
+                        debug result => _21;
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _26 = discriminant((*_1));
+        switchInt(move _26) -> [0: bb11, 3: bb14, otherwise: bb15];
+    }
+
+    bb1: {
+        StorageDead(_24);
+        StorageDead(_23);
+        drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb2, unwind: bb7];
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_8);
+        goto -> bb4;
+    }
+
+    bb4: {
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb12;
+    }
+
+    bb5: {
+        return;
+    }
+
+    bb6 (cleanup): {
+        resume;
+    }
+
+    bb7 (cleanup): {
+        nop;
+        goto -> bb8;
+    }
+
+    bb8 (cleanup): {
+        StorageDead(_8);
+        goto -> bb9;
+    }
+
+    bb9 (cleanup): {
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb6;
+    }
+
+    bb10: {
+        return;
+    }
+
+    bb11: {
+        goto -> bb13;
+    }
+
+    bb12: {
+        goto -> bb5;
+    }
+
+    bb13: {
+        goto -> bb10;
+    }
+
+    bb14: {
+        StorageLive(_5);
+        StorageLive(_8);
+        StorageLive(_23);
+        StorageLive(_24);
+        goto -> bb1;
+    }
+
+    bb15: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..c86391c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.add-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,24 @@
+// MIR for `add::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn add::{closure#0}(_1: {async fn body of add()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+                scope 4 {
+                    scope 5 {
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..9a64430
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,695 @@
+- // MIR for `build_aggregate::{closure#0}` before StateTransform
++ // MIR for `build_aggregate::{closure#0}` after StateTransform
+  
+- fn build_aggregate::{closure#0}(_1: {async fn body of build_aggregate()}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn build_aggregate::{closure#0}(_1: Pin<&mut {async fn body of build_aggregate()}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         field _s0: u32;
++         field _s1: u32;
++         field _s2: u32;
++         field _s3: {async fn body of add()};
++         field _s4: {async fn body of add()};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s3],
++             Suspend1 (4): [_s2, _s4],
++         }
++         storage_conflicts = BitMatrix(5x5) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s4)}
++     }
+      debug _task_context => _2;
+-     debug a => (_1.0: u32);
+-     debug b => (_1.1: u32);
+-     debug c => (_1.2: u32);
+-     debug d => (_1.3: u32);
+-     let mut _0: u32;
++     debug a => ((*_51).0: u32);
++     debug b => ((*_51).1: u32);
++     debug c => ((*_51).2: u32);
++     debug d => ((*_51).3: u32);
++     let mut _0: std::task::Poll<u32>;
+      let _3: u32;
+      let mut _8: u32;
+      let mut _9: {async fn body of add()};
+      let mut _10: {async fn body of add()};
+      let mut _11: u32;
+      let mut _12: u32;
+      let mut _14: ();
+      let _15: ();
+      let mut _16: std::task::Poll<u32>;
+      let mut _17: std::pin::Pin<&mut {async fn body of add()}>;
+      let mut _18: &mut {async fn body of add()};
+      let mut _19: &mut {async fn body of add()};
+      let mut _20: &mut std::task::Context<'_>;
+      let mut _21: &mut std::task::Context<'_>;
+-     let mut _22: std::future::ResumeTy;
++     let mut _22: &mut std::task::Context<'_>;
+      let mut _23: isize;
+      let mut _25: !;
+-     let mut _26: std::future::ResumeTy;
++     let mut _26: &mut std::task::Context<'_>;
+      let mut _27: ();
+      let mut _28: u32;
+      let mut _29: {async fn body of add()};
+      let mut _30: {async fn body of add()};
+      let mut _31: u32;
+      let mut _32: u32;
+      let _34: ();
+      let mut _35: std::task::Poll<u32>;
+      let mut _36: std::pin::Pin<&mut {async fn body of add()}>;
+      let mut _37: &mut {async fn body of add()};
+      let mut _38: &mut {async fn body of add()};
+      let mut _39: &mut std::task::Context<'_>;
+      let mut _40: &mut std::task::Context<'_>;
+-     let mut _41: std::future::ResumeTy;
++     let mut _41: &mut std::task::Context<'_>;
+      let mut _42: isize;
+      let mut _44: !;
+-     let mut _45: std::future::ResumeTy;
++     let mut _45: &mut std::task::Context<'_>;
+      let mut _46: ();
+      let mut _47: u32;
+      let mut _48: u32;
++     let mut _49: u32;
++     let mut _50: u32;
++     let mut _51: &mut {async fn body of build_aggregate()};
+      scope 1 {
+          debug a => _3;
+          let _4: u32;
+          scope 2 {
+              debug b => _4;
++             coroutine debug c => _s0;
+              let _5: u32;
+              scope 3 {
+-                 debug c => _5;
++                 debug c => (((*_51) as variant#3).0: u32);
++                 coroutine debug d => _s1;
+                  let _6: u32;
+                  scope 4 {
+-                     debug d => _6;
++                     debug d => (((*_51) as variant#3).1: u32);
++                     coroutine debug __awaitee => _s3;
++                     coroutine debug __awaitee => _s4;
+                      let _7: (u32, u32);
+                      let mut _13: {async fn body of add()};
+                      let mut _33: {async fn body of add()};
+                      scope 5 {
+                          debug x => _7;
+                      }
+                      scope 6 {
+-                         debug __awaitee => _13;
++                         debug __awaitee => (((*_51) as variant#3).2: {async fn body of add()});
+                          let _24: u32;
+                          scope 7 {
+                              debug result => _24;
+                          }
+                      }
+                      scope 8 {
+-                         debug __awaitee => _33;
++                         debug __awaitee => (((*_51) as variant#4).1: {async fn body of add()});
+                          let _43: u32;
+                          scope 9 {
+                              debug result => _43;
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = copy (_1.0: u32);
+-         StorageLive(_4);
+-         _4 = copy (_1.1: u32);
+-         StorageLive(_5);
+-         _5 = copy (_1.2: u32);
+-         StorageLive(_6);
+-         _6 = copy (_1.3: u32);
+-         StorageLive(_7);
+-         StorageLive(_8);
+-         StorageLive(_9);
+-         StorageLive(_10);
+-         StorageLive(_11);
+-         _11 = copy _3;
+-         StorageLive(_12);
+-         _12 = copy _4;
+-         _10 = add(move _11, move _12) -> [return: bb1, unwind: bb49];
++         _51 = copy (_1.0: &mut {async fn body of build_aggregate()});
++         _50 = discriminant((*_51));
++         switchInt(move _50) -> [0: bb49, 1: bb48, 2: bb47, 3: bb45, 4: bb46, otherwise: bb7];
+      }
+  
+      bb1: {
+          StorageDead(_12);
+          StorageDead(_11);
+-         _9 = <{async fn body of add()} as IntoFuture>::into_future(move _10) -> [return: bb2, unwind: bb48];
++         _9 = <{async fn body of add()} as IntoFuture>::into_future(move _10) -> [return: bb2, unwind: bb38];
+      }
+  
+      bb2: {
+          StorageDead(_10);
+          PlaceMention(_9);
+-         StorageLive(_13);
+-         _13 = move _9;
++         nop;
++         (((*_51) as variant#3).2: {async fn body of add()}) = move _9;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageLive(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          StorageLive(_19);
+-         _19 = &mut _13;
++         _19 = &mut (((*_51) as variant#3).2: {async fn body of add()});
+          _18 = &mut (*_19);
+-         _17 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _18) -> [return: bb4, unwind: bb44];
++         _17 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _18) -> [return: bb4, unwind: bb34];
+      }
+  
+      bb4: {
+          StorageDead(_18);
+          StorageLive(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          _22 = copy _2;
+-         _21 = std::future::get_context::<'_, '_>(move _22) -> [return: bb5, unwind: bb42];
++         _21 = move _22;
++         goto -> bb5;
+      }
+  
+      bb5: {
+          _20 = &mut (*_21);
+          StorageDead(_22);
+-         _16 = <{async fn body of add()} as Future>::poll(move _17, move _20) -> [return: bb6, unwind: bb43];
++         _16 = <{async fn body of add()} as Future>::poll(move _17, move _20) -> [return: bb6, unwind: bb33];
+      }
+  
+      bb6: {
+          StorageDead(_21);
+          StorageDead(_20);
+          StorageDead(_19);
+          StorageDead(_17);
+          PlaceMention(_16);
+          _23 = discriminant(_16);
+          switchInt(move _23) -> [0: bb9, 1: bb8, otherwise: bb7];
+      }
+  
+      bb7: {
+          unreachable;
+      }
+  
+      bb8: {
+          _15 = const ();
+          StorageDead(_16);
+          StorageDead(_15);
+          StorageLive(_26);
+          StorageLive(_27);
+          _27 = ();
+-         _26 = yield(move _27) -> [resume: bb10, drop: bb28];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_3);
++         StorageDead(_4);
++         StorageDead(_7);
++         StorageDead(_9);
++         StorageDead(_26);
++         StorageDead(_27);
++         discriminant((*_51)) = 3;
++         return;
+      }
+  
+      bb9: {
+          StorageLive(_24);
+          _24 = copy ((_16 as Ready).0: u32);
+-         _8 = copy _24;
++         (((*_51) as variant#4).0: u32) = copy _24;
+          StorageDead(_24);
+          StorageDead(_16);
+          StorageDead(_15);
+-         drop(_13) -> [return: bb11, unwind: bb46];
++         drop((((*_51) as variant#3).2: {async fn body of add()})) -> [return: bb11, unwind: bb36];
+      }
+  
+      bb10: {
+          StorageDead(_27);
+          _2 = move _26;
+          StorageDead(_26);
+          _14 = const ();
+          goto -> bb3;
+      }
+  
+      bb11: {
+-         StorageDead(_13);
++         nop;
+          StorageLive(_28);
+          StorageLive(_29);
+          StorageLive(_30);
+          StorageLive(_31);
+-         _31 = copy _5;
++         _31 = copy (((*_51) as variant#3).0: u32);
+          StorageLive(_32);
+-         _32 = copy _6;
+-         _30 = add(move _31, move _32) -> [return: bb12, unwind: bb39];
++         _32 = copy (((*_51) as variant#3).1: u32);
++         _30 = add(move _31, move _32) -> [return: bb12, unwind: bb30];
+      }
+  
+      bb12: {
+          StorageDead(_32);
+          StorageDead(_31);
+-         _29 = <{async fn body of add()} as IntoFuture>::into_future(move _30) -> [return: bb13, unwind: bb38];
++         _29 = <{async fn body of add()} as IntoFuture>::into_future(move _30) -> [return: bb13, unwind: bb29];
+      }
+  
+      bb13: {
+          StorageDead(_30);
+          PlaceMention(_29);
+-         StorageLive(_33);
+-         _33 = move _29;
++         nop;
++         (((*_51) as variant#4).1: {async fn body of add()}) = move _29;
+          goto -> bb14;
+      }
+  
+      bb14: {
+          StorageLive(_34);
+          StorageLive(_35);
+          StorageLive(_36);
+          StorageLive(_37);
+          StorageLive(_38);
+-         _38 = &mut _33;
++         _38 = &mut (((*_51) as variant#4).1: {async fn body of add()});
+          _37 = &mut (*_38);
+-         _36 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _37) -> [return: bb15, unwind: bb35];
++         _36 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _37) -> [return: bb15, unwind: bb26];
+      }
+  
+      bb15: {
+          StorageDead(_37);
+          StorageLive(_39);
+          StorageLive(_40);
+          StorageLive(_41);
+          _41 = copy _2;
+-         _40 = std::future::get_context::<'_, '_>(move _41) -> [return: bb16, unwind: bb33];
++         _40 = move _41;
++         goto -> bb16;
+      }
+  
+      bb16: {
+          _39 = &mut (*_40);
+          StorageDead(_41);
+-         _35 = <{async fn body of add()} as Future>::poll(move _36, move _39) -> [return: bb17, unwind: bb34];
++         _35 = <{async fn body of add()} as Future>::poll(move _36, move _39) -> [return: bb17, unwind: bb25];
+      }
+  
+      bb17: {
+          StorageDead(_40);
+          StorageDead(_39);
+          StorageDead(_38);
+          StorageDead(_36);
+          PlaceMention(_35);
+          _42 = discriminant(_35);
+          switchInt(move _42) -> [0: bb19, 1: bb18, otherwise: bb7];
+      }
+  
+      bb18: {
+          _34 = const ();
+          StorageDead(_35);
+          StorageDead(_34);
+          StorageLive(_45);
+          StorageLive(_46);
+          _46 = ();
+-         _45 = yield(move _46) -> [resume: bb20, drop: bb25];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_3);
++         StorageDead(_4);
++         StorageDead(_7);
++         StorageDead(_9);
++         StorageDead(_28);
++         StorageDead(_29);
++         StorageDead(_45);
++         StorageDead(_46);
++         discriminant((*_51)) = 4;
++         return;
+      }
+  
+      bb19: {
+          StorageLive(_43);
+          _43 = copy ((_35 as Ready).0: u32);
+          _28 = copy _43;
+          StorageDead(_43);
+          StorageDead(_35);
+          StorageDead(_34);
+-         drop(_33) -> [return: bb21, unwind: bb37];
++         drop((((*_51) as variant#4).1: {async fn body of add()})) -> [return: bb21, unwind: bb28];
+      }
+  
+      bb20: {
+          StorageDead(_46);
+          _2 = move _45;
+          StorageDead(_45);
+          _14 = const ();
+          goto -> bb14;
+      }
+  
+      bb21: {
+-         StorageDead(_33);
+-         _7 = (move _8, move _28);
++         nop;
++         _7 = (move (((*_51) as variant#4).0: u32), move _28);
+          StorageDead(_28);
+-         StorageDead(_8);
++         nop;
+          goto -> bb22;
+      }
+  
+      bb22: {
+          StorageDead(_29);
+          goto -> bb23;
+      }
+  
+      bb23: {
+          StorageDead(_9);
+          StorageLive(_47);
+          _47 = copy (_7.0: u32);
+          StorageLive(_48);
+          _48 = copy (_7.1: u32);
+-         _0 = Add(move _47, move _48);
++         _49 = Add(move _47, move _48);
+          StorageDead(_48);
+          StorageDead(_47);
+          StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
++         nop;
++         nop;
+          StorageDead(_4);
+          StorageDead(_3);
+-         drop(_1) -> [return: bb24, unwind: bb52];
++         goto -> bb43;
+      }
+  
+      bb24: {
++         _0 = Poll::<u32>::Ready(move _49);
++         discriminant((*_51)) = 1;
+          return;
+      }
+  
+-     bb25: {
+-         StorageDead(_46);
+-         StorageDead(_45);
+-         drop(_33) -> [return: bb26, unwind: bb53];
+-     }
+- 
+-     bb26: {
+-         StorageDead(_33);
+-         StorageDead(_28);
+-         StorageDead(_8);
+-         goto -> bb27;
+-     }
+- 
+-     bb27: {
+-         StorageDead(_29);
+-         goto -> bb30;
+-     }
+- 
+-     bb28: {
+-         StorageDead(_27);
+-         StorageDead(_26);
+-         drop(_13) -> [return: bb29, unwind: bb55];
+-     }
+- 
+-     bb29: {
+-         StorageDead(_13);
+-         StorageDead(_8);
+-         goto -> bb30;
+-     }
+- 
+-     bb30: {
+-         goto -> bb31;
+-     }
+- 
+-     bb31: {
+-         StorageDead(_9);
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb32, unwind: bb52];
+-     }
+- 
+-     bb32: {
+-         coroutine_drop;
+-     }
+- 
+-     bb33 (cleanup): {
+-         StorageDead(_41);
+-         goto -> bb34;
+-     }
+- 
+-     bb34 (cleanup): {
++     bb25 (cleanup): {
+          StorageDead(_40);
+          StorageDead(_39);
+-         goto -> bb36;
++         goto -> bb27;
+      }
+  
+-     bb35 (cleanup): {
++     bb26 (cleanup): {
+          StorageDead(_37);
+-         goto -> bb36;
++         goto -> bb27;
+      }
+  
+-     bb36 (cleanup): {
++     bb27 (cleanup): {
+          StorageDead(_38);
+          StorageDead(_36);
+          StorageDead(_35);
+          StorageDead(_34);
+-         drop(_33) -> [return: bb37, unwind terminate(cleanup)];
++         drop((((*_51) as variant#4).1: {async fn body of add()})) -> [return: bb28, unwind terminate(cleanup)];
+      }
+  
+-     bb37 (cleanup): {
+-         StorageDead(_33);
++     bb28 (cleanup): {
++         nop;
+          StorageDead(_28);
+-         StorageDead(_8);
+-         goto -> bb41;
++         nop;
++         goto -> bb32;
+      }
+  
+-     bb38 (cleanup): {
+-         goto -> bb40;
++     bb29 (cleanup): {
++         goto -> bb31;
+      }
+  
+-     bb39 (cleanup): {
++     bb30 (cleanup): {
+          StorageDead(_32);
+          StorageDead(_31);
+-         goto -> bb40;
++         goto -> bb31;
+      }
+  
+-     bb40 (cleanup): {
++     bb31 (cleanup): {
+          StorageDead(_30);
+          StorageDead(_28);
+-         StorageDead(_8);
+-         goto -> bb41;
++         nop;
++         goto -> bb32;
+      }
+  
+-     bb41 (cleanup): {
++     bb32 (cleanup): {
+          StorageDead(_29);
+-         goto -> bb47;
++         goto -> bb37;
+      }
+  
+-     bb42 (cleanup): {
+-         StorageDead(_22);
+-         goto -> bb43;
+-     }
+- 
+-     bb43 (cleanup): {
++     bb33 (cleanup): {
+          StorageDead(_21);
+          StorageDead(_20);
+-         goto -> bb45;
++         goto -> bb35;
+      }
+  
+-     bb44 (cleanup): {
++     bb34 (cleanup): {
+          StorageDead(_18);
+-         goto -> bb45;
++         goto -> bb35;
+      }
+  
+-     bb45 (cleanup): {
++     bb35 (cleanup): {
+          StorageDead(_19);
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_15);
+-         drop(_13) -> [return: bb46, unwind terminate(cleanup)];
++         drop((((*_51) as variant#3).2: {async fn body of add()})) -> [return: bb36, unwind terminate(cleanup)];
+      }
+  
+-     bb46 (cleanup): {
+-         StorageDead(_13);
+-         StorageDead(_8);
+-         goto -> bb47;
++     bb36 (cleanup): {
++         nop;
++         nop;
++         goto -> bb37;
+      }
+  
+-     bb47 (cleanup): {
+-         goto -> bb51;
++     bb37 (cleanup): {
++         goto -> bb41;
+      }
+  
+-     bb48 (cleanup): {
+-         goto -> bb50;
++     bb38 (cleanup): {
++         goto -> bb40;
+      }
+  
+-     bb49 (cleanup): {
++     bb39 (cleanup): {
+          StorageDead(_12);
+          StorageDead(_11);
+-         goto -> bb50;
++         goto -> bb40;
+      }
+  
+-     bb50 (cleanup): {
++     bb40 (cleanup): {
+          StorageDead(_10);
+-         StorageDead(_8);
+-         goto -> bb51;
++         nop;
++         goto -> bb41;
+      }
+  
+-     bb51 (cleanup): {
++     bb41 (cleanup): {
+          StorageDead(_9);
+          StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
++         nop;
++         nop;
+          StorageDead(_4);
+          StorageDead(_3);
+-         drop(_1) -> [return: bb52, unwind terminate(cleanup)];
++         goto -> bb42;
+      }
+  
+-     bb52 (cleanup): {
++     bb42 (cleanup): {
++         goto -> bb44;
++     }
++ 
++     bb43: {
++         goto -> bb24;
++     }
++ 
++     bb44 (cleanup): {
++         discriminant((*_51)) = 2;
+          resume;
+      }
+  
+-     bb53 (cleanup): {
+-         StorageDead(_33);
+-         StorageDead(_28);
+-         StorageDead(_8);
+-         goto -> bb54;
++     bb45: {
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_7);
++         StorageLive(_9);
++         StorageLive(_26);
++         StorageLive(_27);
++         _26 = move _2;
++         goto -> bb10;
+      }
+  
+-     bb54 (cleanup): {
+-         StorageDead(_29);
+-         goto -> bb56;
++     bb46: {
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_7);
++         StorageLive(_9);
++         StorageLive(_28);
++         StorageLive(_29);
++         StorageLive(_45);
++         StorageLive(_46);
++         _45 = move _2;
++         goto -> bb20;
+      }
+  
+-     bb55 (cleanup): {
+-         StorageDead(_13);
+-         StorageDead(_8);
+-         goto -> bb56;
++     bb47: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb47, unwind continue];
+      }
+  
+-     bb56 (cleanup): {
+-         goto -> bb57;
++     bb48: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb48, unwind continue];
+      }
+  
+-     bb57 (cleanup): {
+-         StorageDead(_9);
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb52, unwind terminate(cleanup)];
++     bb49: {
++         StorageLive(_3);
++         _3 = copy ((*_51).0: u32);
++         StorageLive(_4);
++         _4 = copy ((*_51).1: u32);
++         nop;
++         (((*_51) as variant#3).0: u32) = copy ((*_51).2: u32);
++         nop;
++         (((*_51) as variant#3).1: u32) = copy ((*_51).3: u32);
++         StorageLive(_7);
++         nop;
++         StorageLive(_9);
++         StorageLive(_10);
++         StorageLive(_11);
++         _11 = copy _3;
++         StorageLive(_12);
++         _12 = copy _4;
++         _10 = add(move _11, move _12) -> [return: bb1, unwind: bb39];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..bd5fea3
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,217 @@
+// MIR for `build_aggregate::{closure#0}` 0 coroutine_drop
+
+fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) -> () {
+    debug _task_context => _2;
+    debug a => ((*_1).0: u32);
+    debug b => ((*_1).1: u32);
+    debug c => ((*_1).2: u32);
+    debug d => ((*_1).3: u32);
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: u32;
+    let mut _8: u32;
+    let mut _9: {async fn body of add()};
+    let mut _10: {async fn body of add()};
+    let mut _11: u32;
+    let mut _12: u32;
+    let mut _14: ();
+    let _15: ();
+    let mut _16: std::task::Poll<u32>;
+    let mut _17: std::pin::Pin<&mut {async fn body of add()}>;
+    let mut _18: &mut {async fn body of add()};
+    let mut _19: &mut {async fn body of add()};
+    let mut _20: &mut std::task::Context<'_>;
+    let mut _21: &mut std::task::Context<'_>;
+    let mut _22: &mut std::task::Context<'_>;
+    let mut _23: isize;
+    let mut _25: !;
+    let mut _26: &mut std::task::Context<'_>;
+    let mut _27: ();
+    let mut _28: u32;
+    let mut _29: {async fn body of add()};
+    let mut _30: {async fn body of add()};
+    let mut _31: u32;
+    let mut _32: u32;
+    let _34: ();
+    let mut _35: std::task::Poll<u32>;
+    let mut _36: std::pin::Pin<&mut {async fn body of add()}>;
+    let mut _37: &mut {async fn body of add()};
+    let mut _38: &mut {async fn body of add()};
+    let mut _39: &mut std::task::Context<'_>;
+    let mut _40: &mut std::task::Context<'_>;
+    let mut _41: &mut std::task::Context<'_>;
+    let mut _42: isize;
+    let mut _44: !;
+    let mut _45: &mut std::task::Context<'_>;
+    let mut _46: ();
+    let mut _47: u32;
+    let mut _48: u32;
+    let mut _49: u32;
+    let mut _50: u32;
+    scope 1 {
+        debug a => _3;
+        let _4: u32;
+        scope 2 {
+            debug b => _4;
+            let _5: u32;
+            scope 3 {
+                debug c => (((*_1) as variant#3).0: u32);
+                let _6: u32;
+                scope 4 {
+                    debug d => (((*_1) as variant#3).1: u32);
+                    let _7: (u32, u32);
+                    let mut _13: {async fn body of add()};
+                    let mut _33: {async fn body of add()};
+                    scope 5 {
+                        debug x => _7;
+                    }
+                    scope 6 {
+                        debug __awaitee => (((*_1) as variant#3).2: {async fn body of add()});
+                        let _24: u32;
+                        scope 7 {
+                            debug result => _24;
+                        }
+                    }
+                    scope 8 {
+                        debug __awaitee => (((*_1) as variant#4).1: {async fn body of add()});
+                        let _43: u32;
+                        scope 9 {
+                            debug result => _43;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _50 = discriminant((*_1));
+        switchInt(move _50) -> [0: bb16, 3: bb19, 4: bb20, otherwise: bb21];
+    }
+
+    bb1: {
+        StorageDead(_46);
+        StorageDead(_45);
+        drop((((*_1) as variant#4).1: {async fn body of add()})) -> [return: bb2, unwind: bb10];
+    }
+
+    bb2: {
+        nop;
+        StorageDead(_28);
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_29);
+        goto -> bb6;
+    }
+
+    bb4: {
+        StorageDead(_27);
+        StorageDead(_26);
+        drop((((*_1) as variant#3).2: {async fn body of add()})) -> [return: bb5, unwind: bb12];
+    }
+
+    bb5: {
+        nop;
+        nop;
+        goto -> bb6;
+    }
+
+    bb6: {
+        goto -> bb7;
+    }
+
+    bb7: {
+        StorageDead(_9);
+        StorageDead(_7);
+        nop;
+        nop;
+        StorageDead(_4);
+        StorageDead(_3);
+        goto -> bb17;
+    }
+
+    bb8: {
+        return;
+    }
+
+    bb9 (cleanup): {
+        resume;
+    }
+
+    bb10 (cleanup): {
+        nop;
+        StorageDead(_28);
+        nop;
+        goto -> bb11;
+    }
+
+    bb11 (cleanup): {
+        StorageDead(_29);
+        goto -> bb13;
+    }
+
+    bb12 (cleanup): {
+        nop;
+        nop;
+        goto -> bb13;
+    }
+
+    bb13 (cleanup): {
+        goto -> bb14;
+    }
+
+    bb14 (cleanup): {
+        StorageDead(_9);
+        StorageDead(_7);
+        nop;
+        nop;
+        StorageDead(_4);
+        StorageDead(_3);
+        goto -> bb9;
+    }
+
+    bb15: {
+        return;
+    }
+
+    bb16: {
+        goto -> bb18;
+    }
+
+    bb17: {
+        goto -> bb8;
+    }
+
+    bb18: {
+        goto -> bb15;
+    }
+
+    bb19: {
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_26);
+        StorageLive(_27);
+        goto -> bb4;
+    }
+
+    bb20: {
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_28);
+        StorageLive(_29);
+        StorageLive(_45);
+        StorageLive(_46);
+        goto -> bb1;
+    }
+
+    bb21: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..9f06ae9
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.build_aggregate-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,32 @@
+// MIR for `build_aggregate::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn build_aggregate::{closure#0}(_1: {async fn body of build_aggregate()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+                scope 4 {
+                    scope 5 {
+                    }
+                    scope 6 {
+                        scope 7 {
+                        }
+                    }
+                    scope 8 {
+                        scope 9 {
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..b902c7c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,80 @@
+- // MIR for `foo::{closure#0}::{closure#0}` before StateTransform
++ // MIR for `foo::{closure#0}::{closure#0}` after StateTransform
+  
+- fn foo::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:21:13: 21:18}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     debug y => (*(_1.0: &u32));
+-     debug z => (*(_1.1: &u32));
+-     let mut _0: u32;
++     debug y => (*((*_9).0: &u32));
++     debug z => (*((*_9).1: &u32));
++     let mut _0: std::task::Poll<u32>;
+      let mut _3: u32;
+      let mut _4: u32;
+      let mut _5: &u32;
+      let mut _6: &u32;
++     let mut _7: u32;
++     let mut _8: u32;
++     let mut _9: &mut {async block@$DIR/async_fn.rs:21:13: 21:18};
+  
+      bb0: {
+-         StorageLive(_3);
+-         _5 = no_retag copy (_1.0: &u32);
+-         _3 = copy (*_5);
+-         StorageLive(_4);
+-         _6 = no_retag copy (_1.1: &u32);
+-         _4 = copy (*_6);
+-         _0 = Add(move _3, move _4);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:21:13: 21:18});
++         _8 = discriminant((*_9));
++         switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<u32>::Ready(move _7);
++         discriminant((*_9)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         StorageLive(_3);
++         _5 = no_retag copy ((*_9).0: &u32);
++         _3 = copy (*_5);
++         StorageLive(_4);
++         _6 = no_retag copy ((*_9).1: &u32);
++         _4 = copy (*_6);
++         _7 = Add(move _3, move _4);
++         StorageDead(_4);
++         StorageDead(_3);
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..c22d1ca
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,36 @@
+// MIR for `foo::{closure#0}::{closure#0}` 0 coroutine_drop
+
+fn foo::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}) -> () {
+    debug _task_context => _2;
+    debug y => (*((*_1).0: &u32));
+    debug z => (*((*_1).1: &u32));
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let mut _3: u32;
+    let mut _4: u32;
+    let mut _5: &u32;
+    let mut _6: &u32;
+    let mut _7: u32;
+    let mut _8: u32;
+
+    bb0: {
+        _8 = discriminant((*_1));
+        switchInt(move _8) -> [0: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2: {
+        goto -> bb3;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..19fe75d
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,14 @@
+// MIR for `foo::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn foo::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:21:13: 21:18}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..86cac4a
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,432 @@
+- // MIR for `foo::{closure#0}` before StateTransform
++ // MIR for `foo::{closure#0}` after StateTransform
+  
+- fn foo::{closure#0}(_1: {async fn body of foo()}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn foo::{closure#0}(_1: Pin<&mut {async fn body of foo()}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         field _s0: &u32;
++         field _s1: u32;
++         field _s2: u32;
++         field _s3: {async block@$DIR/async_fn.rs:21:13: 21:18};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s2, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)}
++     }
+      debug _task_context => _2;
+-     debug x => (_1.0: &u32);
+-     debug y => (_1.1: u32);
+-     let mut _0: u32;
++     debug x => ((*_36).0: &u32);
++     debug y => ((*_36).1: u32);
++     coroutine debug x => _s0;
++     let mut _0: std::task::Poll<u32>;
+      let _3: &u32;
+      let mut _9: {async block@$DIR/async_fn.rs:21:13: 21:18};
+      let mut _10: {async block@$DIR/async_fn.rs:21:13: 21:18};
+      let mut _11: &u32;
+      let mut _12: &u32;
+      let mut _14: ();
+      let _15: ();
+      let mut _16: std::task::Poll<u32>;
+      let mut _17: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>;
+      let mut _18: &mut {async block@$DIR/async_fn.rs:21:13: 21:18};
+      let mut _19: &mut {async block@$DIR/async_fn.rs:21:13: 21:18};
+      let mut _20: &mut std::task::Context<'_>;
+      let mut _21: &mut std::task::Context<'_>;
+-     let mut _22: std::future::ResumeTy;
++     let mut _22: &mut std::task::Context<'_>;
+      let mut _23: isize;
+      let mut _25: !;
+-     let mut _26: std::future::ResumeTy;
++     let mut _26: &mut std::task::Context<'_>;
+      let mut _27: ();
+      let mut _30: u32;
+      let mut _31: u32;
+      let mut _32: u32;
+      let mut _33: u32;
++     let mut _34: u32;
++     let mut _35: u32;
++     let mut _36: &mut {async fn body of foo()};
++     let mut _37: &u32;
+      scope 1 {
+-         debug x => _3;
++         debug x => (((*_36) as variant#3).0: &u32);
++         coroutine debug y => _s1;
+          let _4: u32;
+          scope 2 {
+-             debug y => _4;
++             debug y => (((*_36) as variant#3).1: u32);
+              let _5: &u32;
+              scope 3 {
+                  debug y => _5;
++                 coroutine debug z => _s2;
+                  let _6: u32;
+                  scope 4 {
+-                     debug z => _6;
++                     debug z => (((*_36) as variant#3).2: u32);
+                      let _7: &u32;
+                      scope 5 {
+                          debug z => _7;
++                         coroutine debug __awaitee => _s3;
+                          let _8: u32;
+                          let mut _13: {async block@$DIR/async_fn.rs:21:13: 21:18};
+                          scope 6 {
+                              debug y => _8;
+                              let _28: u32;
+                              scope 9 {
+                                  debug a => _28;
+                                  let _29: &u32;
+                                  scope 10 {
+                                      debug a => _29;
+                                  }
+                              }
+                          }
+                          scope 7 {
+-                             debug __awaitee => _13;
++                             debug __awaitee => (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18});
+                              let _24: u32;
+                              scope 8 {
+                                  debug result => _24;
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = copy (_1.0: &u32);
+-         StorageLive(_4);
+-         _4 = copy (_1.1: u32);
+-         StorageLive(_5);
+-         _5 = &_4;
+-         StorageLive(_6);
+-         _6 = const 9_u32;
+-         StorageLive(_7);
+-         _7 = &_6;
+-         StorageLive(_8);
+-         StorageLive(_9);
+-         StorageLive(_10);
+-         StorageLive(_11);
+-         _11 = &(*_5);
+-         StorageLive(_12);
+-         _12 = &(*_7);
+-         _10 = {coroutine@$DIR/async_fn.rs:21:13: 21:18 (#0)} { y: move _11, z: move _12 };
+-         StorageDead(_12);
+-         StorageDead(_11);
+-         _9 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as IntoFuture>::into_future(move _10) -> [return: bb1, unwind: bb22];
++         _36 = copy (_1.0: &mut {async fn body of foo()});
++         _35 = discriminant((*_36));
++         switchInt(move _35) -> [0: bb26, 1: bb25, 2: bb24, 3: bb23, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageDead(_10);
+          PlaceMention(_9);
+-         StorageLive(_13);
+-         _13 = move _9;
++         nop;
++         (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18}) = move _9;
+          goto -> bb2;
+      }
+  
+      bb2: {
+          StorageLive(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          StorageLive(_19);
+-         _19 = &mut _13;
++         _19 = &mut (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18});
+          _18 = &mut (*_19);
+-         _17 = Pin::<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>::new_unchecked(move _18) -> [return: bb3, unwind: bb19];
++         _17 = Pin::<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>::new_unchecked(move _18) -> [return: bb3, unwind: bb14];
+      }
+  
+      bb3: {
+          StorageDead(_18);
+          StorageLive(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          _22 = copy _2;
+-         _21 = std::future::get_context::<'_, '_>(move _22) -> [return: bb4, unwind: bb17];
++         _21 = move _22;
++         goto -> bb4;
+      }
+  
+      bb4: {
+          _20 = &mut (*_21);
+          StorageDead(_22);
+-         _16 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as Future>::poll(move _17, move _20) -> [return: bb5, unwind: bb18];
++         _16 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as Future>::poll(move _17, move _20) -> [return: bb5, unwind: bb13];
+      }
+  
+      bb5: {
+          StorageDead(_21);
+          StorageDead(_20);
+          StorageDead(_19);
+          StorageDead(_17);
+          PlaceMention(_16);
+          _23 = discriminant(_16);
+          switchInt(move _23) -> [0: bb8, 1: bb7, otherwise: bb6];
+      }
+  
+      bb6: {
+          unreachable;
+      }
+  
+      bb7: {
+          _15 = const ();
+          StorageDead(_16);
+          StorageDead(_15);
+          StorageLive(_26);
+          StorageLive(_27);
+          _27 = ();
+-         _26 = yield(move _27) -> [resume: bb9, drop: bb13];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_5);
++         StorageDead(_7);
++         StorageDead(_8);
++         StorageDead(_9);
++         StorageDead(_26);
++         StorageDead(_27);
++         discriminant((*_36)) = 3;
++         return;
+      }
+  
+      bb8: {
+          StorageLive(_24);
+          _24 = copy ((_16 as Ready).0: u32);
+          _8 = copy _24;
+          StorageDead(_24);
+          StorageDead(_16);
+          StorageDead(_15);
+-         drop(_13) -> [return: bb10, unwind: bb21];
++         drop((((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb10, unwind: bb16];
+      }
+  
+      bb9: {
+          StorageDead(_27);
+          _2 = move _26;
+          StorageDead(_26);
+          _14 = const ();
+          goto -> bb2;
+      }
+  
+      bb10: {
+-         StorageDead(_13);
++         nop;
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_9);
+          StorageLive(_28);
+          _28 = const 10_u32;
+          StorageLive(_29);
+          _29 = &_28;
+          StorageLive(_30);
+          StorageLive(_31);
+-         _31 = copy (*_3);
++         _37 = no_retag copy (((*_36) as variant#3).0: &u32);
++         _31 = copy (*_37);
+          StorageLive(_32);
+          _32 = copy _8;
+          _30 = Add(move _31, move _32);
+          StorageDead(_32);
+          StorageDead(_31);
+          StorageLive(_33);
+          _33 = copy (*_29);
+-         _0 = Add(move _30, move _33);
++         _34 = Add(move _30, move _33);
+          StorageDead(_33);
+          StorageDead(_30);
+          StorageDead(_29);
+          StorageDead(_28);
+          StorageDead(_8);
+          StorageDead(_7);
+-         StorageDead(_6);
++         nop;
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb12, unwind: bb25];
++         nop;
++         nop;
++         goto -> bb21;
+      }
+  
+      bb12: {
++         _0 = Poll::<u32>::Ready(move _34);
++         discriminant((*_36)) = 1;
+          return;
+      }
+  
+-     bb13: {
+-         StorageDead(_27);
+-         StorageDead(_26);
+-         drop(_13) -> [return: bb14, unwind: bb26];
++     bb13 (cleanup): {
++         StorageDead(_21);
++         StorageDead(_20);
++         goto -> bb15;
+      }
+  
+-     bb14: {
+-         StorageDead(_13);
++     bb14 (cleanup): {
++         StorageDead(_18);
+          goto -> bb15;
+      }
+  
+-     bb15: {
+-         StorageDead(_9);
+-         StorageDead(_8);
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb16, unwind: bb25];
++     bb15 (cleanup): {
++         StorageDead(_19);
++         StorageDead(_17);
++         StorageDead(_16);
++         StorageDead(_15);
++         drop((((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb16, unwind terminate(cleanup)];
+      }
+  
+-     bb16: {
+-         coroutine_drop;
++     bb16 (cleanup): {
++         nop;
++         goto -> bb19;
+      }
+  
+      bb17 (cleanup): {
+-         StorageDead(_22);
+          goto -> bb18;
+      }
+  
+      bb18 (cleanup): {
+-         StorageDead(_21);
+-         StorageDead(_20);
+-         goto -> bb20;
++         StorageDead(_10);
++         goto -> bb19;
+      }
+  
+      bb19 (cleanup): {
+-         StorageDead(_18);
++         StorageDead(_9);
++         StorageDead(_8);
++         StorageDead(_7);
++         nop;
++         StorageDead(_5);
++         nop;
++         nop;
+          goto -> bb20;
+      }
+  
+      bb20 (cleanup): {
+-         StorageDead(_19);
+-         StorageDead(_17);
+-         StorageDead(_16);
+-         StorageDead(_15);
+-         drop(_13) -> [return: bb21, unwind terminate(cleanup)];
++         goto -> bb22;
+      }
+  
+-     bb21 (cleanup): {
+-         StorageDead(_13);
+-         goto -> bb24;
++     bb21: {
++         goto -> bb12;
+      }
+  
+      bb22 (cleanup): {
+-         goto -> bb23;
++         discriminant((*_36)) = 2;
++         resume;
+      }
+  
+-     bb23 (cleanup): {
+-         StorageDead(_10);
+-         goto -> bb24;
++     bb23: {
++         StorageLive(_5);
++         StorageLive(_7);
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_26);
++         StorageLive(_27);
++         _26 = move _2;
++         goto -> bb9;
+      }
+  
+-     bb24 (cleanup): {
+-         StorageDead(_9);
+-         StorageDead(_8);
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb25, unwind terminate(cleanup)];
++     bb24: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb24, unwind continue];
+      }
+  
+-     bb25 (cleanup): {
+-         resume;
++     bb25: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb25, unwind continue];
+      }
+  
+-     bb26 (cleanup): {
+-         StorageDead(_13);
+-         goto -> bb27;
+-     }
+- 
+-     bb27 (cleanup): {
+-         StorageDead(_9);
+-         StorageDead(_8);
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb25, unwind terminate(cleanup)];
++     bb26: {
++         nop;
++         (((*_36) as variant#3).0: &u32) = copy ((*_36).0: &u32);
++         nop;
++         (((*_36) as variant#3).1: u32) = copy ((*_36).1: u32);
++         StorageLive(_5);
++         _5 = &(((*_36) as variant#3).1: u32);
++         nop;
++         (((*_36) as variant#3).2: u32) = const 9_u32;
++         StorageLive(_7);
++         _7 = &(((*_36) as variant#3).2: u32);
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_10);
++         StorageLive(_11);
++         _11 = &(*_5);
++         StorageLive(_12);
++         _12 = &(*_7);
++         _10 = {coroutine@$DIR/async_fn.rs:21:13: 21:18 (#0)} { y: move _11, z: move _12 };
++         StorageDead(_12);
++         StorageDead(_11);
++         _9 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as IntoFuture>::into_future(move _10) -> [return: bb1, unwind: bb17];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..1ce52d3
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,153 @@
+// MIR for `foo::{closure#0}` 0 coroutine_drop
+
+fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () {
+    debug _task_context => _2;
+    debug x => ((*_1).0: &u32);
+    debug y => ((*_1).1: u32);
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: &u32;
+    let mut _9: {async block@$DIR/async_fn.rs:21:13: 21:18};
+    let mut _10: {async block@$DIR/async_fn.rs:21:13: 21:18};
+    let mut _11: &u32;
+    let mut _12: &u32;
+    let mut _14: ();
+    let _15: ();
+    let mut _16: std::task::Poll<u32>;
+    let mut _17: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>;
+    let mut _18: &mut {async block@$DIR/async_fn.rs:21:13: 21:18};
+    let mut _19: &mut {async block@$DIR/async_fn.rs:21:13: 21:18};
+    let mut _20: &mut std::task::Context<'_>;
+    let mut _21: &mut std::task::Context<'_>;
+    let mut _22: &mut std::task::Context<'_>;
+    let mut _23: isize;
+    let mut _25: !;
+    let mut _26: &mut std::task::Context<'_>;
+    let mut _27: ();
+    let mut _30: u32;
+    let mut _31: u32;
+    let mut _32: u32;
+    let mut _33: u32;
+    let mut _34: u32;
+    let mut _35: u32;
+    scope 1 {
+        debug x => (((*_1) as variant#3).0: &u32);
+        let _4: u32;
+        scope 2 {
+            debug y => (((*_1) as variant#3).1: u32);
+            let _5: &u32;
+            scope 3 {
+                debug y => _5;
+                let _6: u32;
+                scope 4 {
+                    debug z => (((*_1) as variant#3).2: u32);
+                    let _7: &u32;
+                    scope 5 {
+                        debug z => _7;
+                        let _8: u32;
+                        let mut _13: {async block@$DIR/async_fn.rs:21:13: 21:18};
+                        scope 6 {
+                            debug y => _8;
+                            let _28: u32;
+                            scope 9 {
+                                debug a => _28;
+                                let _29: &u32;
+                                scope 10 {
+                                    debug a => _29;
+                                }
+                            }
+                        }
+                        scope 7 {
+                            debug __awaitee => (((*_1) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18});
+                            let _24: u32;
+                            scope 8 {
+                                debug result => _24;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _35 = discriminant((*_1));
+        switchInt(move _35) -> [0: bb9, 3: bb12, otherwise: bb13];
+    }
+
+    bb1: {
+        StorageDead(_27);
+        StorageDead(_26);
+        drop((((*_1) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb2, unwind: bb6];
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageDead(_7);
+        nop;
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb10;
+    }
+
+    bb4: {
+        return;
+    }
+
+    bb5 (cleanup): {
+        resume;
+    }
+
+    bb6 (cleanup): {
+        nop;
+        goto -> bb7;
+    }
+
+    bb7 (cleanup): {
+        StorageDead(_9);
+        StorageDead(_8);
+        StorageDead(_7);
+        nop;
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb5;
+    }
+
+    bb8: {
+        return;
+    }
+
+    bb9: {
+        goto -> bb11;
+    }
+
+    bb10: {
+        goto -> bb4;
+    }
+
+    bb11: {
+        goto -> bb8;
+    }
+
+    bb12: {
+        StorageLive(_5);
+        StorageLive(_7);
+        StorageLive(_8);
+        StorageLive(_9);
+        StorageLive(_26);
+        StorageLive(_27);
+        goto -> bb1;
+    }
+
+    bb13: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..f7038fc
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.foo-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,34 @@
+// MIR for `foo::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn foo::{closure#0}(_1: {async fn body of foo()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+                scope 4 {
+                    scope 5 {
+                        scope 6 {
+                            scope 9 {
+                                scope 10 {
+                                }
+                            }
+                        }
+                        scope 7 {
+                            scope 8 {
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..fbbec5a
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,453 @@
+- // MIR for `hello_world::{closure#0}` before StateTransform
++ // MIR for `hello_world::{closure#0}` after StateTransform
+  
+- fn hello_world::{closure#0}(_1: {async fn body of hello_world()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn hello_world::{closure#0}(_1: Pin<&mut {async fn body of hello_world()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: [u8; 1];
++         field _s1: &[u8];
++         field _s2: [u8; 1];
++         field _s3: {async fn body of read_exact()};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s2, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug data => _s0;
++     let mut _0: std::task::Poll<()>;
+      let _3: [u8; 1];
+      let _5: &[u8];
+      let mut _6: &[u8; 1];
+      let mut _7: std::ops::RangeFull;
+      let _9: ();
+      let mut _10: std::option::Option<()>;
+      let mut _11: {async fn body of read_exact()};
+      let mut _12: {async fn body of read_exact()};
+      let mut _13: &mut &[u8];
+      let mut _14: &mut &[u8];
+      let mut _15: &mut [u8];
+      let mut _16: &mut [u8; 1];
+      let mut _17: &mut [u8; 1];
+      let mut _19: ();
+      let _20: ();
+      let mut _21: std::task::Poll<std::option::Option<()>>;
+      let mut _22: std::pin::Pin<&mut {async fn body of read_exact()}>;
+      let mut _23: &mut {async fn body of read_exact()};
+      let mut _24: &mut {async fn body of read_exact()};
+      let mut _25: &mut std::task::Context<'_>;
+      let mut _26: &mut std::task::Context<'_>;
+-     let mut _27: std::future::ResumeTy;
++     let mut _27: &mut std::task::Context<'_>;
+      let mut _28: isize;
+      let mut _30: !;
+-     let mut _31: std::future::ResumeTy;
++     let mut _31: &mut std::task::Context<'_>;
+      let mut _32: ();
++     let mut _33: ();
++     let mut _34: u32;
++     let mut _35: &mut {async fn body of hello_world()};
+      scope 1 {
+-         debug data => _3;
++         debug data => (((*_35) as variant#3).0: [u8; 1]);
++         coroutine debug reader => _s1;
+          let mut _4: &[u8];
+          scope 2 {
+-             debug reader => _4;
++             debug reader => (((*_35) as variant#3).1: &[u8]);
++             coroutine debug marker => _s2;
+              let mut _8: [u8; 1];
+              scope 3 {
+-                 debug marker => _8;
++                 debug marker => (((*_35) as variant#3).2: [u8; 1]);
++                 coroutine debug __awaitee => _s3;
+                  let mut _18: {async fn body of read_exact()};
+                  scope 4 {
+-                     debug __awaitee => _18;
++                     debug __awaitee => (((*_35) as variant#3).3: {async fn body of read_exact()});
+                      let _29: std::option::Option<()>;
+                      scope 5 {
+                          debug result => _29;
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = [const 0_u8; 1];
+-         StorageLive(_4);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = &_3;
+-         StorageLive(_7);
+-         _7 = RangeFull;
+-         _5 = <[u8; 1] as Index<RangeFull>>::index(move _6, move _7) -> [return: bb1, unwind: bb30];
++         _35 = copy (_1.0: &mut {async fn body of hello_world()});
++         _34 = discriminant((*_35));
++         switchInt(move _34) -> [0: bb33, 1: bb32, 2: bb31, 3: bb30, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageDead(_7);
+          StorageDead(_6);
+-         _4 = &(*_5);
+-         StorageLive(_8);
+-         _8 = [const 0_u8; 1];
++         (((*_35) as variant#3).1: &[u8]) = &(*_5);
++         nop;
++         (((*_35) as variant#3).2: [u8; 1]) = [const 0_u8; 1];
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+-         _14 = &mut _4;
++         _14 = &mut (((*_35) as variant#3).1: &[u8]);
+          _13 = &mut (*_14);
+          StorageLive(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+-         _17 = &mut _8;
++         _17 = &mut (((*_35) as variant#3).2: [u8; 1]);
+          _16 = &mut (*_17);
+          _15 = move _16 as &mut [u8] (PointerCoercion(Unsize, Implicit));
+          StorageDead(_16);
+-         _12 = read_exact(move _13, move _15) -> [return: bb2, unwind: bb27];
++         _12 = read_exact(move _13, move _15) -> [return: bb2, unwind: bb22];
+      }
+  
+      bb2: {
+          StorageDead(_15);
+          StorageDead(_13);
+-         _11 = <{async fn body of read_exact()} as IntoFuture>::into_future(move _12) -> [return: bb3, unwind: bb26];
++         _11 = <{async fn body of read_exact()} as IntoFuture>::into_future(move _12) -> [return: bb3, unwind: bb21];
+      }
+  
+      bb3: {
+          StorageDead(_12);
+          PlaceMention(_11);
+-         StorageLive(_18);
+-         _18 = move _11;
++         nop;
++         (((*_35) as variant#3).3: {async fn body of read_exact()}) = move _11;
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageLive(_20);
+          StorageLive(_21);
+          StorageLive(_22);
+          StorageLive(_23);
+          StorageLive(_24);
+-         _24 = &mut _18;
++         _24 = &mut (((*_35) as variant#3).3: {async fn body of read_exact()});
+          _23 = &mut (*_24);
+-         _22 = Pin::<&mut {async fn body of read_exact()}>::new_unchecked(move _23) -> [return: bb5, unwind: bb22];
++         _22 = Pin::<&mut {async fn body of read_exact()}>::new_unchecked(move _23) -> [return: bb5, unwind: bb17];
+      }
+  
+      bb5: {
+          StorageDead(_23);
+          StorageLive(_25);
+          StorageLive(_26);
+          StorageLive(_27);
+          _27 = copy _2;
+-         _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb6, unwind: bb20];
++         _26 = move _27;
++         goto -> bb6;
+      }
+  
+      bb6: {
+          _25 = &mut (*_26);
+          StorageDead(_27);
+-         _21 = <{async fn body of read_exact()} as Future>::poll(move _22, move _25) -> [return: bb7, unwind: bb21];
++         _21 = <{async fn body of read_exact()} as Future>::poll(move _22, move _25) -> [return: bb7, unwind: bb16];
+      }
+  
+      bb7: {
+          StorageDead(_26);
+          StorageDead(_25);
+          StorageDead(_24);
+          StorageDead(_22);
+          PlaceMention(_21);
+          _28 = discriminant(_21);
+          switchInt(move _28) -> [0: bb10, 1: bb9, otherwise: bb8];
+      }
+  
+      bb8: {
+          unreachable;
+      }
+  
+      bb9: {
+          _20 = const ();
+          StorageDead(_21);
+          StorageDead(_20);
+          StorageLive(_31);
+          StorageLive(_32);
+          _32 = ();
+-         _31 = yield(move _32) -> [resume: bb11, drop: bb16];
++         _0 = Poll::<()>::Pending;
++         StorageDead(_5);
++         StorageDead(_9);
++         StorageDead(_10);
++         StorageDead(_11);
++         StorageDead(_14);
++         StorageDead(_17);
++         StorageDead(_31);
++         StorageDead(_32);
++         discriminant((*_35)) = 3;
++         return;
+      }
+  
+      bb10: {
+          StorageLive(_29);
+          _29 = copy ((_21 as Ready).0: std::option::Option<()>);
+          _10 = copy _29;
+          StorageDead(_29);
+          StorageDead(_21);
+          StorageDead(_20);
+-         drop(_18) -> [return: bb12, unwind: bb24];
++         drop((((*_35) as variant#3).3: {async fn body of read_exact()})) -> [return: bb12, unwind: bb19];
+      }
+  
+      bb11: {
+          StorageDead(_32);
+          _2 = move _31;
+          StorageDead(_31);
+          _19 = const ();
+          goto -> bb4;
+      }
+  
+      bb12: {
+-         StorageDead(_18);
+-         _9 = Option::<()>::unwrap(move _10) -> [return: bb13, unwind: bb25];
++         nop;
++         _9 = Option::<()>::unwrap(move _10) -> [return: bb13, unwind: bb20];
+      }
+  
+      bb13: {
+          StorageDead(_10);
+          goto -> bb14;
+      }
+  
+      bb14: {
+          StorageDead(_17);
+          StorageDead(_14);
+          StorageDead(_11);
+          StorageDead(_9);
+-         _0 = const ();
+-         StorageDead(_8);
++         _33 = const ();
++         nop;
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb15, unwind: bb32];
++         nop;
++         nop;
++         goto -> bb28;
+      }
+  
+      bb15: {
++         _0 = Poll::<()>::Ready(move _33);
++         discriminant((*_35)) = 1;
+          return;
+      }
+  
+-     bb16: {
+-         StorageDead(_32);
+-         StorageDead(_31);
+-         drop(_18) -> [return: bb17, unwind: bb33];
+-     }
+- 
+-     bb17: {
+-         StorageDead(_18);
+-         StorageDead(_10);
+-         goto -> bb18;
+-     }
+- 
+-     bb18: {
+-         StorageDead(_17);
+-         StorageDead(_14);
+-         StorageDead(_11);
+-         StorageDead(_9);
+-         StorageDead(_8);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb19, unwind: bb32];
+-     }
+- 
+-     bb19: {
+-         coroutine_drop;
+-     }
+- 
+-     bb20 (cleanup): {
+-         StorageDead(_27);
+-         goto -> bb21;
+-     }
+- 
+-     bb21 (cleanup): {
++     bb16 (cleanup): {
+          StorageDead(_26);
+          StorageDead(_25);
+-         goto -> bb23;
++         goto -> bb18;
+      }
+  
+-     bb22 (cleanup): {
++     bb17 (cleanup): {
+          StorageDead(_23);
+-         goto -> bb23;
++         goto -> bb18;
+      }
+  
+-     bb23 (cleanup): {
++     bb18 (cleanup): {
+          StorageDead(_24);
+          StorageDead(_22);
+          StorageDead(_21);
+          StorageDead(_20);
+-         drop(_18) -> [return: bb24, unwind terminate(cleanup)];
++         drop((((*_35) as variant#3).3: {async fn body of read_exact()})) -> [return: bb19, unwind terminate(cleanup)];
+      }
+  
+-     bb24 (cleanup): {
+-         StorageDead(_18);
+-         goto -> bb25;
++     bb19 (cleanup): {
++         nop;
++         goto -> bb20;
+      }
+  
+-     bb25 (cleanup): {
++     bb20 (cleanup): {
+          StorageDead(_10);
+-         goto -> bb29;
++         goto -> bb24;
+      }
+  
+-     bb26 (cleanup): {
+-         goto -> bb28;
++     bb21 (cleanup): {
++         goto -> bb23;
+      }
+  
+-     bb27 (cleanup): {
++     bb22 (cleanup): {
+          StorageDead(_15);
+          StorageDead(_13);
+-         goto -> bb28;
++         goto -> bb23;
+      }
+  
+-     bb28 (cleanup): {
++     bb23 (cleanup): {
+          StorageDead(_12);
+          StorageDead(_10);
+-         goto -> bb29;
++         goto -> bb24;
+      }
+  
+-     bb29 (cleanup): {
++     bb24 (cleanup): {
+          StorageDead(_17);
+          StorageDead(_14);
+          StorageDead(_11);
+          StorageDead(_9);
+-         StorageDead(_8);
+-         goto -> bb31;
++         nop;
++         goto -> bb26;
+      }
+  
+-     bb30 (cleanup): {
++     bb25 (cleanup): {
+          StorageDead(_7);
+          StorageDead(_6);
+-         goto -> bb31;
++         goto -> bb26;
+      }
+  
+-     bb31 (cleanup): {
++     bb26 (cleanup): {
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb32, unwind terminate(cleanup)];
++         nop;
++         nop;
++         goto -> bb27;
+      }
+  
+-     bb32 (cleanup): {
++     bb27 (cleanup): {
++         goto -> bb29;
++     }
++ 
++     bb28: {
++         goto -> bb15;
++     }
++ 
++     bb29 (cleanup): {
++         discriminant((*_35)) = 2;
+          resume;
+      }
+  
+-     bb33 (cleanup): {
+-         StorageDead(_18);
+-         StorageDead(_10);
+-         goto -> bb34;
++     bb30: {
++         StorageLive(_5);
++         StorageLive(_9);
++         StorageLive(_10);
++         StorageLive(_11);
++         StorageLive(_14);
++         StorageLive(_17);
++         StorageLive(_31);
++         StorageLive(_32);
++         _31 = move _2;
++         goto -> bb11;
+      }
+  
+-     bb34 (cleanup): {
+-         StorageDead(_17);
+-         StorageDead(_14);
+-         StorageDead(_11);
+-         StorageDead(_9);
+-         StorageDead(_8);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb32, unwind terminate(cleanup)];
++     bb31: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb31, unwind continue];
++     }
++ 
++     bb32: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb32, unwind continue];
++     }
++ 
++     bb33: {
++         nop;
++         (((*_35) as variant#3).0: [u8; 1]) = [const 0_u8; 1];
++         nop;
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = &(((*_35) as variant#3).0: [u8; 1]);
++         StorageLive(_7);
++         _7 = RangeFull;
++         _5 = <[u8; 1] as Index<RangeFull>>::index(move _6, move _7) -> [return: bb1, unwind: bb25];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..2fd801f
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,141 @@
+// MIR for `hello_world::{closure#0}` 0 coroutine_drop
+
+fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () {
+    debug _task_context => _2;
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: [u8; 1];
+    let _5: &[u8];
+    let mut _6: &[u8; 1];
+    let mut _7: std::ops::RangeFull;
+    let _9: ();
+    let mut _10: std::option::Option<()>;
+    let mut _11: {async fn body of read_exact()};
+    let mut _12: {async fn body of read_exact()};
+    let mut _13: &mut &[u8];
+    let mut _14: &mut &[u8];
+    let mut _15: &mut [u8];
+    let mut _16: &mut [u8; 1];
+    let mut _17: &mut [u8; 1];
+    let mut _19: ();
+    let _20: ();
+    let mut _21: std::task::Poll<std::option::Option<()>>;
+    let mut _22: std::pin::Pin<&mut {async fn body of read_exact()}>;
+    let mut _23: &mut {async fn body of read_exact()};
+    let mut _24: &mut {async fn body of read_exact()};
+    let mut _25: &mut std::task::Context<'_>;
+    let mut _26: &mut std::task::Context<'_>;
+    let mut _27: &mut std::task::Context<'_>;
+    let mut _28: isize;
+    let mut _30: !;
+    let mut _31: &mut std::task::Context<'_>;
+    let mut _32: ();
+    let mut _33: ();
+    let mut _34: u32;
+    scope 1 {
+        debug data => (((*_1) as variant#3).0: [u8; 1]);
+        let mut _4: &[u8];
+        scope 2 {
+            debug reader => (((*_1) as variant#3).1: &[u8]);
+            let mut _8: [u8; 1];
+            scope 3 {
+                debug marker => (((*_1) as variant#3).2: [u8; 1]);
+                let mut _18: {async fn body of read_exact()};
+                scope 4 {
+                    debug __awaitee => (((*_1) as variant#3).3: {async fn body of read_exact()});
+                    let _29: std::option::Option<()>;
+                    scope 5 {
+                        debug result => _29;
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _34 = discriminant((*_1));
+        switchInt(move _34) -> [0: bb9, 3: bb12, otherwise: bb13];
+    }
+
+    bb1: {
+        StorageDead(_32);
+        StorageDead(_31);
+        drop((((*_1) as variant#3).3: {async fn body of read_exact()})) -> [return: bb2, unwind: bb6];
+    }
+
+    bb2: {
+        nop;
+        StorageDead(_10);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_17);
+        StorageDead(_14);
+        StorageDead(_11);
+        StorageDead(_9);
+        nop;
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb10;
+    }
+
+    bb4: {
+        return;
+    }
+
+    bb5 (cleanup): {
+        resume;
+    }
+
+    bb6 (cleanup): {
+        nop;
+        StorageDead(_10);
+        goto -> bb7;
+    }
+
+    bb7 (cleanup): {
+        StorageDead(_17);
+        StorageDead(_14);
+        StorageDead(_11);
+        StorageDead(_9);
+        nop;
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb5;
+    }
+
+    bb8: {
+        return;
+    }
+
+    bb9: {
+        goto -> bb11;
+    }
+
+    bb10: {
+        goto -> bb4;
+    }
+
+    bb11: {
+        goto -> bb8;
+    }
+
+    bb12: {
+        StorageLive(_5);
+        StorageLive(_9);
+        StorageLive(_10);
+        StorageLive(_11);
+        StorageLive(_14);
+        StorageLive(_17);
+        StorageLive(_31);
+        StorageLive(_32);
+        goto -> bb1;
+    }
+
+    bb13: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..f611658
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.hello_world-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,24 @@
+// MIR for `hello_world::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn hello_world::{closure#0}(_1: {async fn body of hello_world()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+                scope 4 {
+                    scope 5 {
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..00bddd7
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,78 @@
+- // MIR for `includes_never::{closure#0}::{closure#0}` before StateTransform
++ // MIR for `includes_never::{closure#0}::{closure#0}` after StateTransform
+  
+- fn includes_never::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:61:18: 61:23}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn includes_never::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     debug x => (*(_1.0: &u32));
+-     let mut _0: u32;
++     debug x => (*((*_9).0: &u32));
++     let mut _0: std::task::Poll<u32>;
+      let mut _3: u32;
+      let mut _4: u32;
+      let mut _5: &u32;
+      let mut _6: &u32;
++     let mut _7: u32;
++     let mut _8: u32;
++     let mut _9: &mut {async block@$DIR/async_fn.rs:61:18: 61:23};
+  
+      bb0: {
+-         StorageLive(_3);
+-         _5 = no_retag copy (_1.0: &u32);
+-         _3 = copy (*_5);
+-         StorageLive(_4);
+-         _6 = no_retag copy (_1.0: &u32);
+-         _4 = copy (*_6);
+-         _0 = Mul(move _3, move _4);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:61:18: 61:23});
++         _8 = discriminant((*_9));
++         switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<u32>::Ready(move _7);
++         discriminant((*_9)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         StorageLive(_3);
++         _5 = no_retag copy ((*_9).0: &u32);
++         _3 = copy (*_5);
++         StorageLive(_4);
++         _6 = no_retag copy ((*_9).0: &u32);
++         _4 = copy (*_6);
++         _7 = Mul(move _3, move _4);
++         StorageDead(_4);
++         StorageDead(_3);
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..a17dbe3
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,35 @@
+// MIR for `includes_never::{closure#0}::{closure#0}` 0 coroutine_drop
+
+fn includes_never::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}) -> () {
+    debug _task_context => _2;
+    debug x => (*((*_1).0: &u32));
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let mut _3: u32;
+    let mut _4: u32;
+    let mut _5: &u32;
+    let mut _6: &u32;
+    let mut _7: u32;
+    let mut _8: u32;
+
+    bb0: {
+        _8 = discriminant((*_1));
+        switchInt(move _8) -> [0: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2: {
+        goto -> bb3;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..11fefd8
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,14 @@
+// MIR for `includes_never::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn includes_never::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:61:18: 61:23}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.StateTransform.diff"
new file mode 100644
index 0000000..b516426
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.StateTransform.diff"
@@ -0,0 +1,78 @@
+- // MIR for `includes_never::{closure#0}::{closure#1}` before StateTransform
++ // MIR for `includes_never::{closure#0}::{closure#1}` after StateTransform
+  
+- fn includes_never::{closure#0}::{closure#1}(_1: {async block@$DIR/async_fn.rs:67:15: 67:20}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn includes_never::{closure#0}::{closure#1}(_1: Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     debug x => (*(_1.0: &u32));
+-     let mut _0: u32;
++     debug x => (*((*_9).0: &u32));
++     let mut _0: std::task::Poll<u32>;
+      let mut _3: u32;
+      let mut _4: u32;
+      let mut _5: &u32;
+      let mut _6: &u32;
++     let mut _7: u32;
++     let mut _8: u32;
++     let mut _9: &mut {async block@$DIR/async_fn.rs:67:15: 67:20};
+  
+      bb0: {
+-         StorageLive(_3);
+-         _5 = no_retag copy (_1.0: &u32);
+-         _3 = copy (*_5);
+-         StorageLive(_4);
+-         _6 = no_retag copy (_1.0: &u32);
+-         _4 = copy (*_6);
+-         _0 = Add(move _3, move _4);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:67:15: 67:20});
++         _8 = discriminant((*_9));
++         switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<u32>::Ready(move _7);
++         discriminant((*_9)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         StorageLive(_3);
++         _5 = no_retag copy ((*_9).0: &u32);
++         _3 = copy (*_5);
++         StorageLive(_4);
++         _6 = no_retag copy ((*_9).0: &u32);
++         _4 = copy (*_6);
++         _7 = Add(move _3, move _4);
++         StorageDead(_4);
++         StorageDead(_3);
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..bf47e4c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop.0.mir"
@@ -0,0 +1,35 @@
+// MIR for `includes_never::{closure#0}::{closure#1}` 0 coroutine_drop
+
+fn includes_never::{closure#0}::{closure#1}(_1: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}) -> () {
+    debug _task_context => _2;
+    debug x => (*((*_1).0: &u32));
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let mut _3: u32;
+    let mut _4: u32;
+    let mut _5: &u32;
+    let mut _6: &u32;
+    let mut _7: u32;
+    let mut _8: u32;
+
+    bb0: {
+        _8 = discriminant((*_1));
+        switchInt(move _8) -> [0: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2: {
+        goto -> bb3;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..8daa763
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175-\173closure\0431\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,14 @@
+// MIR for `includes_never::{closure#0}::{closure#1}` 0 coroutine_drop_proxy_async
+
+fn includes_never::{closure#0}::{closure#1}(_1: {async block@$DIR/async_fn.rs:67:15: 67:20}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..b3d14b5
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,412 @@
+- // MIR for `includes_never::{closure#0}` before StateTransform
++ // MIR for `includes_never::{closure#0}` after StateTransform
+  
+- fn includes_never::{closure#0}(_1: {async fn body of includes_never()}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn includes_never::{closure#0}(_1: Pin<&mut {async fn body of includes_never()}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         field _s0: bool;
++         field _s1: u32;
++         field _s2: {async block@$DIR/async_fn.rs:61:18: 61:23};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s2],
++         }
++         storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)}
++     }
+      debug _task_context => _2;
+-     debug crash => (_1.0: bool);
+-     debug x => (_1.1: u32);
+-     let mut _0: u32;
++     debug crash => ((*_50).0: bool);
++     debug x => ((*_50).1: u32);
++     coroutine debug crash => _s0;
++     let mut _0: std::task::Poll<u32>;
+      let _3: bool;
+      let mut _6: {async block@$DIR/async_fn.rs:61:18: 61:23};
+      let mut _7: {async block@$DIR/async_fn.rs:61:18: 61:23};
+      let mut _8: &u32;
+      let mut _10: ();
+      let _11: ();
+      let mut _12: std::task::Poll<u32>;
+      let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>;
+      let mut _14: &mut {async block@$DIR/async_fn.rs:61:18: 61:23};
+      let mut _15: &mut {async block@$DIR/async_fn.rs:61:18: 61:23};
+      let mut _16: &mut std::task::Context<'_>;
+      let mut _17: &mut std::task::Context<'_>;
+-     let mut _18: std::future::ResumeTy;
++     let mut _18: &mut std::task::Context<'_>;
+      let mut _19: isize;
+      let mut _21: !;
+-     let mut _22: std::future::ResumeTy;
++     let mut _22: &mut std::task::Context<'_>;
+      let mut _23: ();
+      let _24: ();
+      let mut _25: bool;
+      let mut _26: !;
+      let mut _28: u32;
+      let mut _29: {async block@$DIR/async_fn.rs:67:15: 67:20};
+      let mut _30: {async block@$DIR/async_fn.rs:67:15: 67:20};
+      let mut _31: &u32;
+      let _33: ();
+      let mut _34: std::task::Poll<u32>;
+      let mut _35: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>;
+      let mut _36: &mut {async block@$DIR/async_fn.rs:67:15: 67:20};
+      let mut _37: &mut {async block@$DIR/async_fn.rs:67:15: 67:20};
+      let mut _38: &mut std::task::Context<'_>;
+      let mut _39: &mut std::task::Context<'_>;
+      let mut _40: std::future::ResumeTy;
+      let mut _41: isize;
+      let mut _43: !;
+      let mut _44: std::future::ResumeTy;
+      let mut _45: ();
+      let _46: ();
+      let mut _47: Never;
++     let mut _48: u32;
++     let mut _49: u32;
++     let mut _50: &mut {async fn body of includes_never()};
+      scope 1 {
+-         debug crash => _3;
++         debug crash => (((*_50) as variant#3).0: bool);
++         coroutine debug x => _s1;
+          let _4: u32;
+          scope 2 {
+-             debug x => _4;
++             debug x => (((*_50) as variant#3).1: u32);
++             coroutine debug __awaitee => _s2;
+              let _5: u32;
+              let mut _9: {async block@$DIR/async_fn.rs:61:18: 61:23};
+              scope 3 {
+                  debug result => _5;
+                  scope 6 {
+                      debug bad => _27;
+                      let mut _32: {async block@$DIR/async_fn.rs:67:15: 67:20};
+                      scope 8 {
+                          debug __awaitee => _32;
+                          let _42: u32;
+                          scope 9 {
+                              debug result => _42;
+                          }
+                      }
+                  }
+                  scope 7 {
+                      let _27: Never;
+                  }
+              }
+              scope 4 {
+-                 debug __awaitee => _9;
++                 debug __awaitee => (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23});
+                  let _20: u32;
+                  scope 5 {
+                      debug result => _20;
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = copy (_1.0: bool);
+-         StorageLive(_4);
+-         _4 = copy (_1.1: u32);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         StorageLive(_7);
+-         StorageLive(_8);
+-         _8 = &_4;
+-         _7 = {coroutine@$DIR/async_fn.rs:61:18: 61:23 (#0)} { x: move _8 };
+-         StorageDead(_8);
+-         _6 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as IntoFuture>::into_future(move _7) -> [return: bb1, unwind: bb25];
++         _50 = copy (_1.0: &mut {async fn body of includes_never()});
++         _49 = discriminant((*_50));
++         switchInt(move _49) -> [0: bb30, 1: bb29, 2: bb28, 3: bb27, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageDead(_7);
+          PlaceMention(_6);
+-         StorageLive(_9);
+-         _9 = move _6;
++         nop;
++         (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23}) = move _6;
+          goto -> bb2;
+      }
+  
+      bb2: {
+          StorageLive(_11);
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+-         _15 = &mut _9;
++         _15 = &mut (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23});
+          _14 = &mut (*_15);
+-         _13 = Pin::<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>::new_unchecked(move _14) -> [return: bb3, unwind: bb22];
++         _13 = Pin::<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>::new_unchecked(move _14) -> [return: bb3, unwind: bb17];
+      }
+  
+      bb3: {
+          StorageDead(_14);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          _18 = copy _2;
+-         _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb4, unwind: bb20];
++         _17 = move _18;
++         goto -> bb4;
+      }
+  
+      bb4: {
+          _16 = &mut (*_17);
+          StorageDead(_18);
+-         _12 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as Future>::poll(move _13, move _16) -> [return: bb5, unwind: bb21];
++         _12 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as Future>::poll(move _13, move _16) -> [return: bb5, unwind: bb16];
+      }
+  
+      bb5: {
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_15);
+          StorageDead(_13);
+          PlaceMention(_12);
+          _19 = discriminant(_12);
+          switchInt(move _19) -> [0: bb8, 1: bb7, otherwise: bb6];
+      }
+  
+      bb6: {
+          unreachable;
+      }
+  
+      bb7: {
+          _11 = const ();
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageLive(_22);
+          StorageLive(_23);
+          _23 = ();
+-         _22 = yield(move _23) -> [resume: bb9, drop: bb15];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_5);
++         StorageDead(_6);
++         StorageDead(_22);
++         StorageDead(_23);
++         discriminant((*_50)) = 3;
++         return;
+      }
+  
+      bb8: {
+          StorageLive(_20);
+          _20 = copy ((_12 as Ready).0: u32);
+          _5 = copy _20;
+          StorageDead(_20);
+          StorageDead(_12);
+          StorageDead(_11);
+-         drop(_9) -> [return: bb10, unwind: bb24];
++         drop((((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb10, unwind: bb19];
+      }
+  
+      bb9: {
+          StorageDead(_23);
+          _2 = move _22;
+          StorageDead(_22);
+          _10 = const ();
+          goto -> bb2;
+      }
+  
+      bb10: {
+-         StorageDead(_9);
++         nop;
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_6);
+          StorageLive(_24);
+          StorageLive(_25);
+-         _25 = copy _3;
++         _25 = copy (((*_50) as variant#3).0: bool);
+          switchInt(move _25) -> [0: bb12, otherwise: bb13];
+      }
+  
+      bb12: {
+-         _0 = copy _5;
++         _48 = copy _5;
+          StorageDead(_25);
+          StorageDead(_24);
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb14, unwind: bb29];
++         nop;
++         nop;
++         goto -> bb25;
+      }
+  
+      bb13: {
+          _24 = const ();
+          StorageDead(_25);
+          StorageDead(_24);
+          StorageLive(_27);
+-         _27 = never() -> bb19;
++         _27 = never() -> bb15;
+      }
+  
+      bb14: {
++         _0 = Poll::<u32>::Ready(move _48);
++         discriminant((*_50)) = 1;
+          return;
+      }
+  
+-     bb15: {
+-         StorageDead(_23);
+-         StorageDead(_22);
+-         drop(_9) -> [return: bb16, unwind: bb30];
++     bb15 (cleanup): {
++         StorageDead(_27);
++         goto -> bb23;
+      }
+  
+-     bb16: {
+-         StorageDead(_9);
+-         goto -> bb17;
++     bb16 (cleanup): {
++         StorageDead(_17);
++         StorageDead(_16);
++         goto -> bb18;
+      }
+  
+-     bb17: {
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb18, unwind: bb29];
++     bb17 (cleanup): {
++         StorageDead(_14);
++         goto -> bb18;
+      }
+  
+-     bb18: {
+-         coroutine_drop;
++     bb18 (cleanup): {
++         StorageDead(_15);
++         StorageDead(_13);
++         StorageDead(_12);
++         StorageDead(_11);
++         drop((((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb19, unwind terminate(cleanup)];
+      }
+  
+      bb19 (cleanup): {
+-         StorageDead(_27);
+-         goto -> bb28;
++         nop;
++         goto -> bb22;
+      }
+  
+      bb20 (cleanup): {
+-         StorageDead(_18);
+          goto -> bb21;
+      }
+  
+      bb21 (cleanup): {
+-         StorageDead(_17);
+-         StorageDead(_16);
+-         goto -> bb23;
++         StorageDead(_7);
++         goto -> bb22;
+      }
+  
+      bb22 (cleanup): {
+-         StorageDead(_14);
++         StorageDead(_6);
+          goto -> bb23;
+      }
+  
+      bb23 (cleanup): {
+-         StorageDead(_15);
+-         StorageDead(_13);
+-         StorageDead(_12);
+-         StorageDead(_11);
+-         drop(_9) -> [return: bb24, unwind terminate(cleanup)];
++         StorageDead(_5);
++         nop;
++         nop;
++         goto -> bb24;
+      }
+  
+      bb24 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb27;
++         goto -> bb26;
+      }
+  
+-     bb25 (cleanup): {
+-         goto -> bb26;
++     bb25: {
++         goto -> bb14;
+      }
+  
+      bb26 (cleanup): {
+-         StorageDead(_7);
+-         goto -> bb27;
++         discriminant((*_50)) = 2;
++         resume;
+      }
+  
+-     bb27 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb28;
++     bb27: {
++         StorageLive(_5);
++         StorageLive(_6);
++         StorageLive(_22);
++         StorageLive(_23);
++         _22 = move _2;
++         goto -> bb9;
+      }
+  
+-     bb28 (cleanup): {
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb29, unwind terminate(cleanup)];
++     bb28: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb28, unwind continue];
+      }
+  
+-     bb29 (cleanup): {
+-         resume;
++     bb29: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind continue];
+      }
+  
+-     bb30 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb31;
+-     }
+- 
+-     bb31 (cleanup): {
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb29, unwind terminate(cleanup)];
++     bb30: {
++         nop;
++         (((*_50) as variant#3).0: bool) = copy ((*_50).0: bool);
++         nop;
++         (((*_50) as variant#3).1: u32) = copy ((*_50).1: u32);
++         StorageLive(_5);
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_8);
++         _8 = &(((*_50) as variant#3).1: u32);
++         _7 = {coroutine@$DIR/async_fn.rs:61:18: 61:23 (#0)} { x: move _8 };
++         StorageDead(_8);
++         _6 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as IntoFuture>::into_future(move _7) -> [return: bb1, unwind: bb20];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..a701710
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,155 @@
+// MIR for `includes_never::{closure#0}` 0 coroutine_drop
+
+fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> () {
+    debug _task_context => _2;
+    debug crash => ((*_1).0: bool);
+    debug x => ((*_1).1: u32);
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: bool;
+    let mut _6: {async block@$DIR/async_fn.rs:61:18: 61:23};
+    let mut _7: {async block@$DIR/async_fn.rs:61:18: 61:23};
+    let mut _8: &u32;
+    let mut _10: ();
+    let _11: ();
+    let mut _12: std::task::Poll<u32>;
+    let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>;
+    let mut _14: &mut {async block@$DIR/async_fn.rs:61:18: 61:23};
+    let mut _15: &mut {async block@$DIR/async_fn.rs:61:18: 61:23};
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: isize;
+    let mut _21: !;
+    let mut _22: &mut std::task::Context<'_>;
+    let mut _23: ();
+    let _24: ();
+    let mut _25: bool;
+    let mut _26: !;
+    let mut _28: u32;
+    let mut _29: {async block@$DIR/async_fn.rs:67:15: 67:20};
+    let mut _30: {async block@$DIR/async_fn.rs:67:15: 67:20};
+    let mut _31: &u32;
+    let _33: ();
+    let mut _34: std::task::Poll<u32>;
+    let mut _35: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>;
+    let mut _36: &mut {async block@$DIR/async_fn.rs:67:15: 67:20};
+    let mut _37: &mut {async block@$DIR/async_fn.rs:67:15: 67:20};
+    let mut _38: &mut std::task::Context<'_>;
+    let mut _39: &mut std::task::Context<'_>;
+    let mut _40: std::future::ResumeTy;
+    let mut _41: isize;
+    let mut _43: !;
+    let mut _44: std::future::ResumeTy;
+    let mut _45: ();
+    let _46: ();
+    let mut _47: Never;
+    let mut _48: u32;
+    let mut _49: u32;
+    scope 1 {
+        debug crash => (((*_1) as variant#3).0: bool);
+        let _4: u32;
+        scope 2 {
+            debug x => (((*_1) as variant#3).1: u32);
+            let _5: u32;
+            let mut _9: {async block@$DIR/async_fn.rs:61:18: 61:23};
+            scope 3 {
+                debug result => _5;
+                scope 6 {
+                    debug bad => _27;
+                    let mut _32: {async block@$DIR/async_fn.rs:67:15: 67:20};
+                    scope 8 {
+                        debug __awaitee => _32;
+                        let _42: u32;
+                        scope 9 {
+                            debug result => _42;
+                        }
+                    }
+                }
+                scope 7 {
+                    let _27: Never;
+                }
+            }
+            scope 4 {
+                debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23});
+                let _20: u32;
+                scope 5 {
+                    debug result => _20;
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _49 = discriminant((*_1));
+        switchInt(move _49) -> [0: bb9, 3: bb12, otherwise: bb13];
+    }
+
+    bb1: {
+        StorageDead(_23);
+        StorageDead(_22);
+        drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb2, unwind: bb6];
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_6);
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb10;
+    }
+
+    bb4: {
+        return;
+    }
+
+    bb5 (cleanup): {
+        resume;
+    }
+
+    bb6 (cleanup): {
+        nop;
+        goto -> bb7;
+    }
+
+    bb7 (cleanup): {
+        StorageDead(_6);
+        StorageDead(_5);
+        nop;
+        nop;
+        goto -> bb5;
+    }
+
+    bb8: {
+        return;
+    }
+
+    bb9: {
+        goto -> bb11;
+    }
+
+    bb10: {
+        goto -> bb4;
+    }
+
+    bb11: {
+        goto -> bb8;
+    }
+
+    bb12: {
+        StorageLive(_5);
+        StorageLive(_6);
+        StorageLive(_22);
+        StorageLive(_23);
+        goto -> bb1;
+    }
+
+    bb13: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..4a6ceb7
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.includes_never-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,32 @@
+// MIR for `includes_never::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn includes_never::{closure#0}(_1: {async fn body of includes_never()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+                scope 6 {
+                    scope 8 {
+                        scope 9 {
+                        }
+                    }
+                }
+                scope 7 {
+                }
+            }
+            scope 4 {
+                scope 5 {
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..8f66ed1
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,78 @@
+- // MIR for `partial_init::{closure#0}::{closure#0}` before StateTransform
++ // MIR for `partial_init::{closure#0}::{closure#0}` after StateTransform
+  
+- fn partial_init::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:80:50: 80:55}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn partial_init::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++         }
++         storage_conflicts = BitMatrix(0x0) {}
++     }
+      debug _task_context => _2;
+-     debug x => (*(_1.0: &u32));
+-     let mut _0: u32;
++     debug x => (*((*_9).0: &u32));
++     let mut _0: std::task::Poll<u32>;
+      let mut _3: u32;
+      let mut _4: u32;
+      let mut _5: &u32;
+      let mut _6: &u32;
++     let mut _7: u32;
++     let mut _8: u32;
++     let mut _9: &mut {async block@$DIR/async_fn.rs:80:50: 80:55};
+  
+      bb0: {
+-         StorageLive(_3);
+-         _5 = no_retag copy (_1.0: &u32);
+-         _3 = copy (*_5);
+-         StorageLive(_4);
+-         _6 = no_retag copy (_1.0: &u32);
+-         _4 = copy (*_6);
+-         _0 = Add(move _3, move _4);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb1, unwind: bb2];
++         _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:80:50: 80:55});
++         _8 = discriminant((*_9));
++         switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4];
+      }
+  
+      bb1: {
++         _0 = Poll::<u32>::Ready(move _7);
++         discriminant((*_9)) = 1;
+          return;
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         goto -> bb1;
++     }
++ 
++     bb3: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue];
++     }
++ 
++     bb4: {
++         unreachable;
++     }
++ 
++     bb5: {
++         StorageLive(_3);
++         _5 = no_retag copy ((*_9).0: &u32);
++         _3 = copy (*_5);
++         StorageLive(_4);
++         _6 = no_retag copy ((*_9).0: &u32);
++         _4 = copy (*_6);
++         _7 = Add(move _3, move _4);
++         StorageDead(_4);
++         StorageDead(_3);
++         goto -> bb2;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..0261bfd
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,35 @@
+// MIR for `partial_init::{closure#0}::{closure#0}` 0 coroutine_drop
+
+fn partial_init::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}) -> () {
+    debug _task_context => _2;
+    debug x => (*((*_1).0: &u32));
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let mut _3: u32;
+    let mut _4: u32;
+    let mut _5: &u32;
+    let mut _6: &u32;
+    let mut _7: u32;
+    let mut _8: u32;
+
+    bb0: {
+        _8 = discriminant((*_1));
+        switchInt(move _8) -> [0: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        return;
+    }
+
+    bb2: {
+        goto -> bb3;
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..3ddd757
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,14 @@
+// MIR for `partial_init::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn partial_init::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:80:50: 80:55}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..7acd06e
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,387 @@
+- // MIR for `partial_init::{closure#0}` before StateTransform
++ // MIR for `partial_init::{closure#0}` after StateTransform
+  
+- fn partial_init::{closure#0}(_1: {async fn body of partial_init()}, _2: std::future::ResumeTy) -> u32
+- yields ()
+-  {
++ fn partial_init::{closure#0}(_1: Pin<&mut {async fn body of partial_init()}>, _2: &mut Context<'_>) -> Poll<u32> {
++     coroutine layout {
++         field _s0: u32;
++         field _s1: String;
++         field _s2: {async block@$DIR/async_fn.rs:80:50: 80:55};
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1, _s2],
++         }
++         storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)}
++     }
+      debug _task_context => _2;
+-     debug x => (_1.0: u32);
+-     let mut _0: u32;
++     debug x => ((*_28).0: u32);
++     coroutine debug x => _s0;
++     let mut _0: std::task::Poll<u32>;
+      let _3: u32;
+      let mut _4: !;
+      let mut _6: std::string::String;
+      let mut _7: !;
+      let mut _8: {async block@$DIR/async_fn.rs:80:50: 80:55};
+      let mut _9: {async block@$DIR/async_fn.rs:80:50: 80:55};
+      let mut _10: &u32;
+      let mut _12: ();
+      let _13: ();
+      let mut _14: std::task::Poll<u32>;
+      let mut _15: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>;
+      let mut _16: &mut {async block@$DIR/async_fn.rs:80:50: 80:55};
+      let mut _17: &mut {async block@$DIR/async_fn.rs:80:50: 80:55};
+      let mut _18: &mut std::task::Context<'_>;
+      let mut _19: &mut std::task::Context<'_>;
+-     let mut _20: std::future::ResumeTy;
++     let mut _20: &mut std::task::Context<'_>;
+      let mut _21: isize;
+      let mut _23: !;
+-     let mut _24: std::future::ResumeTy;
++     let mut _24: &mut std::task::Context<'_>;
+      let mut _25: ();
++     let mut _26: u32;
++     let mut _27: u32;
++     let mut _28: &mut {async fn body of partial_init()};
+      scope 1 {
+-         debug x => _3;
++         debug x => (((*_28) as variant#3).0: u32);
+          scope 2 {
+              debug _x => _5;
+          }
+          scope 3 {
++             coroutine debug __awaitee => _s2;
+              let _5: (std::string::String, !);
+              let mut _11: {async block@$DIR/async_fn.rs:80:50: 80:55};
+              scope 4 {
+-                 debug __awaitee => _11;
++                 debug __awaitee => (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55});
+                  let _22: u32;
+                  scope 5 {
+                      debug result => _22;
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = copy (_1.0: u32);
+-         StorageLive(_4);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = String::new() -> [return: bb1, unwind: bb30];
++         _28 = copy (_1.0: &mut {async fn body of partial_init()});
++         _27 = discriminant((*_28));
++         switchInt(move _27) -> [0: bb32, 1: bb31, 2: bb30, 3: bb29, otherwise: bb7];
+      }
+  
+      bb1: {
+          StorageLive(_8);
+          StorageLive(_9);
+          StorageLive(_10);
+-         _10 = &_3;
++         _10 = &(((*_28) as variant#3).0: u32);
+          _9 = {coroutine@$DIR/async_fn.rs:80:50: 80:55 (#0)} { x: move _10 };
+          StorageDead(_10);
+-         _8 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as IntoFuture>::into_future(move _9) -> [return: bb2, unwind: bb26];
++         _8 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as IntoFuture>::into_future(move _9) -> [return: bb2, unwind: bb20];
+      }
+  
+      bb2: {
+          StorageDead(_9);
+          PlaceMention(_8);
+-         StorageLive(_11);
+-         _11 = move _8;
++         nop;
++         (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55}) = move _8;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+          StorageLive(_16);
+          StorageLive(_17);
+-         _17 = &mut _11;
++         _17 = &mut (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55});
+          _16 = &mut (*_17);
+-         _15 = Pin::<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>::new_unchecked(move _16) -> [return: bb4, unwind: bb22];
++         _15 = Pin::<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>::new_unchecked(move _16) -> [return: bb4, unwind: bb16];
+      }
+  
+      bb4: {
+          StorageDead(_16);
+          StorageLive(_18);
+          StorageLive(_19);
+          StorageLive(_20);
+          _20 = copy _2;
+-         _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb5, unwind: bb20];
++         _19 = move _20;
++         goto -> bb5;
+      }
+  
+      bb5: {
+          _18 = &mut (*_19);
+          StorageDead(_20);
+-         _14 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as Future>::poll(move _15, move _18) -> [return: bb6, unwind: bb21];
++         _14 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as Future>::poll(move _15, move _18) -> [return: bb6, unwind: bb15];
+      }
+  
+      bb6: {
+          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageDead(_15);
+          PlaceMention(_14);
+          _21 = discriminant(_14);
+          switchInt(move _21) -> [0: bb9, 1: bb8, otherwise: bb7];
+      }
+  
+      bb7: {
+          unreachable;
+      }
+  
+      bb8: {
+          _13 = const ();
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageLive(_24);
+          StorageLive(_25);
+          _25 = ();
+-         _24 = yield(move _25) -> [resume: bb10, drop: bb15];
++         _0 = Poll::<u32>::Pending;
++         StorageDead(_4);
++         StorageDead(_5);
++         StorageDead(_8);
++         StorageDead(_24);
++         StorageDead(_25);
++         discriminant((*_28)) = 3;
++         return;
+      }
+  
+      bb9: {
+          StorageLive(_22);
+          _22 = copy ((_14 as Ready).0: u32);
+-         _0 = copy _22;
++         _26 = copy _22;
+          StorageDead(_22);
+          StorageDead(_14);
+          StorageDead(_13);
+-         drop(_11) -> [return: bb11, unwind: bb24];
++         drop((((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb11, unwind: bb18];
+      }
+  
+      bb10: {
+          StorageDead(_25);
+          _2 = move _24;
+          StorageDead(_24);
+          _12 = const ();
+          goto -> bb3;
+      }
+  
+      bb11: {
+-         StorageDead(_11);
+-         drop(_6) -> [return: bb12, unwind: bb25];
++         nop;
++         drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb12, unwind: bb19];
+      }
+  
+      bb12: {
+-         StorageDead(_6);
++         nop;
+          goto -> bb13;
+      }
+  
+      bb13: {
+          StorageDead(_8);
+          StorageDead(_5);
+          StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb14, unwind: bb32];
++         nop;
++         goto -> bb27;
+      }
+  
+      bb14: {
++         _0 = Poll::<u32>::Ready(move _26);
++         discriminant((*_28)) = 1;
+          return;
+      }
+  
+-     bb15: {
+-         StorageDead(_25);
+-         StorageDead(_24);
+-         drop(_11) -> [return: bb16, unwind: bb33];
++     bb15 (cleanup): {
++         StorageDead(_19);
++         StorageDead(_18);
++         goto -> bb17;
+      }
+  
+-     bb16: {
+-         StorageDead(_11);
+-         drop(_6) -> [return: bb17, unwind: bb34];
++     bb16 (cleanup): {
++         StorageDead(_16);
++         goto -> bb17;
+      }
+  
+-     bb17: {
+-         StorageDead(_6);
+-         goto -> bb18;
++     bb17 (cleanup): {
++         StorageDead(_17);
++         StorageDead(_15);
++         StorageDead(_14);
++         StorageDead(_13);
++         drop((((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb18, unwind terminate(cleanup)];
+      }
+  
+-     bb18: {
+-         StorageDead(_8);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb19, unwind: bb32];
++     bb18 (cleanup): {
++         nop;
++         drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb19, unwind terminate(cleanup)];
+      }
+  
+-     bb19: {
+-         coroutine_drop;
++     bb19 (cleanup): {
++         nop;
++         goto -> bb23;
+      }
+  
+      bb20 (cleanup): {
+-         StorageDead(_20);
+          goto -> bb21;
+      }
+  
+      bb21 (cleanup): {
+-         StorageDead(_19);
+-         StorageDead(_18);
+-         goto -> bb23;
++         StorageDead(_9);
++         drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb22, unwind terminate(cleanup)];
+      }
+  
+      bb22 (cleanup): {
+-         StorageDead(_16);
++         nop;
+          goto -> bb23;
+      }
+  
+      bb23 (cleanup): {
+-         StorageDead(_17);
+-         StorageDead(_15);
+-         StorageDead(_14);
+-         StorageDead(_13);
+-         drop(_11) -> [return: bb24, unwind terminate(cleanup)];
++         StorageDead(_8);
++         goto -> bb25;
+      }
+  
+      bb24 (cleanup): {
+-         StorageDead(_11);
+-         drop(_6) -> [return: bb25, unwind terminate(cleanup)];
++         nop;
++         goto -> bb25;
+      }
+  
+      bb25 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb29;
++         StorageDead(_5);
++         StorageDead(_4);
++         nop;
++         goto -> bb26;
+      }
+  
+      bb26 (cleanup): {
+-         goto -> bb27;
++         goto -> bb28;
+      }
+  
+-     bb27 (cleanup): {
+-         StorageDead(_9);
+-         drop(_6) -> [return: bb28, unwind terminate(cleanup)];
++     bb27: {
++         goto -> bb14;
+      }
+  
+      bb28 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb29;
++         discriminant((*_28)) = 2;
++         resume;
+      }
+  
+-     bb29 (cleanup): {
+-         StorageDead(_8);
+-         goto -> bb31;
++     bb29: {
++         StorageLive(_4);
++         StorageLive(_5);
++         StorageLive(_8);
++         StorageLive(_24);
++         StorageLive(_25);
++         _24 = move _2;
++         goto -> bb10;
+      }
+  
+-     bb30 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb31;
++     bb30: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb30, unwind continue];
+      }
+  
+-     bb31 (cleanup): {
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb32, unwind terminate(cleanup)];
++     bb31: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb31, unwind continue];
+      }
+  
+-     bb32 (cleanup): {
+-         resume;
+-     }
+- 
+-     bb33 (cleanup): {
+-         StorageDead(_11);
+-         drop(_6) -> [return: bb34, unwind terminate(cleanup)];
+-     }
+- 
+-     bb34 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb35;
+-     }
+- 
+-     bb35 (cleanup): {
+-         StorageDead(_8);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb32, unwind terminate(cleanup)];
++     bb32: {
++         nop;
++         (((*_28) as variant#3).0: u32) = copy ((*_28).0: u32);
++         StorageLive(_4);
++         StorageLive(_5);
++         nop;
++         (((*_28) as variant#3).1: std::string::String) = String::new() -> [return: bb1, unwind: bb24];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..20525a4
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,131 @@
+// MIR for `partial_init::{closure#0}` 0 coroutine_drop
+
+fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () {
+    debug _task_context => _2;
+    debug x => ((*_1).0: u32);
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: u32;
+    let mut _4: !;
+    let mut _6: std::string::String;
+    let mut _7: !;
+    let mut _8: {async block@$DIR/async_fn.rs:80:50: 80:55};
+    let mut _9: {async block@$DIR/async_fn.rs:80:50: 80:55};
+    let mut _10: &u32;
+    let mut _12: ();
+    let _13: ();
+    let mut _14: std::task::Poll<u32>;
+    let mut _15: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>;
+    let mut _16: &mut {async block@$DIR/async_fn.rs:80:50: 80:55};
+    let mut _17: &mut {async block@$DIR/async_fn.rs:80:50: 80:55};
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: &mut std::task::Context<'_>;
+    let mut _20: &mut std::task::Context<'_>;
+    let mut _21: isize;
+    let mut _23: !;
+    let mut _24: &mut std::task::Context<'_>;
+    let mut _25: ();
+    let mut _26: u32;
+    let mut _27: u32;
+    scope 1 {
+        debug x => (((*_1) as variant#3).0: u32);
+        scope 2 {
+            debug _x => _5;
+        }
+        scope 3 {
+            let _5: (std::string::String, !);
+            let mut _11: {async block@$DIR/async_fn.rs:80:50: 80:55};
+            scope 4 {
+                debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55});
+                let _22: u32;
+                scope 5 {
+                    debug result => _22;
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _27 = discriminant((*_1));
+        switchInt(move _27) -> [0: bb11, 3: bb14, otherwise: bb15];
+    }
+
+    bb1: {
+        StorageDead(_25);
+        StorageDead(_24);
+        drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb2, unwind: bb7];
+    }
+
+    bb2: {
+        nop;
+        drop((((*_1) as variant#3).1: std::string::String)) -> [return: bb3, unwind: bb8];
+    }
+
+    bb3: {
+        nop;
+        goto -> bb4;
+    }
+
+    bb4: {
+        StorageDead(_8);
+        StorageDead(_5);
+        StorageDead(_4);
+        nop;
+        goto -> bb12;
+    }
+
+    bb5: {
+        return;
+    }
+
+    bb6 (cleanup): {
+        resume;
+    }
+
+    bb7 (cleanup): {
+        nop;
+        drop((((*_1) as variant#3).1: std::string::String)) -> [return: bb8, unwind terminate(cleanup)];
+    }
+
+    bb8 (cleanup): {
+        nop;
+        goto -> bb9;
+    }
+
+    bb9 (cleanup): {
+        StorageDead(_8);
+        StorageDead(_5);
+        StorageDead(_4);
+        nop;
+        goto -> bb6;
+    }
+
+    bb10: {
+        return;
+    }
+
+    bb11: {
+        goto -> bb13;
+    }
+
+    bb12: {
+        goto -> bb5;
+    }
+
+    bb13: {
+        goto -> bb10;
+    }
+
+    bb14: {
+        StorageLive(_4);
+        StorageLive(_5);
+        StorageLive(_8);
+        StorageLive(_24);
+        StorageLive(_25);
+        goto -> bb1;
+    }
+
+    bb15: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..1f67854
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.partial_init-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,24 @@
+// MIR for `partial_init::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn partial_init::{closure#0}(_1: {async fn body of partial_init()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+        }
+        scope 3 {
+            scope 4 {
+                scope 5 {
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git a/tests/mir-opt/coroutine/async_fn.rs b/tests/mir-opt/coroutine/async_fn.rs
new file mode 100644
index 0000000..2e8f2e1
--- /dev/null
+++ b/tests/mir-opt/coroutine/async_fn.rs
@@ -0,0 +1,139 @@
+//@ skip-filecheck
+//@ compile-flags: -Zmir-opt-level=0
+//@ needs-unwind
+//@ edition: 2024
+
+#![feature(never_type)]
+
+use std::future::Future;
+
+// See if we can run a basic `async fn`
+// EMIT_MIR async_fn.foo-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.foo-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.foo-{closure#0}.coroutine_drop_proxy_async.0.mir
+// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir
+pub async fn foo(x: &u32, y: u32) -> u32 {
+    let y = &y;
+    let z = 9;
+    let z = &z;
+    let y = async { *y + *z }.await;
+    let a = 10;
+    let a = &a;
+    *x + y + *a
+}
+
+// EMIT_MIR async_fn.add-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.add-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.add-{closure#0}.coroutine_drop_proxy_async.0.mir
+// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir
+async fn add(x: u32, y: u32) -> u32 {
+    let a = async { x + y };
+    a.await
+}
+
+// EMIT_MIR async_fn.build_aggregate-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.build_aggregate-{closure#0}.coroutine_drop_proxy_async.0.mir
+async fn build_aggregate(a: u32, b: u32, c: u32, d: u32) -> u32 {
+    let x = (add(a, b).await, add(c, d).await);
+    x.0 + x.1
+}
+
+enum Never {}
+fn never() -> Never {
+    panic!()
+}
+
+// EMIT_MIR async_fn.includes_never-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.includes_never-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.includes_never-{closure#0}.coroutine_drop_proxy_async.0.mir
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.diff
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop_proxy_async.0.mir
+async fn includes_never(crash: bool, x: u32) -> u32 {
+    let result = async { x * x }.await;
+    if !crash {
+        return result;
+    }
+    #[allow(unused)]
+    let bad = never();
+    result *= async { x + x }.await;
+    drop(bad);
+    result
+}
+
+// EMIT_MIR async_fn.partial_init-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.partial_init-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.partial_init-{closure#0}.coroutine_drop_proxy_async.0.mir
+// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir
+async fn partial_init(x: u32) -> u32 {
+    #[allow(unreachable_code)]
+    let _x: (String, !) = (String::new(), return async { x + x }.await);
+}
+
+async fn read_exact(_from: &mut &[u8], _to: &mut [u8]) -> Option<()> {
+    Some(())
+}
+
+// EMIT_MIR async_fn.hello_world-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.hello_world-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.hello_world-{closure#0}.coroutine_drop_proxy_async.0.mir
+async fn hello_world() {
+    let data = [0u8; 1];
+    let mut reader = &data[..];
+
+    let mut marker = [0u8; 1];
+    read_exact(&mut reader, &mut marker).await.unwrap();
+}
+
+// This example comes from https://github.com/rust-lang/rust/issues/115145
+// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.StateTransform.diff
+// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir
+// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.coroutine_drop_proxy_async.0.mir
+#[allow(unreachable_patterns)]
+async fn uninhabited_variant() {
+    async fn unreachable(_: Never) {}
+
+    let c = async {};
+    match None::<Never> {
+        None => {
+            c.await;
+        }
+        Some(r) => {
+            unreachable(r).await;
+        }
+    }
+}
+
+fn run_fut<T>(fut: impl Future<Output = T>) -> T {
+    use std::task::{Context, Poll, Waker};
+
+    let mut context = Context::from_waker(Waker::noop());
+
+    let mut pinned = Box::pin(fut);
+    loop {
+        match pinned.as_mut().poll(&mut context) {
+            Poll::Pending => continue,
+            Poll::Ready(v) => return v,
+        }
+    }
+}
+
+fn main() {
+    let x = 5;
+    assert_eq!(run_fut(foo(&x, 7)), 31);
+    assert_eq!(run_fut(build_aggregate(1, 2, 3, 4)), 10);
+    assert_eq!(run_fut(includes_never(false, 4)), 16);
+    assert_eq!(run_fut(partial_init(4)), 8);
+    run_fut(hello_world());
+    run_fut(uninhabited_variant());
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..f29242c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,683 @@
+- // MIR for `uninhabited_variant::{closure#0}` before StateTransform
++ // MIR for `uninhabited_variant::{closure#0}` after StateTransform
+  
+- fn uninhabited_variant::{closure#0}(_1: {async fn body of uninhabited_variant()}, _2: std::future::ResumeTy) -> ()
+- yields ()
+-  {
++ fn uninhabited_variant::{closure#0}(_1: Pin<&mut {async fn body of uninhabited_variant()}>, _2: &mut Context<'_>) -> Poll<()> {
++     coroutine layout {
++         field _s0: {async block@$DIR/async_fn.rs:106:13: 106:18};
++         field _s1: {async block@$DIR/async_fn.rs:106:13: 106:18};
++         field _s2: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
++         field _s3: bool;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s1, _s3],
++             Suspend1 (4): [_s0, _s2, _s3],
++         }
++         storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s2), (_s0, _s3), (_s1, _s1), (_s1, _s3), (_s2, _s0), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)}
++     }
+      debug _task_context => _2;
+-     let mut _0: ();
++     coroutine debug c => _s0;
++     let mut _0: std::task::Poll<()>;
+      let _3: {async block@$DIR/async_fn.rs:106:13: 106:18};
+      let mut _4: std::option::Option<Never>;
+      let mut _5: isize;
+      let _6: ();
+      let mut _7: {async block@$DIR/async_fn.rs:106:13: 106:18};
+      let mut _8: {async block@$DIR/async_fn.rs:106:13: 106:18};
+      let mut _10: ();
+      let _11: ();
+      let mut _12: std::task::Poll<()>;
+      let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>;
+      let mut _14: &mut {async block@$DIR/async_fn.rs:106:13: 106:18};
+      let mut _15: &mut {async block@$DIR/async_fn.rs:106:13: 106:18};
+      let mut _16: &mut std::task::Context<'_>;
+      let mut _17: &mut std::task::Context<'_>;
+-     let mut _18: std::future::ResumeTy;
++     let mut _18: &mut std::task::Context<'_>;
+      let mut _19: isize;
+      let mut _21: !;
+-     let mut _22: std::future::ResumeTy;
++     let mut _22: &mut std::task::Context<'_>;
+      let mut _23: ();
+      let _25: ();
+      let mut _26: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+      let mut _27: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+      let mut _28: Never;
+      let _30: ();
+      let mut _31: std::task::Poll<()>;
+      let mut _32: std::pin::Pin<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>;
+      let mut _33: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+      let mut _34: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+      let mut _35: &mut std::task::Context<'_>;
+      let mut _36: &mut std::task::Context<'_>;
+-     let mut _37: std::future::ResumeTy;
++     let mut _37: &mut std::task::Context<'_>;
+      let mut _38: isize;
+      let mut _40: !;
+-     let mut _41: std::future::ResumeTy;
++     let mut _41: &mut std::task::Context<'_>;
+      let mut _42: ();
+      let mut _43: bool;
++     let mut _44: ();
++     let mut _45: u32;
++     let mut _46: &mut {async fn body of uninhabited_variant()};
+      scope 1 {
+-         debug c => _3;
++         debug c => (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
++         coroutine debug __awaitee => _s1;
+          let mut _9: {async block@$DIR/async_fn.rs:106:13: 106:18};
+          let _24: Never;
+          scope 2 {
+-             debug __awaitee => _9;
++             debug __awaitee => (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
+              let _20: ();
+              scope 3 {
+                  debug result => _20;
+              }
+          }
+          scope 4 {
+              debug r => _24;
++             coroutine debug __awaitee => _s2;
+              let mut _29: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+              scope 5 {
+-                 debug __awaitee => _29;
++                 debug __awaitee => (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()});
+                  let _39: ();
+                  scope 6 {
+                      debug result => _39;
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         _43 = const false;
+-         StorageLive(_3);
+-         _43 = const true;
+-         _3 = {coroutine@$DIR/async_fn.rs:106:13: 106:18 (#0)};
+-         StorageLive(_4);
+-         _4 = Option::<Never>::None;
+-         PlaceMention(_4);
+-         _5 = discriminant(_4);
+-         switchInt(move _5) -> [0: bb3, 1: bb2, otherwise: bb1];
++         _46 = copy (_1.0: &mut {async fn body of uninhabited_variant()});
++         _45 = discriminant((*_46));
++         switchInt(move _45) -> [0: bb56, 1: bb55, 2: bb54, 3: bb52, 4: bb53, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_24);
+          _24 = move ((_4 as Some).0: Never);
+          StorageLive(_25);
+          StorageLive(_26);
+          StorageLive(_27);
+          StorageLive(_28);
+          _28 = move _24;
+-         _27 = uninhabited_variant::{closure#0}::unreachable(move _28) -> [return: bb14, unwind: bb43];
++         _27 = uninhabited_variant::{closure#0}::unreachable(move _28) -> [return: bb14, unwind: bb33];
+      }
+  
+      bb3: {
+          StorageLive(_6);
+          StorageLive(_7);
+          StorageLive(_8);
+-         _43 = const false;
+-         _8 = move _3;
+-         _7 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as IntoFuture>::into_future(move _8) -> [return: bb4, unwind: bb51];
++         (((*_46) as variant#4).2: bool) = const false;
++         _8 = move (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
++         _7 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as IntoFuture>::into_future(move _8) -> [return: bb4, unwind: bb40];
+      }
+  
+      bb4: {
+          StorageDead(_8);
+          PlaceMention(_7);
+-         StorageLive(_9);
+-         _9 = move _7;
++         nop;
++         (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18}) = move _7;
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageLive(_11);
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+-         _15 = &mut _9;
++         _15 = &mut (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
+          _14 = &mut (*_15);
+-         _13 = Pin::<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>::new_unchecked(move _14) -> [return: bb6, unwind: bb48];
++         _13 = Pin::<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>::new_unchecked(move _14) -> [return: bb6, unwind: bb37];
+      }
+  
+      bb6: {
+          StorageDead(_14);
+          StorageLive(_16);
+          StorageLive(_17);
+          StorageLive(_18);
+          _18 = copy _2;
+-         _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb7, unwind: bb46];
++         _17 = move _18;
++         goto -> bb7;
+      }
+  
+      bb7: {
+          _16 = &mut (*_17);
+          StorageDead(_18);
+-         _12 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as Future>::poll(move _13, move _16) -> [return: bb8, unwind: bb47];
++         _12 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as Future>::poll(move _13, move _16) -> [return: bb8, unwind: bb36];
+      }
+  
+      bb8: {
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_15);
+          StorageDead(_13);
+          PlaceMention(_12);
+          _19 = discriminant(_12);
+          switchInt(move _19) -> [0: bb10, 1: bb9, otherwise: bb1];
+      }
+  
+      bb9: {
+          _11 = const ();
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageLive(_22);
+          StorageLive(_23);
+          _23 = ();
+-         _22 = yield(move _23) -> [resume: bb11, drop: bb31];
++         _0 = Poll::<()>::Pending;
++         StorageDead(_4);
++         StorageDead(_6);
++         StorageDead(_7);
++         StorageDead(_22);
++         StorageDead(_23);
++         discriminant((*_46)) = 3;
++         return;
+      }
+  
+      bb10: {
+          StorageLive(_20);
+          _20 = copy ((_12 as Ready).0: ());
+          _6 = copy _20;
+          StorageDead(_20);
+          StorageDead(_12);
+          StorageDead(_11);
+-         drop(_9) -> [return: bb12, unwind: bb50];
++         drop((((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb12, unwind: bb39];
+      }
+  
+      bb11: {
+          StorageDead(_23);
+          _2 = move _22;
+          StorageDead(_22);
+          _10 = const ();
+          goto -> bb5;
+      }
+  
+      bb12: {
+-         StorageDead(_9);
++         nop;
+          goto -> bb13;
+      }
+  
+      bb13: {
+          StorageDead(_7);
+          StorageDead(_6);
+-         _0 = const ();
++         _44 = const ();
+          goto -> bb25;
+      }
+  
+      bb14: {
+          StorageDead(_28);
+-         _26 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as IntoFuture>::into_future(move _27) -> [return: bb15, unwind: bb42];
++         _26 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as IntoFuture>::into_future(move _27) -> [return: bb15, unwind: bb32];
+      }
+  
+      bb15: {
+          StorageDead(_27);
+          PlaceMention(_26);
+-         StorageLive(_29);
+-         _29 = move _26;
++         nop;
++         (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()}) = move _26;
+          goto -> bb16;
+      }
+  
+      bb16: {
+          StorageLive(_30);
+          StorageLive(_31);
+          StorageLive(_32);
+          StorageLive(_33);
+          StorageLive(_34);
+-         _34 = &mut _29;
++         _34 = &mut (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()});
+          _33 = &mut (*_34);
+-         _32 = Pin::<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>::new_unchecked(move _33) -> [return: bb17, unwind: bb39];
++         _32 = Pin::<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>::new_unchecked(move _33) -> [return: bb17, unwind: bb29];
+      }
+  
+      bb17: {
+          StorageDead(_33);
+          StorageLive(_35);
+          StorageLive(_36);
+          StorageLive(_37);
+          _37 = copy _2;
+-         _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb18, unwind: bb37];
++         _36 = move _37;
++         goto -> bb18;
+      }
+  
+      bb18: {
+          _35 = &mut (*_36);
+          StorageDead(_37);
+-         _31 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as Future>::poll(move _32, move _35) -> [return: bb19, unwind: bb38];
++         _31 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as Future>::poll(move _32, move _35) -> [return: bb19, unwind: bb28];
+      }
+  
+      bb19: {
+          StorageDead(_36);
+          StorageDead(_35);
+          StorageDead(_34);
+          StorageDead(_32);
+          PlaceMention(_31);
+          _38 = discriminant(_31);
+          switchInt(move _38) -> [0: bb21, 1: bb20, otherwise: bb1];
+      }
+  
+      bb20: {
+          _30 = const ();
+          StorageDead(_31);
+          StorageDead(_30);
+          StorageLive(_41);
+          StorageLive(_42);
+          _42 = ();
+-         _41 = yield(move _42) -> [resume: bb22, drop: bb28];
++         _0 = Poll::<()>::Pending;
++         StorageDead(_4);
++         StorageDead(_24);
++         StorageDead(_25);
++         StorageDead(_26);
++         StorageDead(_41);
++         StorageDead(_42);
++         discriminant((*_46)) = 4;
++         return;
+      }
+  
+      bb21: {
+          StorageLive(_39);
+          _39 = copy ((_31 as Ready).0: ());
+          _25 = copy _39;
+          StorageDead(_39);
+          StorageDead(_31);
+          StorageDead(_30);
+-         drop(_29) -> [return: bb23, unwind: bb41];
++         drop((((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb23, unwind: bb31];
+      }
+  
+      bb22: {
+          StorageDead(_42);
+          _2 = move _41;
+          StorageDead(_41);
+          _10 = const ();
+          goto -> bb16;
+      }
+  
+      bb23: {
+-         StorageDead(_29);
++         nop;
+          goto -> bb24;
+      }
+  
+      bb24: {
+          StorageDead(_26);
+          StorageDead(_25);
+-         _0 = const ();
++         _44 = const ();
+          StorageDead(_24);
+          goto -> bb25;
+      }
+  
+      bb25: {
+          StorageDead(_4);
+-         goto -> bb64;
++         goto -> bb47;
+      }
+  
+      bb26: {
+-         _43 = const false;
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb27, unwind: bb56];
++         (((*_46) as variant#4).2: bool) = const false;
++         nop;
++         goto -> bb50;
+      }
+  
+      bb27: {
++         _0 = Poll::<()>::Ready(move _44);
++         discriminant((*_46)) = 1;
+          return;
+      }
+  
+-     bb28: {
+-         StorageDead(_42);
+-         StorageDead(_41);
+-         drop(_29) -> [return: bb29, unwind: bb57];
+-     }
+- 
+-     bb29: {
+-         StorageDead(_29);
+-         goto -> bb30;
+-     }
+- 
+-     bb30: {
+-         StorageDead(_26);
+-         StorageDead(_25);
+-         StorageDead(_24);
+-         goto -> bb34;
+-     }
+- 
+-     bb31: {
+-         StorageDead(_23);
+-         StorageDead(_22);
+-         drop(_9) -> [return: bb32, unwind: bb59];
+-     }
+- 
+-     bb32: {
+-         StorageDead(_9);
+-         goto -> bb33;
+-     }
+- 
+-     bb33: {
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         goto -> bb34;
+-     }
+- 
+-     bb34: {
+-         StorageDead(_4);
+-         goto -> bb66;
+-     }
+- 
+-     bb35: {
+-         _43 = const false;
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb36, unwind: bb56];
+-     }
+- 
+-     bb36: {
+-         coroutine_drop;
+-     }
+- 
+-     bb37 (cleanup): {
+-         StorageDead(_37);
+-         goto -> bb38;
+-     }
+- 
+-     bb38 (cleanup): {
++     bb28 (cleanup): {
+          StorageDead(_36);
+          StorageDead(_35);
+-         goto -> bb40;
++         goto -> bb30;
+      }
+  
+-     bb39 (cleanup): {
++     bb29 (cleanup): {
+          StorageDead(_33);
+-         goto -> bb40;
++         goto -> bb30;
+      }
+  
+-     bb40 (cleanup): {
++     bb30 (cleanup): {
+          StorageDead(_34);
+          StorageDead(_32);
+          StorageDead(_31);
+          StorageDead(_30);
+-         drop(_29) -> [return: bb41, unwind terminate(cleanup)];
++         drop((((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb31, unwind terminate(cleanup)];
+      }
+  
+-     bb41 (cleanup): {
+-         StorageDead(_29);
+-         goto -> bb45;
++     bb31 (cleanup): {
++         nop;
++         goto -> bb35;
+      }
+  
+-     bb42 (cleanup): {
+-         goto -> bb44;
++     bb32 (cleanup): {
++         goto -> bb34;
+      }
+  
+-     bb43 (cleanup): {
++     bb33 (cleanup): {
+          StorageDead(_28);
+-         goto -> bb44;
++         goto -> bb34;
+      }
+  
+-     bb44 (cleanup): {
++     bb34 (cleanup): {
+          StorageDead(_27);
+-         goto -> bb45;
++         goto -> bb35;
+      }
+  
+-     bb45 (cleanup): {
++     bb35 (cleanup): {
+          StorageDead(_26);
+          StorageDead(_25);
+          StorageDead(_24);
+-         goto -> bb54;
++         goto -> bb43;
+      }
+  
+-     bb46 (cleanup): {
+-         StorageDead(_18);
+-         goto -> bb47;
+-     }
+- 
+-     bb47 (cleanup): {
++     bb36 (cleanup): {
+          StorageDead(_17);
+          StorageDead(_16);
+-         goto -> bb49;
++         goto -> bb38;
+      }
+  
+-     bb48 (cleanup): {
++     bb37 (cleanup): {
+          StorageDead(_14);
+-         goto -> bb49;
++         goto -> bb38;
+      }
+  
+-     bb49 (cleanup): {
++     bb38 (cleanup): {
+          StorageDead(_15);
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
+-         drop(_9) -> [return: bb50, unwind terminate(cleanup)];
++         drop((((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb39, unwind terminate(cleanup)];
+      }
+  
+-     bb50 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb53;
++     bb39 (cleanup): {
++         nop;
++         goto -> bb42;
+      }
+  
+-     bb51 (cleanup): {
+-         goto -> bb52;
++     bb40 (cleanup): {
++         goto -> bb41;
+      }
+  
+-     bb52 (cleanup): {
++     bb41 (cleanup): {
+          StorageDead(_8);
+-         goto -> bb53;
++         goto -> bb42;
+      }
+  
+-     bb53 (cleanup): {
++     bb42 (cleanup): {
+          StorageDead(_7);
+          StorageDead(_6);
+-         goto -> bb54;
++         goto -> bb43;
+      }
+  
+-     bb54 (cleanup): {
++     bb43 (cleanup): {
+          StorageDead(_4);
+-         goto -> bb68;
++         goto -> bb49;
+      }
+  
+-     bb55 (cleanup): {
+-         _43 = const false;
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb56, unwind terminate(cleanup)];
++     bb44 (cleanup): {
++         (((*_46) as variant#4).2: bool) = const false;
++         nop;
++         goto -> bb45;
+      }
+  
+-     bb56 (cleanup): {
+-         resume;
++     bb45 (cleanup): {
++         goto -> bb51;
+      }
+  
+-     bb57 (cleanup): {
+-         StorageDead(_29);
+-         goto -> bb58;
++     bb46: {
++         drop((((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb26, unwind: bb44];
+      }
+  
+-     bb58 (cleanup): {
+-         StorageDead(_26);
+-         StorageDead(_25);
+-         StorageDead(_24);
+-         goto -> bb61;
++     bb47: {
++         switchInt(copy (((*_46) as variant#4).2: bool)) -> [0: bb26, otherwise: bb46];
+      }
+  
+-     bb59 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb60;
++     bb48 (cleanup): {
++         drop((((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb44, unwind terminate(cleanup)];
+      }
+  
+-     bb60 (cleanup): {
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         goto -> bb61;
++     bb49 (cleanup): {
++         switchInt(copy (((*_46) as variant#4).2: bool)) -> [0: bb44, otherwise: bb48];
+      }
+  
+-     bb61 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb70;
++     bb50: {
++         goto -> bb27;
+      }
+  
+-     bb62 (cleanup): {
+-         _43 = const false;
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb56, unwind terminate(cleanup)];
++     bb51 (cleanup): {
++         discriminant((*_46)) = 2;
++         resume;
+      }
+  
+-     bb63: {
+-         drop(_3) -> [return: bb26, unwind: bb55];
++     bb52: {
++         StorageLive(_4);
++         StorageLive(_6);
++         StorageLive(_7);
++         StorageLive(_22);
++         StorageLive(_23);
++         _22 = move _2;
++         goto -> bb11;
+      }
+  
+-     bb64: {
+-         switchInt(copy _43) -> [0: bb26, otherwise: bb63];
++     bb53: {
++         StorageLive(_4);
++         StorageLive(_24);
++         StorageLive(_25);
++         StorageLive(_26);
++         StorageLive(_41);
++         StorageLive(_42);
++         _41 = move _2;
++         goto -> bb22;
+      }
+  
+-     bb65: {
+-         drop(_3) -> [return: bb35, unwind: bb62];
++     bb54: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb54, unwind continue];
+      }
+  
+-     bb66: {
+-         switchInt(copy _43) -> [0: bb35, otherwise: bb65];
++     bb55: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb55, unwind continue];
+      }
+  
+-     bb67 (cleanup): {
+-         drop(_3) -> [return: bb55, unwind terminate(cleanup)];
+-     }
+- 
+-     bb68 (cleanup): {
+-         switchInt(copy _43) -> [0: bb55, otherwise: bb67];
+-     }
+- 
+-     bb69 (cleanup): {
+-         drop(_3) -> [return: bb62, unwind terminate(cleanup)];
+-     }
+- 
+-     bb70 (cleanup): {
+-         switchInt(copy _43) -> [0: bb62, otherwise: bb69];
++     bb56: {
++         (((*_46) as variant#4).2: bool) = const false;
++         nop;
++         (((*_46) as variant#4).2: bool) = const true;
++         (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18}) = {coroutine@$DIR/async_fn.rs:106:13: 106:18 (#0)};
++         StorageLive(_4);
++         _4 = Option::<Never>::None;
++         PlaceMention(_4);
++         _5 = discriminant(_4);
++         switchInt(move _5) -> [0: bb3, 1: bb2, otherwise: bb1];
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop.0.mir" "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop.0.mir"
new file mode 100644
index 0000000..31b418c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop.0.mir"
@@ -0,0 +1,216 @@
+// MIR for `uninhabited_variant::{closure#0}` 0 coroutine_drop
+
+fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_variant()}) -> () {
+    debug _task_context => _2;
+    let mut _0: ();
+    let mut _2: &mut std::task::Context<'_>;
+    let _3: {async block@$DIR/async_fn.rs:106:13: 106:18};
+    let mut _4: std::option::Option<Never>;
+    let mut _5: isize;
+    let _6: ();
+    let mut _7: {async block@$DIR/async_fn.rs:106:13: 106:18};
+    let mut _8: {async block@$DIR/async_fn.rs:106:13: 106:18};
+    let mut _10: ();
+    let _11: ();
+    let mut _12: std::task::Poll<()>;
+    let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>;
+    let mut _14: &mut {async block@$DIR/async_fn.rs:106:13: 106:18};
+    let mut _15: &mut {async block@$DIR/async_fn.rs:106:13: 106:18};
+    let mut _16: &mut std::task::Context<'_>;
+    let mut _17: &mut std::task::Context<'_>;
+    let mut _18: &mut std::task::Context<'_>;
+    let mut _19: isize;
+    let mut _21: !;
+    let mut _22: &mut std::task::Context<'_>;
+    let mut _23: ();
+    let _25: ();
+    let mut _26: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+    let mut _27: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+    let mut _28: Never;
+    let _30: ();
+    let mut _31: std::task::Poll<()>;
+    let mut _32: std::pin::Pin<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>;
+    let mut _33: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+    let mut _34: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+    let mut _35: &mut std::task::Context<'_>;
+    let mut _36: &mut std::task::Context<'_>;
+    let mut _37: &mut std::task::Context<'_>;
+    let mut _38: isize;
+    let mut _40: !;
+    let mut _41: &mut std::task::Context<'_>;
+    let mut _42: ();
+    let mut _43: bool;
+    let mut _44: ();
+    let mut _45: u32;
+    scope 1 {
+        debug c => (((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
+        let mut _9: {async block@$DIR/async_fn.rs:106:13: 106:18};
+        let _24: Never;
+        scope 2 {
+            debug __awaitee => (((*_1) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18});
+            let _20: ();
+            scope 3 {
+                debug result => _20;
+            }
+        }
+        scope 4 {
+            debug r => _24;
+            let mut _29: {async fn body of uninhabited_variant::{closure#0}::unreachable()};
+            scope 5 {
+                debug __awaitee => (((*_1) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()});
+                let _39: ();
+                scope 6 {
+                    debug result => _39;
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _45 = discriminant((*_1));
+        switchInt(move _45) -> [0: bb22, 3: bb25, 4: bb26, otherwise: bb27];
+    }
+
+    bb1: {
+        StorageDead(_42);
+        StorageDead(_41);
+        drop((((*_1) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb2, unwind: bb11];
+    }
+
+    bb2: {
+        nop;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_24);
+        goto -> bb7;
+    }
+
+    bb4: {
+        StorageDead(_23);
+        StorageDead(_22);
+        drop((((*_1) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb5, unwind: bb13];
+    }
+
+    bb5: {
+        nop;
+        goto -> bb6;
+    }
+
+    bb6: {
+        StorageDead(_7);
+        StorageDead(_6);
+        goto -> bb7;
+    }
+
+    bb7: {
+        StorageDead(_4);
+        goto -> bb18;
+    }
+
+    bb8: {
+        (((*_1) as variant#4).2: bool) = const false;
+        nop;
+        goto -> bb23;
+    }
+
+    bb9: {
+        return;
+    }
+
+    bb10 (cleanup): {
+        resume;
+    }
+
+    bb11 (cleanup): {
+        nop;
+        goto -> bb12;
+    }
+
+    bb12 (cleanup): {
+        StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_24);
+        goto -> bb15;
+    }
+
+    bb13 (cleanup): {
+        nop;
+        goto -> bb14;
+    }
+
+    bb14 (cleanup): {
+        StorageDead(_7);
+        StorageDead(_6);
+        goto -> bb15;
+    }
+
+    bb15 (cleanup): {
+        StorageDead(_4);
+        goto -> bb20;
+    }
+
+    bb16 (cleanup): {
+        (((*_1) as variant#4).2: bool) = const false;
+        nop;
+        goto -> bb10;
+    }
+
+    bb17: {
+        drop((((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb8, unwind: bb16];
+    }
+
+    bb18: {
+        switchInt(copy (((*_1) as variant#4).2: bool)) -> [0: bb8, otherwise: bb17];
+    }
+
+    bb19 (cleanup): {
+        drop((((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb16, unwind terminate(cleanup)];
+    }
+
+    bb20 (cleanup): {
+        switchInt(copy (((*_1) as variant#4).2: bool)) -> [0: bb16, otherwise: bb19];
+    }
+
+    bb21: {
+        return;
+    }
+
+    bb22: {
+        goto -> bb24;
+    }
+
+    bb23: {
+        goto -> bb9;
+    }
+
+    bb24: {
+        goto -> bb21;
+    }
+
+    bb25: {
+        StorageLive(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_22);
+        StorageLive(_23);
+        goto -> bb4;
+    }
+
+    bb26: {
+        StorageLive(_4);
+        StorageLive(_24);
+        StorageLive(_25);
+        StorageLive(_26);
+        StorageLive(_41);
+        StorageLive(_42);
+        goto -> bb1;
+    }
+
+    bb27: {
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop_proxy_async.0.mir" "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
new file mode 100644
index 0000000..f460d89
--- /dev/null
+++ "b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-\173closure\0430\175.coroutine_drop_proxy_async.0.mir"
@@ -0,0 +1,26 @@
+// MIR for `uninhabited_variant::{closure#0}` 0 coroutine_drop_proxy_async
+
+fn uninhabited_variant::{closure#0}(_1: {async fn body of uninhabited_variant()}, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: std::task::Poll<()>;
+    scope 1 {
+        scope 2 {
+            scope 3 {
+            }
+        }
+        scope 4 {
+            scope 5 {
+                scope 6 {
+                }
+            }
+        }
+    }
+
+    bb0: {
+        drop(_1) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        _0 = Poll::<()>::Ready(const ());
+        return;
+    }
+}
diff --git "a/tests/mir-opt/coroutine/coroutine.main-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/coroutine.main-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..1767122
--- /dev/null
+++ "b/tests/mir-opt/coroutine/coroutine.main-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,353 @@
+- // MIR for `main::{closure#0}` before StateTransform
++ // MIR for `main::{closure#0}` after StateTransform
+  
+- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine.rs:19:5: 19:18}, _2: String) -> ()
+- yields (&str, String, &Location<'_>)
+-  {
+-     debug arg => _2;
+-     let mut _0: ();
++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
++     coroutine layout {
++         field _s0: String;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++             Suspend1 (4): [_s0],
++         }
++         storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
++     }
++     debug arg => (((*_18) as variant#4).0: std::string::String);
++     coroutine debug arg => _s0;
++     let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
+      let _3: std::string::String;
+      let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
+      let mut _5: std::string::String;
+      let mut _6: &std::string::String;
+      let mut _7: &std::panic::Location<'_>;
+      let _8: std::string::String;
+      let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
+      let mut _10: &str;
+      let _11: &str;
+      let mut _12: std::string::String;
+      let mut _13: &std::string::String;
+      let mut _14: &std::panic::Location<'_>;
+      let _15: &std::panic::Location<'_>;
++     let mut _16: ();
++     let mut _17: u32;
++     let mut _18: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18};
+  
+      bb0: {
+-         StorageLive(_3);
+-         StorageLive(_4);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = &_2;
+-         _5 = <String as Clone>::clone(move _6) -> [return: bb1, unwind: bb31];
++         _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18});
++         _17 = discriminant((*_18));
++         switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageLive(_7);
+-         _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb30];
++         _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb21];
+      }
+  
+      bb2: {
+          _4 = (const "first", move _5, move _7);
+          StorageDead(_7);
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_5);
+-         _3 = yield(move _4) -> [resume: bb4, drop: bb18];
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
++         StorageDead(_3);
++         StorageDead(_4);
++         discriminant((*_18)) = 3;
++         return;
+      }
+  
+      bb4: {
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb6, unwind: bb34];
++         drop(_3) -> [return: bb6, unwind: bb25];
+      }
+  
+      bb6: {
+          StorageDead(_3);
+          StorageLive(_8);
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          _11 = const "second";
+          _10 = &(*_11);
+          StorageLive(_12);
+          StorageLive(_13);
+-         _13 = &_2;
+-         _12 = <String as Clone>::clone(move _13) -> [return: bb7, unwind: bb28];
++         _13 = &(((*_18) as variant#4).0: std::string::String);
++         _12 = <String as Clone>::clone(move _13) -> [return: bb7, unwind: bb19];
+      }
+  
+      bb7: {
+          StorageDead(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+-         _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb24];
++         _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb15];
+      }
+  
+      bb8: {
+          _14 = &(*_15);
+          _9 = (move _10, move _12, move _14);
+          StorageDead(_14);
+          goto -> bb9;
+      }
+  
+      bb9: {
+          StorageDead(_12);
+          StorageDead(_10);
+-         _8 = yield(move _9) -> [resume: bb10, drop: bb15];
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
++         StorageDead(_8);
++         StorageDead(_9);
++         StorageDead(_11);
++         StorageDead(_15);
++         discriminant((*_18)) = 4;
++         return;
+      }
+  
+      bb10: {
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_9);
+-         drop(_8) -> [return: bb12, unwind: bb27];
++         drop(_8) -> [return: bb12, unwind: bb18];
+      }
+  
+      bb12: {
+          StorageDead(_15);
+          StorageDead(_11);
+          StorageDead(_8);
+-         _0 = const ();
+-         drop(_2) -> [return: bb13, unwind: bb36];
++         _16 = const ();
++         drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb13, unwind: bb27];
+      }
+  
+      bb13: {
+-         drop(_1) -> [return: bb14, unwind: bb37];
++         goto -> bb29;
+      }
+  
+      bb14: {
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
++         discriminant((*_18)) = 1;
+          return;
+      }
+  
+-     bb15: {
+-         goto -> bb16;
++     bb15 (cleanup): {
++         StorageDead(_14);
++         drop(_12) -> [return: bb16, unwind terminate(cleanup)];
+      }
+  
+-     bb16: {
+-         StorageDead(_9);
++     bb16 (cleanup): {
++         StorageDead(_12);
++         StorageDead(_10);
+          goto -> bb17;
+      }
+  
+-     bb17: {
+-         StorageDead(_15);
+-         StorageDead(_11);
+-         StorageDead(_8);
+-         goto -> bb21;
++     bb17 (cleanup): {
++         StorageDead(_9);
++         goto -> bb18;
+      }
+  
+-     bb18: {
+-         goto -> bb19;
++     bb18 (cleanup): {
++         StorageDead(_15);
++         goto -> bb20;
+      }
+  
+-     bb19: {
+-         StorageDead(_4);
++     bb19 (cleanup): {
++         StorageDead(_13);
++         StorageDead(_12);
++         StorageDead(_10);
++         StorageDead(_9);
+          goto -> bb20;
+      }
+  
+-     bb20: {
+-         StorageDead(_3);
+-         goto -> bb21;
++     bb20 (cleanup): {
++         StorageDead(_11);
++         StorageDead(_8);
++         goto -> bb26;
+      }
+  
+-     bb21: {
+-         drop(_2) -> [return: bb22, unwind: bb38];
++     bb21 (cleanup): {
++         StorageDead(_7);
++         drop(_5) -> [return: bb23, unwind terminate(cleanup)];
+      }
+  
+-     bb22: {
+-         drop(_1) -> [return: bb23, unwind: bb37];
++     bb22 (cleanup): {
++         StorageDead(_6);
++         goto -> bb23;
+      }
+  
+-     bb23: {
+-         coroutine_drop;
++     bb23 (cleanup): {
++         StorageDead(_5);
++         goto -> bb24;
+      }
+  
+      bb24 (cleanup): {
+-         StorageDead(_14);
+-         drop(_12) -> [return: bb25, unwind terminate(cleanup)];
++         StorageDead(_4);
++         goto -> bb25;
+      }
+  
+      bb25 (cleanup): {
+-         StorageDead(_12);
+-         StorageDead(_10);
++         StorageDead(_3);
+          goto -> bb26;
+      }
+  
+      bb26 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb27;
++         drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb27, unwind terminate(cleanup)];
+      }
+  
+      bb27 (cleanup): {
+-         StorageDead(_15);
+-         goto -> bb29;
++         goto -> bb28;
+      }
+  
+      bb28 (cleanup): {
+-         StorageDead(_13);
+-         StorageDead(_12);
+-         StorageDead(_10);
+-         StorageDead(_9);
+-         goto -> bb29;
++         goto -> bb30;
+      }
+  
+-     bb29 (cleanup): {
+-         StorageDead(_11);
+-         StorageDead(_8);
+-         goto -> bb35;
++     bb29: {
++         goto -> bb14;
+      }
+  
+      bb30 (cleanup): {
+-         StorageDead(_7);
+-         drop(_5) -> [return: bb32, unwind terminate(cleanup)];
++         discriminant((*_18)) = 2;
++         resume;
+      }
+  
+-     bb31 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb32;
++     bb31: {
++         StorageLive(_3);
++         StorageLive(_4);
++         _3 = move _2;
++         goto -> bb4;
+      }
+  
+-     bb32 (cleanup): {
+-         StorageDead(_5);
+-         goto -> bb33;
++     bb32: {
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_11);
++         StorageLive(_15);
++         _8 = move _2;
++         goto -> bb10;
+      }
+  
+-     bb33 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb34;
++     bb33: {
++         assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue];
+      }
+  
+-     bb34 (cleanup): {
+-         StorageDead(_3);
+-         goto -> bb35;
++     bb34: {
++         assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue];
+      }
+  
+-     bb35 (cleanup): {
+-         drop(_2) -> [return: bb36, unwind terminate(cleanup)];
++     bb35: {
++         unreachable;
+      }
+  
+-     bb36 (cleanup): {
+-         drop(_1) -> [return: bb37, unwind terminate(cleanup)];
+-     }
+- 
+-     bb37 (cleanup): {
+-         resume;
+-     }
+- 
+-     bb38 (cleanup): {
+-         drop(_1) -> [return: bb37, unwind terminate(cleanup)];
++     bb36: {
++         (((*_18) as variant#4).0: std::string::String) = move _2;
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = &(((*_18) as variant#4).0: std::string::String);
++         _5 = <String as Clone>::clone(move _6) -> [return: bb1, unwind: bb22];
+      }
+  }
+  
+  ALLOC0 (size: 6, align: 1) {
+      73 65 63 6f 6e 64                               │ second
+  }
+  
+  ALLOC1 (size: 5, align: 1) {
+      66 69 72 73 74                                  │ first
+  }
+  
diff --git "a/tests/mir-opt/coroutine/coroutine.main-\173closure\0431\175.StateTransform.diff" "b/tests/mir-opt/coroutine/coroutine.main-\173closure\0431\175.StateTransform.diff"
new file mode 100644
index 0000000..97c45da
--- /dev/null
+++ "b/tests/mir-opt/coroutine/coroutine.main-\173closure\0431\175.StateTransform.diff"
@@ -0,0 +1,353 @@
+- // MIR for `main::{closure#1}` before StateTransform
++ // MIR for `main::{closure#1}` after StateTransform
+  
+- fn main::{closure#1}(_1: {coroutine@$DIR/coroutine.rs:26:5: 26:18}, _2: String) -> ()
+- yields (&str, String, &Location<'_>)
+-  {
+-     debug arg => _2;
+-     let mut _0: ();
++ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
++     coroutine layout {
++         field _s0: String;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++             Suspend1 (4): [_s0],
++         }
++         storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
++     }
++     debug arg => (((*_18) as variant#4).0: std::string::String);
++     coroutine debug arg => _s0;
++     let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
+      let _3: std::string::String;
+      let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
+      let mut _5: std::string::String;
+      let mut _6: &std::string::String;
+      let mut _7: &std::panic::Location<'_>;
+      let _8: std::string::String;
+      let mut _9: (&str, std::string::String, &std::panic::Location<'_>);
+      let mut _10: &str;
+      let _11: &str;
+      let mut _12: std::string::String;
+      let mut _13: &std::string::String;
+      let mut _14: &std::panic::Location<'_>;
+      let _15: &std::panic::Location<'_>;
++     let mut _16: ();
++     let mut _17: u32;
++     let mut _18: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18};
+  
+      bb0: {
+-         StorageLive(_3);
+-         StorageLive(_4);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = &_2;
+-         _5 = <String as Clone>::clone(move _6) -> [return: bb1, unwind: bb31];
++         _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18});
++         _17 = discriminant((*_18));
++         switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageLive(_7);
+-         _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb30];
++         _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb21];
+      }
+  
+      bb2: {
+          _4 = (const "first", move _5, move _7);
+          StorageDead(_7);
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_5);
+-         _3 = yield(move _4) -> [resume: bb4, drop: bb18];
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
++         StorageDead(_3);
++         StorageDead(_4);
++         discriminant((*_18)) = 3;
++         return;
+      }
+  
+      bb4: {
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_4);
+-         drop(_3) -> [return: bb6, unwind: bb34];
++         drop(_3) -> [return: bb6, unwind: bb25];
+      }
+  
+      bb6: {
+          StorageDead(_3);
+          StorageLive(_8);
+          StorageLive(_9);
+          StorageLive(_10);
+          StorageLive(_11);
+          _11 = const "second";
+          _10 = &(*_11);
+          StorageLive(_12);
+          StorageLive(_13);
+-         _13 = &_2;
+-         _12 = <String as Clone>::clone(move _13) -> [return: bb7, unwind: bb28];
++         _13 = &(((*_18) as variant#4).0: std::string::String);
++         _12 = <String as Clone>::clone(move _13) -> [return: bb7, unwind: bb19];
+      }
+  
+      bb7: {
+          StorageDead(_13);
+          StorageLive(_14);
+          StorageLive(_15);
+-         _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb24];
++         _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb15];
+      }
+  
+      bb8: {
+          _14 = &(*_15);
+          _9 = (move _10, move _12, move _14);
+          StorageDead(_14);
+          goto -> bb9;
+      }
+  
+      bb9: {
+          StorageDead(_12);
+          StorageDead(_10);
+-         _8 = yield(move _9) -> [resume: bb10, drop: bb15];
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9);
++         StorageDead(_8);
++         StorageDead(_9);
++         StorageDead(_11);
++         StorageDead(_15);
++         discriminant((*_18)) = 4;
++         return;
+      }
+  
+      bb10: {
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_9);
+-         drop(_8) -> [return: bb12, unwind: bb27];
++         drop(_8) -> [return: bb12, unwind: bb18];
+      }
+  
+      bb12: {
+          StorageDead(_15);
+          StorageDead(_11);
+          StorageDead(_8);
+-         _0 = const ();
+-         drop(_2) -> [return: bb13, unwind: bb36];
++         _16 = const ();
++         drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb13, unwind: bb27];
+      }
+  
+      bb13: {
+-         drop(_1) -> [return: bb14, unwind: bb37];
++         goto -> bb29;
+      }
+  
+      bb14: {
++         _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
++         discriminant((*_18)) = 1;
+          return;
+      }
+  
+-     bb15: {
+-         goto -> bb16;
++     bb15 (cleanup): {
++         StorageDead(_14);
++         drop(_12) -> [return: bb16, unwind terminate(cleanup)];
+      }
+  
+-     bb16: {
+-         StorageDead(_9);
++     bb16 (cleanup): {
++         StorageDead(_12);
++         StorageDead(_10);
+          goto -> bb17;
+      }
+  
+-     bb17: {
+-         StorageDead(_15);
+-         StorageDead(_11);
+-         StorageDead(_8);
+-         goto -> bb21;
++     bb17 (cleanup): {
++         StorageDead(_9);
++         goto -> bb18;
+      }
+  
+-     bb18: {
+-         goto -> bb19;
++     bb18 (cleanup): {
++         StorageDead(_15);
++         goto -> bb20;
+      }
+  
+-     bb19: {
+-         StorageDead(_4);
++     bb19 (cleanup): {
++         StorageDead(_13);
++         StorageDead(_12);
++         StorageDead(_10);
++         StorageDead(_9);
+          goto -> bb20;
+      }
+  
+-     bb20: {
+-         StorageDead(_3);
+-         goto -> bb21;
++     bb20 (cleanup): {
++         StorageDead(_11);
++         StorageDead(_8);
++         goto -> bb26;
+      }
+  
+-     bb21: {
+-         drop(_2) -> [return: bb22, unwind: bb38];
++     bb21 (cleanup): {
++         StorageDead(_7);
++         drop(_5) -> [return: bb23, unwind terminate(cleanup)];
+      }
+  
+-     bb22: {
+-         drop(_1) -> [return: bb23, unwind: bb37];
++     bb22 (cleanup): {
++         StorageDead(_6);
++         goto -> bb23;
+      }
+  
+-     bb23: {
+-         coroutine_drop;
++     bb23 (cleanup): {
++         StorageDead(_5);
++         goto -> bb24;
+      }
+  
+      bb24 (cleanup): {
+-         StorageDead(_14);
+-         drop(_12) -> [return: bb25, unwind terminate(cleanup)];
++         StorageDead(_4);
++         goto -> bb25;
+      }
+  
+      bb25 (cleanup): {
+-         StorageDead(_12);
+-         StorageDead(_10);
++         StorageDead(_3);
+          goto -> bb26;
+      }
+  
+      bb26 (cleanup): {
+-         StorageDead(_9);
+-         goto -> bb27;
++         drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb27, unwind terminate(cleanup)];
+      }
+  
+      bb27 (cleanup): {
+-         StorageDead(_15);
+-         goto -> bb29;
++         goto -> bb28;
+      }
+  
+      bb28 (cleanup): {
+-         StorageDead(_13);
+-         StorageDead(_12);
+-         StorageDead(_10);
+-         StorageDead(_9);
+-         goto -> bb29;
++         goto -> bb30;
+      }
+  
+-     bb29 (cleanup): {
+-         StorageDead(_11);
+-         StorageDead(_8);
+-         goto -> bb35;
++     bb29: {
++         goto -> bb14;
+      }
+  
+      bb30 (cleanup): {
+-         StorageDead(_7);
+-         drop(_5) -> [return: bb32, unwind terminate(cleanup)];
++         discriminant((*_18)) = 2;
++         resume;
+      }
+  
+-     bb31 (cleanup): {
+-         StorageDead(_6);
+-         goto -> bb32;
++     bb31: {
++         StorageLive(_3);
++         StorageLive(_4);
++         _3 = move _2;
++         goto -> bb4;
+      }
+  
+-     bb32 (cleanup): {
+-         StorageDead(_5);
+-         goto -> bb33;
++     bb32: {
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_11);
++         StorageLive(_15);
++         _8 = move _2;
++         goto -> bb10;
+      }
+  
+-     bb33 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb34;
++     bb33: {
++         assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue];
+      }
+  
+-     bb34 (cleanup): {
+-         StorageDead(_3);
+-         goto -> bb35;
++     bb34: {
++         assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue];
+      }
+  
+-     bb35 (cleanup): {
+-         drop(_2) -> [return: bb36, unwind terminate(cleanup)];
++     bb35: {
++         unreachable;
+      }
+  
+-     bb36 (cleanup): {
+-         drop(_1) -> [return: bb37, unwind terminate(cleanup)];
+-     }
+- 
+-     bb37 (cleanup): {
+-         resume;
+-     }
+- 
+-     bb38 (cleanup): {
+-         drop(_1) -> [return: bb37, unwind terminate(cleanup)];
++     bb36: {
++         (((*_18) as variant#4).0: std::string::String) = move _2;
++         StorageLive(_3);
++         StorageLive(_4);
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = &(((*_18) as variant#4).0: std::string::String);
++         _5 = <String as Clone>::clone(move _6) -> [return: bb1, unwind: bb22];
+      }
+  }
+  
+  ALLOC0 (size: 6, align: 1) {
+      73 65 63 6f 6e 64                               │ second
+  }
+  
+  ALLOC1 (size: 5, align: 1) {
+      66 69 72 73 74                                  │ first
+  }
+  
diff --git a/tests/mir-opt/building/coroutine.rs b/tests/mir-opt/coroutine/coroutine.rs
similarity index 77%
rename from tests/mir-opt/building/coroutine.rs
rename to tests/mir-opt/coroutine/coroutine.rs
index 77388c8..15d3cbb 100644
--- a/tests/mir-opt/building/coroutine.rs
+++ b/tests/mir-opt/coroutine/coroutine.rs
@@ -1,6 +1,7 @@
 //@ skip-filecheck
 //@ edition:2024
-//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
+//@ compile-flags: -Zmir-opt-level=0
+//@ needs-unwind
 
 #![feature(stmt_expr_attributes)]
 #![feature(closure_track_caller)]
@@ -11,8 +12,8 @@
 use std::panic::Location;
 use std::pin::Pin;
 
-// EMIT_MIR coroutine.main-{closure#0}.StateTransform.after.mir
-// EMIT_MIR coroutine.main-{closure#1}.StateTransform.after.mir
+// EMIT_MIR coroutine.main-{closure#0}.StateTransform.diff
+// EMIT_MIR coroutine.main-{closure#1}.StateTransform.diff
 fn main() {
     let simple = #[coroutine]
     |arg: String| {
diff --git "a/tests/mir-opt/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-abort.mir" "b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-abort.mir"
similarity index 100%
rename from "tests/mir-opt/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-abort.mir"
rename to "tests/mir-opt/coroutine/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-abort.mir"
diff --git "a/tests/mir-opt/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-unwind.mir" "b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-unwind.mir"
similarity index 100%
rename from "tests/mir-opt/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-unwind.mir"
rename to "tests/mir-opt/coroutine/coroutine_drop_cleanup.main-\173closure\0430\175.coroutine_drop.0.panic-unwind.mir"
diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine/coroutine_drop_cleanup.rs
similarity index 100%
rename from tests/mir-opt/coroutine_drop_cleanup.rs
rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.rs
diff --git "a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-abort.diff" "b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-abort.diff"
new file mode 100644
index 0000000..9e4fb0c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-abort.diff"
@@ -0,0 +1,141 @@
+- // MIR for `main::{closure#0}` before StateTransform
++ // MIR for `main::{closure#0}` after StateTransform
+  
+- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}>, _2: ()) -> CoroutineState<(), ()> {
++     coroutine layout {
++         field _s0: Foo;
++         field _s1: Bar;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1],
++         }
++         storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s0, _s1), (_s1, _s0), (_s1, _s1)}
++     }
++     coroutine debug a => _s0;
++     let mut _0: std::ops::CoroutineState<(), ()>;
+      let _3: Foo;
+      let _5: ();
+      let mut _6: ();
+      let _7: ();
+      let mut _8: Foo;
+      let _9: ();
+      let mut _10: Bar;
++     let mut _11: ();
++     let mut _12: u32;
++     let mut _13: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7};
+      scope 1 {
+-         debug a => _3;
++         debug a => (((*_13) as variant#3).0: Foo);
++         coroutine debug b => _s1;
+          let _4: Bar;
+          scope 2 {
+-             debug b => _4;
++             debug b => (((*_13) as variant#3).1: Bar);
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = Foo(const 5_i32);
+-         StorageLive(_4);
+-         _4 = Bar(const 6_i32);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = ();
+-         _5 = yield(move _6) -> [resume: bb1, drop: bb6];
++         _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7});
++         _12 = discriminant((*_13));
++         switchInt(move _12) -> [0: bb10, 1: bb8, 3: bb7, otherwise: bb9];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+          StorageLive(_7);
+          StorageLive(_8);
+-         _8 = move _3;
++         _8 = move (((*_13) as variant#3).0: Foo);
+          _7 = take::<Foo>(move _8) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+-         _10 = move _4;
++         _10 = move (((*_13) as variant#3).1: Bar);
+          _9 = take::<Bar>(move _10) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          StorageDead(_10);
+          StorageDead(_9);
+-         _0 = const ();
+-         StorageDead(_4);
++         _11 = const ();
++         nop;
+          goto -> bb4;
+      }
+  
+      bb4: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb5, unwind unreachable];
++         nop;
++         goto -> bb6;
+      }
+  
+      bb5: {
++         _0 = CoroutineState::<(), ()>::Complete(move _11);
++         discriminant((*_13)) = 1;
+          return;
+      }
+  
+      bb6: {
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb7, unwind unreachable];
++         goto -> bb5;
+      }
+  
+      bb7: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb8, unwind unreachable];
++         StorageLive(_5);
++         StorageLive(_6);
++         _5 = move _2;
++         goto -> bb1;
+      }
+  
+      bb8: {
+-         coroutine_drop;
++         assert(const false, "coroutine resumed after completion") -> [success: bb8, unwind unreachable];
++     }
++ 
++     bb9: {
++         unreachable;
++     }
++ 
++     bb10: {
++         nop;
++         (((*_13) as variant#3).0: Foo) = Foo(const 5_i32);
++         nop;
++         (((*_13) as variant#3).1: Bar) = Bar(const 6_i32);
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = ();
++         _0 = CoroutineState::<(), ()>::Yielded(move _6);
++         StorageDead(_5);
++         StorageDead(_6);
++         discriminant((*_13)) = 3;
++         return;
+      }
+  }
+  
diff --git "a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-unwind.diff" "b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-unwind.diff"
new file mode 100644
index 0000000..fa89df1
--- /dev/null
+++ "b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.panic-unwind.diff"
@@ -0,0 +1,201 @@
+- // MIR for `main::{closure#0}` before StateTransform
++ // MIR for `main::{closure#0}` after StateTransform
+  
+- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
+- yields ()
+-  {
+-     let mut _0: ();
++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}>, _2: ()) -> CoroutineState<(), ()> {
++     coroutine layout {
++         field _s0: Foo;
++         field _s1: Bar;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0, _s1],
++         }
++         storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s0, _s1), (_s1, _s0), (_s1, _s1)}
++     }
++     coroutine debug a => _s0;
++     let mut _0: std::ops::CoroutineState<(), ()>;
+      let _3: Foo;
+      let _5: ();
+      let mut _6: ();
+      let _7: ();
+      let mut _8: Foo;
+      let _9: ();
+      let mut _10: Bar;
++     let mut _11: ();
++     let mut _12: u32;
++     let mut _13: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7};
+      scope 1 {
+-         debug a => _3;
++         debug a => (((*_13) as variant#3).0: Foo);
++         coroutine debug b => _s1;
+          let _4: Bar;
+          scope 2 {
+-             debug b => _4;
++             debug b => (((*_13) as variant#3).1: Bar);
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = Foo(const 5_i32);
+-         StorageLive(_4);
+-         _4 = Bar(const 6_i32);
+-         StorageLive(_5);
+-         StorageLive(_6);
+-         _6 = ();
+-         _5 = yield(move _6) -> [resume: bb1, drop: bb6];
++         _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7});
++         _12 = discriminant((*_13));
++         switchInt(move _12) -> [0: bb18, 1: bb16, 2: bb15, 3: bb14, otherwise: bb17];
+      }
+  
+      bb1: {
+          StorageDead(_6);
+          StorageDead(_5);
+          StorageLive(_7);
+          StorageLive(_8);
+-         _8 = move _3;
+-         _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb10];
++         _8 = move (((*_13) as variant#3).0: Foo);
++         _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb7];
+      }
+  
+      bb2: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+-         _10 = move _4;
+-         _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb9];
++         _10 = move (((*_13) as variant#3).1: Bar);
++         _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb6];
+      }
+  
+      bb3: {
+          StorageDead(_10);
+          StorageDead(_9);
+-         _0 = const ();
+-         StorageDead(_4);
++         _11 = const ();
++         nop;
+          goto -> bb4;
+      }
+  
+      bb4: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb5, unwind: bb14];
++         nop;
++         goto -> bb12;
+      }
+  
+      bb5: {
++         _0 = CoroutineState::<(), ()>::Complete(move _11);
++         discriminant((*_13)) = 1;
+          return;
+      }
+  
+-     bb6: {
+-         StorageDead(_6);
+-         StorageDead(_5);
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb7, unwind: bb15];
++     bb6 (cleanup): {
++         StorageDead(_10);
++         StorageDead(_9);
++         goto -> bb9;
+      }
+  
+-     bb7: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb8, unwind: bb14];
++     bb7 (cleanup): {
++         goto -> bb8;
+      }
+  
+-     bb8: {
+-         coroutine_drop;
++     bb8 (cleanup): {
++         StorageDead(_8);
++         StorageDead(_7);
++         goto -> bb9;
+      }
+  
+      bb9 (cleanup): {
+-         StorageDead(_10);
+-         StorageDead(_9);
+-         goto -> bb12;
++         nop;
++         goto -> bb10;
+      }
+  
+      bb10 (cleanup): {
++         nop;
+          goto -> bb11;
+      }
+  
+      bb11 (cleanup): {
+-         StorageDead(_8);
+-         StorageDead(_7);
+-         goto -> bb12;
++         goto -> bb13;
+      }
+  
+-     bb12 (cleanup): {
+-         StorageDead(_4);
+-         goto -> bb13;
++     bb12: {
++         goto -> bb5;
+      }
+  
+      bb13 (cleanup): {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb14, unwind terminate(cleanup)];
++         discriminant((*_13)) = 2;
++         resume;
+      }
+  
+-     bb14 (cleanup): {
+-         resume;
++     bb14: {
++         StorageLive(_5);
++         StorageLive(_6);
++         _5 = move _2;
++         goto -> bb1;
+      }
+  
+-     bb15 (cleanup): {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb14, unwind terminate(cleanup)];
++     bb15: {
++         assert(const false, "coroutine resumed after panicking") -> [success: bb15, unwind continue];
++     }
++ 
++     bb16: {
++         assert(const false, "coroutine resumed after completion") -> [success: bb16, unwind continue];
++     }
++ 
++     bb17: {
++         unreachable;
++     }
++ 
++     bb18: {
++         nop;
++         (((*_13) as variant#3).0: Foo) = Foo(const 5_i32);
++         nop;
++         (((*_13) as variant#3).1: Bar) = Bar(const 6_i32);
++         StorageLive(_5);
++         StorageLive(_6);
++         _6 = ();
++         _0 = CoroutineState::<(), ()>::Yielded(move _6);
++         StorageDead(_5);
++         StorageDead(_6);
++         discriminant((*_13)) = 3;
++         return;
+      }
+  }
+  
diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs
similarity index 96%
rename from tests/mir-opt/coroutine_storage_dead_unwind.rs
rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs
index 0537aed..1267f72 100644
--- a/tests/mir-opt/coroutine_storage_dead_unwind.rs
+++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs
@@ -18,7 +18,7 @@ fn drop(&mut self) {}
 
 fn take<T>(_x: T) {}
 
-// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
+// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.diff
 fn main() {
     let _gen = #[coroutine]
     || {
diff --git "a/tests/mir-opt/coroutine/coroutine_tiny.main-\173closure\0430\175.StateTransform.diff" "b/tests/mir-opt/coroutine/coroutine_tiny.main-\173closure\0430\175.StateTransform.diff"
new file mode 100644
index 0000000..b84e55c
--- /dev/null
+++ "b/tests/mir-opt/coroutine/coroutine_tiny.main-\173closure\0430\175.StateTransform.diff"
@@ -0,0 +1,98 @@
+- // MIR for `main::{closure#0}` before StateTransform
++ // MIR for `main::{closure#0}` after StateTransform
+  
+- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13}, _2: u8) -> ()
+- yields ()
+-  {
++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13}>, _2: u8) -> CoroutineState<(), ()> {
++     coroutine layout {
++         field _s0: HasDrop;
++         variant_fields = {
++             Unresumed(0): [],
++             Returned (1): [],
++             Panicked (2): [],
++             Suspend0 (3): [_s0],
++         }
++         storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
++     }
+      debug _x => _2;
+-     let mut _0: ();
++     coroutine debug _d => _s0;
++     let mut _0: std::ops::CoroutineState<(), ()>;
+      let _3: HasDrop;
+      let mut _4: !;
+      let mut _5: ();
+      let _6: u8;
+      let mut _7: ();
+      let _8: ();
++     let mut _9: ();
++     let mut _10: u32;
++     let mut _11: &mut {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13};
+      scope 1 {
+-         debug _d => _3;
++         debug _d => (((*_11) as variant#3).0: HasDrop);
+      }
+  
+      bb0: {
+-         StorageLive(_3);
+-         _3 = HasDrop;
+-         StorageLive(_4);
+-         goto -> bb1;
++         _11 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13});
++         _10 = discriminant((*_11));
++         switchInt(move _10) -> [0: bb6, 3: bb4, otherwise: bb5];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = ();
+-         _6 = yield(move _7) -> [resume: bb2, drop: bb4];
++         _0 = CoroutineState::<(), ()>::Yielded(move _7);
++         StorageDead(_4);
++         StorageDead(_6);
++         StorageDead(_7);
++         discriminant((*_11)) = 3;
++         return;
+      }
+  
+      bb2: {
+          StorageDead(_7);
+          StorageDead(_6);
+          StorageLive(_8);
+          _8 = callee() -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          StorageDead(_8);
+          _5 = const ();
+          goto -> bb1;
+      }
+  
+      bb4: {
+-         StorageDead(_7);
+-         StorageDead(_6);
+-         StorageDead(_4);
+-         drop(_3) -> [return: bb5, unwind unreachable];
++         StorageLive(_4);
++         StorageLive(_6);
++         StorageLive(_7);
++         _6 = move _2;
++         goto -> bb2;
+      }
+  
+      bb5: {
+-         StorageDead(_3);
+-         drop(_1) -> [return: bb6, unwind unreachable];
++         unreachable;
+      }
+  
+      bb6: {
+-         coroutine_drop;
++         nop;
++         (((*_11) as variant#3).0: HasDrop) = HasDrop;
++         StorageLive(_4);
++         goto -> bb1;
+      }
+  }
+  
diff --git a/tests/mir-opt/coroutine_tiny.rs b/tests/mir-opt/coroutine/coroutine_tiny.rs
similarity index 81%
rename from tests/mir-opt/coroutine_tiny.rs
rename to tests/mir-opt/coroutine/coroutine_tiny.rs
index b92628a..2f3a774 100644
--- a/tests/mir-opt/coroutine_tiny.rs
+++ b/tests/mir-opt/coroutine/coroutine_tiny.rs
@@ -1,4 +1,3 @@
-//@ skip-filecheck
 //! Tests that coroutines that cannot return or unwind don't have unnecessary
 //! panic branches.
 
@@ -15,7 +14,7 @@ fn drop(&mut self) {}
 
 fn callee() {}
 
-// EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
+// EMIT_MIR coroutine_tiny.main-{closure#0}.StateTransform.diff
 fn main() {
     let _gen = #[coroutine]
     |_x: u8| {
@@ -26,3 +25,6 @@ fn main() {
         }
     };
 }
+
+// CHECK-NOT: panic
+// CHECK-NOT: cleanup
diff --git "a/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-abort.mir" "b/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-abort.mir"
deleted file mode 100644
index 4731aed..0000000
--- "a/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-abort.mir"
+++ /dev/null
@@ -1,83 +0,0 @@
-// MIR for `main::{closure#0}` before StateTransform
-
-fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
-yields ()
- {
-    let mut _0: ();
-    let _3: Foo;
-    let _5: ();
-    let mut _6: ();
-    let _7: ();
-    let mut _8: Foo;
-    let _9: ();
-    let mut _10: Bar;
-    scope 1 {
-        debug a => _3;
-        let _4: Bar;
-        scope 2 {
-            debug b => _4;
-        }
-    }
-
-    bb0: {
-        StorageLive(_3);
-        _3 = Foo(const 5_i32);
-        StorageLive(_4);
-        _4 = Bar(const 6_i32);
-        StorageLive(_5);
-        StorageLive(_6);
-        _6 = ();
-        _5 = yield(move _6) -> [resume: bb1, drop: bb6];
-    }
-
-    bb1: {
-        StorageDead(_6);
-        StorageDead(_5);
-        StorageLive(_7);
-        StorageLive(_8);
-        _8 = move _3;
-        _7 = take::<Foo>(move _8) -> [return: bb2, unwind unreachable];
-    }
-
-    bb2: {
-        StorageDead(_8);
-        StorageDead(_7);
-        StorageLive(_9);
-        StorageLive(_10);
-        _10 = move _4;
-        _9 = take::<Bar>(move _10) -> [return: bb3, unwind unreachable];
-    }
-
-    bb3: {
-        StorageDead(_10);
-        StorageDead(_9);
-        _0 = const ();
-        StorageDead(_4);
-        goto -> bb4;
-    }
-
-    bb4: {
-        StorageDead(_3);
-        drop(_1) -> [return: bb5, unwind unreachable];
-    }
-
-    bb5: {
-        return;
-    }
-
-    bb6: {
-        StorageDead(_6);
-        StorageDead(_5);
-        StorageDead(_4);
-        drop(_3) -> [return: bb7, unwind unreachable];
-    }
-
-    bb7: {
-        StorageDead(_3);
-        drop(_1) -> [return: bb8, unwind unreachable];
-    }
-
-    bb8: {
-        coroutine_drop;
-    }
-}
diff --git "a/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-unwind.mir" "b/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-unwind.mir"
deleted file mode 100644
index 14e1782..0000000
--- "a/tests/mir-opt/coroutine_storage_dead_unwind.main-\173closure\0430\175.StateTransform.before.panic-unwind.mir"
+++ /dev/null
@@ -1,118 +0,0 @@
-// MIR for `main::{closure#0}` before StateTransform
-
-fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
-yields ()
- {
-    let mut _0: ();
-    let _3: Foo;
-    let _5: ();
-    let mut _6: ();
-    let _7: ();
-    let mut _8: Foo;
-    let _9: ();
-    let mut _10: Bar;
-    scope 1 {
-        debug a => _3;
-        let _4: Bar;
-        scope 2 {
-            debug b => _4;
-        }
-    }
-
-    bb0: {
-        StorageLive(_3);
-        _3 = Foo(const 5_i32);
-        StorageLive(_4);
-        _4 = Bar(const 6_i32);
-        StorageLive(_5);
-        StorageLive(_6);
-        _6 = ();
-        _5 = yield(move _6) -> [resume: bb1, drop: bb6];
-    }
-
-    bb1: {
-        StorageDead(_6);
-        StorageDead(_5);
-        StorageLive(_7);
-        StorageLive(_8);
-        _8 = move _3;
-        _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb10];
-    }
-
-    bb2: {
-        StorageDead(_8);
-        StorageDead(_7);
-        StorageLive(_9);
-        StorageLive(_10);
-        _10 = move _4;
-        _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb9];
-    }
-
-    bb3: {
-        StorageDead(_10);
-        StorageDead(_9);
-        _0 = const ();
-        StorageDead(_4);
-        goto -> bb4;
-    }
-
-    bb4: {
-        StorageDead(_3);
-        drop(_1) -> [return: bb5, unwind: bb14];
-    }
-
-    bb5: {
-        return;
-    }
-
-    bb6: {
-        StorageDead(_6);
-        StorageDead(_5);
-        StorageDead(_4);
-        drop(_3) -> [return: bb7, unwind: bb15];
-    }
-
-    bb7: {
-        StorageDead(_3);
-        drop(_1) -> [return: bb8, unwind: bb14];
-    }
-
-    bb8: {
-        coroutine_drop;
-    }
-
-    bb9 (cleanup): {
-        StorageDead(_10);
-        StorageDead(_9);
-        goto -> bb12;
-    }
-
-    bb10 (cleanup): {
-        goto -> bb11;
-    }
-
-    bb11 (cleanup): {
-        StorageDead(_8);
-        StorageDead(_7);
-        goto -> bb12;
-    }
-
-    bb12 (cleanup): {
-        StorageDead(_4);
-        goto -> bb13;
-    }
-
-    bb13 (cleanup): {
-        StorageDead(_3);
-        drop(_1) -> [return: bb14, unwind terminate(cleanup)];
-    }
-
-    bb14 (cleanup): {
-        resume;
-    }
-
-    bb15 (cleanup): {
-        StorageDead(_3);
-        drop(_1) -> [return: bb14, unwind terminate(cleanup)];
-    }
-}
diff --git "a/tests/mir-opt/coroutine_tiny.main-\173closure\0430\175.coroutine_resume.0.mir" "b/tests/mir-opt/coroutine_tiny.main-\173closure\0430\175.coroutine_resume.0.mir"
deleted file mode 100644
index 222c714..0000000
--- "a/tests/mir-opt/coroutine_tiny.main-\173closure\0430\175.coroutine_resume.0.mir"
+++ /dev/null
@@ -1,89 +0,0 @@
-// MIR for `main::{closure#0}` 0 coroutine_resume
-/* coroutine_layout = CoroutineLayout {
-    field_tys: {
-        _s0: CoroutineSavedTy {
-            ty: HasDrop,
-            source_info: SourceInfo {
-                span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
-                scope: scope[0],
-            },
-            ignore_for_traits: false,
-        },
-    },
-    variant_fields: {
-        Unresumed(0): [],
-        Returned (1): [],
-        Panicked (2): [],
-        Suspend0 (3): [_s0],
-    },
-    storage_conflicts: BitMatrix(1x1) {
-        (_s0, _s0),
-    },
-} */
-
-fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
-    debug _x => _2;
-    let mut _0: std::ops::CoroutineState<(), ()>;
-    let _3: HasDrop;
-    let mut _4: !;
-    let mut _5: ();
-    let _6: u8;
-    let mut _7: ();
-    let _8: ();
-    let mut _9: ();
-    let mut _10: u32;
-    let mut _11: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13};
-    scope 1 {
-        debug _d => (((*_11) as variant#3).0: HasDrop);
-    }
-
-    bb0: {
-        _11 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13});
-        _10 = discriminant((*_11));
-        switchInt(move _10) -> [0: bb1, 3: bb5, otherwise: bb6];
-    }
-
-    bb1: {
-        nop;
-        (((*_11) as variant#3).0: HasDrop) = HasDrop;
-        StorageLive(_4);
-        goto -> bb2;
-    }
-
-    bb2: {
-        StorageLive(_6);
-        StorageLive(_7);
-        _7 = ();
-        _0 = CoroutineState::<(), ()>::Yielded(move _7);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_7);
-        discriminant((*_11)) = 3;
-        return;
-    }
-
-    bb3: {
-        StorageDead(_7);
-        StorageDead(_6);
-        StorageLive(_8);
-        _8 = callee() -> [return: bb4, unwind unreachable];
-    }
-
-    bb4: {
-        StorageDead(_8);
-        _5 = const ();
-        goto -> bb2;
-    }
-
-    bb5: {
-        StorageLive(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _6 = move _2;
-        goto -> bb3;
-    }
-
-    bb6: {
-        unreachable;
-    }
-}
diff --git a/tests/mir-opt/inline_coroutine_body.rs b/tests/mir-opt/inline/inline_coroutine_body.rs
similarity index 100%
rename from tests/mir-opt/inline_coroutine_body.rs
rename to tests/mir-opt/inline/inline_coroutine_body.rs
diff --git "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff" "b/tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
similarity index 76%
rename from "tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
rename to "tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
index f8ef70b..617f2ad 100644
--- "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
+++ "b/tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
@@ -47,42 +47,42 @@
 +                         let _26: ();
 +                         scope 9 {
 +                         }
-+                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
++                         scope 11 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
-+                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _34: ();
-+                             let mut _35: std::option::Option<()>;
-+                             let mut _36: &mut std::option::Option<()>;
-+                             let mut _37: &mut std::future::Ready<()>;
-+                             let mut _38: &mut std::pin::Pin<&mut std::future::Ready<()>>;
-+                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
-+                                 let mut _39: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>;
-+                                 let mut _40: *mut std::pin::Pin<&mut std::future::Ready<()>>;
-+                                 scope 15 (inlined <pin::helper::PinHelper<&mut std::future::Ready<()>> as pin::helper::PinDerefMutHelper>::deref_mut) {
-+                                     let mut _41: &mut &mut std::future::Ready<()>;
-+                                     scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
++                         scope 12 (inlined <std::future::Ready<()> as Future>::poll) {
++                             let mut _33: ();
++                             let mut _34: std::option::Option<()>;
++                             let mut _35: &mut std::option::Option<()>;
++                             let mut _36: &mut std::future::Ready<()>;
++                             let mut _37: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             scope 13 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
++                                 let mut _38: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>;
++                                 let mut _39: *mut std::pin::Pin<&mut std::future::Ready<()>>;
++                                 scope 14 (inlined <pin::helper::PinHelper<&mut std::future::Ready<()>> as pin::helper::PinDerefMutHelper>::deref_mut) {
++                                     let mut _40: &mut &mut std::future::Ready<()>;
++                                     scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
 +                                     }
 +                                 }
 +                             }
-+                             scope 17 (inlined Option::<()>::take) {
-+                                 let mut _42: std::option::Option<()>;
-+                                 scope 18 (inlined std::mem::replace::<Option<()>>) {
-+                                     scope 19 {
++                             scope 16 (inlined Option::<()>::take) {
++                                 let mut _41: std::option::Option<()>;
++                                 scope 17 (inlined std::mem::replace::<Option<()>>) {
++                                     scope 18 {
 +                                     }
 +                                 }
 +                             }
-+                             scope 20 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _43: isize;
-+                                 let mut _44: !;
-+                                 scope 21 {
++                             scope 19 (inlined #[track_caller] Option::<()>::expect) {
++                                 let mut _42: isize;
++                                 let mut _43: !;
++                                 scope 20 {
 +                                 }
 +                             }
 +                         }
 +                     }
-+                     scope 10 (inlined ready::<()>) {
-+                         let mut _33: std::option::Option<()>;
++                     scope 10 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
-+                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
++                     scope 21 (inlined ready::<()>) {
++                         let mut _44: std::option::Option<()>;
 +                     }
 +                 }
 +             }
@@ -127,7 +127,7 @@
 +         StorageLive(_32);
 +         _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _31 = discriminant((*_32));
-+         switchInt(move _31) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
++         switchInt(move _31) -> [0: bb10, 1: bb9, 3: bb8, otherwise: bb4];
       }
   
 -     bb3: {
@@ -154,25 +154,6 @@
       }
   
 +     bb3: {
-+         (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>);
-+         StorageLive(_12);
-+         StorageLive(_13);
-+         StorageLive(_14);
-+         _14 = ();
-+         StorageLive(_33);
-+         _33 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _33);
-+         StorageDead(_33);
-+         StorageDead(_14);
-+         _12 = move _13;
-+         StorageDead(_13);
-+         (((*_32) as variant#3).1: std::future::Ready<()>) = move _12;
-+         goto -> bb4;
-+     }
-+ 
-      bb4: {
--         StorageDead(_2);
--         return;
 +         StorageLive(_17);
 +         StorageLive(_18);
 +         StorageLive(_19);
@@ -189,31 +170,33 @@
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
-+         StorageLive(_37);
-+         StorageLive(_39);
-+         StorageLive(_44);
-+         StorageLive(_34);
-+         StorageLive(_35);
-+         StorageLive(_40);
-+         _40 = &raw mut _19;
-+         _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr);
-+         StorageDead(_40);
-+         _37 = no_retag copy ((*_39).0: &mut std::future::Ready<()>);
-+         StorageLive(_42);
-+         _42 = Option::<()>::None;
-+         _35 = copy ((*_37).0: std::option::Option<()>);
-+         ((*_37).0: std::option::Option<()>) = move _42;
-+         StorageDead(_42);
++         StorageLive(_36);
++         StorageLive(_38);
 +         StorageLive(_43);
-+         _43 = discriminant(_35);
-+         switchInt(move _43) -> [0: bb11, 1: bb12, otherwise: bb5];
++         StorageLive(_33);
++         StorageLive(_34);
++         StorageLive(_39);
++         _39 = &raw mut _19;
++         _38 = copy _39 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr);
++         StorageDead(_39);
++         _36 = no_retag copy ((*_38).0: &mut std::future::Ready<()>);
++         StorageLive(_41);
++         _41 = Option::<()>::None;
++         _34 = copy ((*_36).0: std::option::Option<()>);
++         ((*_36).0: std::option::Option<()>) = move _41;
++         StorageDead(_41);
++         StorageLive(_42);
++         _42 = discriminant(_34);
++         switchInt(move _42) -> [0: bb11, 1: bb12, otherwise: bb4];
++     }
++ 
+      bb4: {
+-         StorageDead(_2);
+-         return;
++         unreachable;
       }
 + 
 +     bb5: {
-+         unreachable;
-+     }
-+ 
-+     bb6: {
 +         _17 = const ();
 +         StorageDead(_23);
 +         StorageDead(_21);
@@ -230,7 +213,7 @@
 +         goto -> bb2;
 +     }
 + 
-+     bb7: {
++     bb6: {
 +         StorageLive(_26);
 +         _26 = copy ((_18 as Ready).0: ());
 +         _30 = copy _26;
@@ -240,16 +223,16 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
++         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb7, unwind unreachable];
 +     }
 + 
-+     bb8: {
++     bb7: {
 +         _7 = Poll::<()>::Ready(move _30);
 +         discriminant((*_32)) = 1;
 +         goto -> bb2;
 +     }
 + 
-+     bb9: {
++     bb8: {
 +         StorageLive(_12);
 +         StorageLive(_28);
 +         StorageLive(_29);
@@ -258,30 +241,47 @@
 +         _9 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
-+         goto -> bb4;
++         goto -> bb3;
++     }
++ 
++     bb9: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb9, unwind unreachable];
 +     }
 + 
 +     bb10: {
-+         assert(const false, "`async fn` resumed after completion") -> [success: bb10, unwind unreachable];
++         (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>);
++         StorageLive(_12);
++         StorageLive(_13);
++         StorageLive(_14);
++         _14 = ();
++         StorageLive(_44);
++         _44 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _44);
++         StorageDead(_44);
++         StorageDead(_14);
++         _12 = move _13;
++         StorageDead(_13);
++         (((*_32) as variant#3).1: std::future::Ready<()>) = move _12;
++         goto -> bb3;
 +     }
 + 
 +     bb11: {
-+         _44 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
++         _43 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
 +     }
 + 
 +     bb12: {
-+         _34 = move ((_35 as Some).0: ());
-+         StorageDead(_43);
-+         StorageDead(_35);
-+         _18 = Poll::<()>::Ready(move _34);
++         _33 = move ((_34 as Some).0: ());
++         StorageDead(_42);
 +         StorageDead(_34);
-+         StorageDead(_44);
-+         StorageDead(_39);
-+         StorageDead(_37);
++         _18 = Poll::<()>::Ready(move _33);
++         StorageDead(_33);
++         StorageDead(_43);
++         StorageDead(_38);
++         StorageDead(_36);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
-+         switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5];
++         switchInt(move _25) -> [0: bb6, 1: bb5, otherwise: bb4];
 +     }
 + }
 + 
diff --git "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff" "b/tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
similarity index 76%
rename from "tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
rename to "tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
index 18be10c..f12462a 100644
--- "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
+++ "b/tests/mir-opt/inline/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
@@ -47,42 +47,42 @@
 +                         let _26: ();
 +                         scope 9 {
 +                         }
-+                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
++                         scope 11 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
-+                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _34: ();
-+                             let mut _35: std::option::Option<()>;
-+                             let mut _36: &mut std::option::Option<()>;
-+                             let mut _37: &mut std::future::Ready<()>;
-+                             let mut _38: &mut std::pin::Pin<&mut std::future::Ready<()>>;
-+                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
-+                                 let mut _39: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>;
-+                                 let mut _40: *mut std::pin::Pin<&mut std::future::Ready<()>>;
-+                                 scope 15 (inlined <pin::helper::PinHelper<&mut std::future::Ready<()>> as pin::helper::PinDerefMutHelper>::deref_mut) {
-+                                     let mut _41: &mut &mut std::future::Ready<()>;
-+                                     scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
++                         scope 12 (inlined <std::future::Ready<()> as Future>::poll) {
++                             let mut _33: ();
++                             let mut _34: std::option::Option<()>;
++                             let mut _35: &mut std::option::Option<()>;
++                             let mut _36: &mut std::future::Ready<()>;
++                             let mut _37: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             scope 13 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
++                                 let mut _38: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>;
++                                 let mut _39: *mut std::pin::Pin<&mut std::future::Ready<()>>;
++                                 scope 14 (inlined <pin::helper::PinHelper<&mut std::future::Ready<()>> as pin::helper::PinDerefMutHelper>::deref_mut) {
++                                     let mut _40: &mut &mut std::future::Ready<()>;
++                                     scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
 +                                     }
 +                                 }
 +                             }
-+                             scope 17 (inlined Option::<()>::take) {
-+                                 let mut _42: std::option::Option<()>;
-+                                 scope 18 (inlined std::mem::replace::<Option<()>>) {
-+                                     scope 19 {
++                             scope 16 (inlined Option::<()>::take) {
++                                 let mut _41: std::option::Option<()>;
++                                 scope 17 (inlined std::mem::replace::<Option<()>>) {
++                                     scope 18 {
 +                                     }
 +                                 }
 +                             }
-+                             scope 20 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _43: isize;
-+                                 let mut _44: !;
-+                                 scope 21 {
++                             scope 19 (inlined #[track_caller] Option::<()>::expect) {
++                                 let mut _42: isize;
++                                 let mut _43: !;
++                                 scope 20 {
 +                                 }
 +                             }
 +                         }
 +                     }
-+                     scope 10 (inlined ready::<()>) {
-+                         let mut _33: std::option::Option<()>;
++                     scope 10 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
-+                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
++                     scope 21 (inlined ready::<()>) {
++                         let mut _44: std::option::Option<()>;
 +                     }
 +                 }
 +             }
@@ -127,7 +127,7 @@
 +         StorageLive(_32);
 +         _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _31 = discriminant((*_32));
-+         switchInt(move _31) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
++         switchInt(move _31) -> [0: bb15, 1: bb14, 2: bb13, 3: bb12, otherwise: bb6];
       }
   
 -     bb3: {
@@ -165,25 +165,6 @@
 -         StorageDead(_2);
 -         return;
 +     bb5: {
-+         (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>);
-+         StorageLive(_12);
-+         StorageLive(_13);
-+         StorageLive(_14);
-+         _14 = ();
-+         StorageLive(_33);
-+         _33 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _33);
-+         StorageDead(_33);
-+         StorageDead(_14);
-+         _12 = move _13;
-+         StorageDead(_13);
-+         (((*_32) as variant#3).1: std::future::Ready<()>) = move _12;
-+         goto -> bb6;
-      }
-  
--     bb5 (cleanup): {
--         drop(_2) -> [return: bb6, unwind terminate(cleanup)];
-+     bb6: {
 +         StorageLive(_17);
 +         StorageLive(_18);
 +         StorageLive(_19);
@@ -200,33 +181,35 @@
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
-+         StorageLive(_37);
-+         StorageLive(_39);
-+         StorageLive(_44);
-+         StorageLive(_34);
-+         StorageLive(_35);
-+         StorageLive(_40);
-+         _40 = &raw mut _19;
-+         _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr);
-+         StorageDead(_40);
-+         _37 = no_retag copy ((*_39).0: &mut std::future::Ready<()>);
-+         StorageLive(_42);
-+         _42 = Option::<()>::None;
-+         _35 = copy ((*_37).0: std::option::Option<()>);
-+         ((*_37).0: std::option::Option<()>) = move _42;
-+         StorageDead(_42);
++         StorageLive(_36);
++         StorageLive(_38);
 +         StorageLive(_43);
-+         _43 = discriminant(_35);
-+         switchInt(move _43) -> [0: bb16, 1: bb17, otherwise: bb7];
++         StorageLive(_33);
++         StorageLive(_34);
++         StorageLive(_39);
++         _39 = &raw mut _19;
++         _38 = copy _39 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr);
++         StorageDead(_39);
++         _36 = no_retag copy ((*_38).0: &mut std::future::Ready<()>);
++         StorageLive(_41);
++         _41 = Option::<()>::None;
++         _34 = copy ((*_36).0: std::option::Option<()>);
++         ((*_36).0: std::option::Option<()>) = move _41;
++         StorageDead(_41);
++         StorageLive(_42);
++         _42 = discriminant(_34);
++         switchInt(move _42) -> [0: bb16, 1: bb17, otherwise: bb6];
+      }
+  
+-     bb5 (cleanup): {
+-         drop(_2) -> [return: bb6, unwind terminate(cleanup)];
++     bb6: {
++         unreachable;
       }
   
 -     bb6 (cleanup): {
 -         resume;
 +     bb7: {
-+         unreachable;
-      }
-+ 
-+     bb8: {
 +         _17 = const ();
 +         StorageDead(_23);
 +         StorageDead(_21);
@@ -241,9 +224,9 @@
 +         StorageDead(_29);
 +         discriminant((*_32)) = 3;
 +         goto -> bb4;
-+     }
+      }
 + 
-+     bb9: {
++     bb8: {
 +         StorageLive(_26);
 +         _26 = copy ((_18 as Ready).0: ());
 +         _30 = copy _26;
@@ -253,16 +236,16 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
++         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb9, unwind: bb11];
 +     }
 + 
-+     bb10: {
++     bb9: {
 +         _7 = Poll::<()>::Ready(move _30);
 +         discriminant((*_32)) = 1;
 +         goto -> bb4;
 +     }
 + 
-+     bb11 (cleanup): {
++     bb10 (cleanup): {
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         StorageDead(_23);
@@ -270,15 +253,15 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
++         drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind terminate(cleanup)];
 +     }
 + 
-+     bb12 (cleanup): {
++     bb11 (cleanup): {
 +         discriminant((*_32)) = 2;
 +         goto -> bb2;
 +     }
 + 
-+     bb13: {
++     bb12: {
 +         StorageLive(_12);
 +         StorageLive(_28);
 +         StorageLive(_29);
@@ -287,34 +270,51 @@
 +         _9 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
-+         goto -> bb6;
++         goto -> bb5;
++     }
++ 
++     bb13: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb13, unwind: bb2];
 +     }
 + 
 +     bb14: {
-+         assert(const false, "`async fn` resumed after panicking") -> [success: bb14, unwind: bb2];
++         assert(const false, "`async fn` resumed after completion") -> [success: bb14, unwind: bb2];
 +     }
 + 
 +     bb15: {
-+         assert(const false, "`async fn` resumed after completion") -> [success: bb15, unwind: bb2];
++         (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>);
++         StorageLive(_12);
++         StorageLive(_13);
++         StorageLive(_14);
++         _14 = ();
++         StorageLive(_44);
++         _44 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _44);
++         StorageDead(_44);
++         StorageDead(_14);
++         _12 = move _13;
++         StorageDead(_13);
++         (((*_32) as variant#3).1: std::future::Ready<()>) = move _12;
++         goto -> bb5;
 +     }
 + 
 +     bb16: {
-+         _44 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
++         _43 = option::expect_failed(const "`Ready` polled after completion") -> bb10;
 +     }
 + 
 +     bb17: {
-+         _34 = move ((_35 as Some).0: ());
-+         StorageDead(_43);
-+         StorageDead(_35);
-+         _18 = Poll::<()>::Ready(move _34);
++         _33 = move ((_34 as Some).0: ());
++         StorageDead(_42);
 +         StorageDead(_34);
-+         StorageDead(_44);
-+         StorageDead(_39);
-+         StorageDead(_37);
++         _18 = Poll::<()>::Ready(move _33);
++         StorageDead(_33);
++         StorageDead(_43);
++         StorageDead(_38);
++         StorageDead(_36);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
-+         switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7];
++         switchInt(move _25) -> [0: bb8, 1: bb7, otherwise: bb6];
 +     }
 + }
 + 
diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
index c5875e8..8b303fe 100644
--- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
@@ -36,24 +36,28 @@
 +                         }
 +                     }
 +                 }
-+                 scope 13 (inlined slice_from_raw_parts_mut::<A>) {
-+                     scope 14 (inlined std::ptr::from_raw_parts_mut::<[A], A>) {
++                 scope 13 (inlined std::ptr::mut_ptr::<impl *mut A>::cast_slice) {
++                     scope 14 (inlined slice_from_raw_parts_mut::<A>) {
++                         scope 15 (inlined std::ptr::from_raw_parts_mut::<[A], A>) {
++                         }
 +                     }
 +                 }
-+                 scope 15 (inlined drop_in_place::<[A]>) {
-+                     let mut _13: &mut [A];
-+                     scope 16 (inlined std::ptr::drop_glue::<[A]> - shim(Some([A]))) {
-+                         let mut _14: usize;
-+                         let mut _15: *mut A;
-+                         let mut _16: bool;
++                 scope 16 (inlined std::ptr::mut_ptr::<impl *mut [A]>::drop_in_place) {
++                     scope 17 (inlined drop_in_place::<[A]>) {
++                         let mut _13: &mut [A];
++                         scope 18 (inlined std::ptr::drop_glue::<[A]> - shim(Some([A]))) {
++                             let mut _14: usize;
++                             let mut _15: *mut A;
++                             let mut _16: bool;
++                         }
 +                     }
 +                 }
 +             }
 +         }
 +     }
-+     scope 17 (inlined drop_in_place::<Option<B>>) {
++     scope 19 (inlined drop_in_place::<Option<B>>) {
 +         let mut _17: &mut std::option::Option<B>;
-+         scope 18 (inlined std::ptr::drop_glue::<Option<B>> - shim(Some(Option<B>))) {
++         scope 20 (inlined std::ptr::drop_glue::<Option<B>> - shim(Some(Option<B>))) {
 +             let mut _18: isize;
 +             let mut _19: isize;
 +         }
diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
index 9e48cf0..4d4e858 100644
--- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
@@ -2,7 +2,7 @@
 
 | User Type Annotations
 | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
index 9e48cf0..4d4e858 100644
--- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
@@ -2,7 +2,7 @@
 
 | User Type Annotations
 | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/pretty/offload/offload_kernel.device.pp b/tests/pretty/offload/offload_kernel.device.pp
new file mode 100644
index 0000000..9c8e6ed
--- /dev/null
+++ b/tests/pretty/offload/offload_kernel.device.pp
@@ -0,0 +1,26 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ only-nightly
+//@ revisions: host device
+
+//@ pretty-mode:expanded
+//@ pretty-compare-only
+//@[host] pp-exact:offload_kernel.host.pp
+//@[device] pp-exact:offload_kernel.device.pp
+
+//@[device] compile-flags: -Zunstable-options -Zoffload=Device
+
+#![feature(gpu_offload)]
+extern crate std;
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+
+use std::offload::offload_kernel;
+
+#[rustc_offload_kernel]
+#[unsafe(no_mangle)]
+unsafe extern "gpu-kernel" fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+    *c = a[0] + b[0];
+}
+
+fn main() {}
diff --git a/tests/pretty/offload/offload_kernel.host.pp b/tests/pretty/offload/offload_kernel.host.pp
new file mode 100644
index 0000000..cf60ee9
--- /dev/null
+++ b/tests/pretty/offload/offload_kernel.host.pp
@@ -0,0 +1,26 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ only-nightly
+//@ revisions: host device
+
+//@ pretty-mode:expanded
+//@ pretty-compare-only
+//@[host] pp-exact:offload_kernel.host.pp
+//@[device] pp-exact:offload_kernel.device.pp
+
+//@[device] compile-flags: -Zunstable-options -Zoffload=Device
+
+#![feature(gpu_offload)]
+extern crate std;
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+
+use std::offload::offload_kernel;
+
+#[unsafe(no_mangle)]
+#[inline(never)]
+fn foo(_: &[f32], _: &[f32], _: *mut f32) {
+
+    ::core::panicking::panic("not implemented")
+}
+fn main() {}
diff --git a/tests/pretty/offload/offload_kernel.rs b/tests/pretty/offload/offload_kernel.rs
new file mode 100644
index 0000000..1084242
--- /dev/null
+++ b/tests/pretty/offload/offload_kernel.rs
@@ -0,0 +1,20 @@
+//@ only-nightly
+//@ revisions: host device
+
+//@ pretty-mode:expanded
+//@ pretty-compare-only
+//@[host] pp-exact:offload_kernel.host.pp
+//@[device] pp-exact:offload_kernel.device.pp
+
+//@[device] compile-flags: -Zunstable-options -Zoffload=Device
+
+#![feature(gpu_offload)]
+
+use std::offload::offload_kernel;
+
+#[offload_kernel]
+fn foo(a: &[f32], b: &[f32], c: *mut f32) {
+    *c = a[0] + b[0];
+}
+
+fn main() {}
diff --git a/tests/rustdoc-html/async/async-fn-delegation.rs b/tests/rustdoc-html/async/async-fn-delegation.rs
new file mode 100644
index 0000000..7d891ac
--- /dev/null
+++ b/tests/rustdoc-html/async/async-fn-delegation.rs
@@ -0,0 +1,42 @@
+//@ edition: 2021
+
+// Regression test for <https://github.com/rust-lang/rust/issues/157040>.
+//
+// rustdoc used to ICE with "unexpected async fn return type" when cleaning a
+// delegated (`reuse`) async fn: the delegation's HIR signature is unresolved
+// (`InferDelegation`), so its return type cleaned to `_` even though the header
+// is `async`, and unconditionally sugaring that inferred type panicked.
+//
+// We now clean the resolved (ty-side) signature for delegation items, like we
+// already do for inlined items. That both avoids the ICE and renders the real
+// return type and `self` parameter instead of `-> _` / `self: _`.
+//
+// Note: the `<Self>` generic on the free-function variants is a pre-existing
+// quirk of how delegation generics are rendered (plain sync delegation prints it
+// too); it is tracked separately and is not what this test is about.
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+#![crate_name = "async_delegation"]
+
+pub trait Trait {
+    async fn unit(&self) {}
+    async fn nonunit(&self) -> i32 {
+        0
+    }
+}
+
+//@ has async_delegation/fn.unit.html '//pre[@class="rust item-decl"]' 'pub async fn unit<Self>(&self)'
+pub reuse Trait::unit;
+//@ has async_delegation/fn.nonunit.html '//pre[@class="rust item-decl"]' 'pub async fn nonunit<Self>(&self) -> i32'
+pub reuse Trait::nonunit;
+
+pub struct S;
+impl Trait for S {}
+
+//@ has async_delegation/struct.S.html '//*[@class="code-header"]' 'pub async fn unit(self: &S)'
+//@ has async_delegation/struct.S.html '//*[@class="code-header"]' 'pub async fn nonunit(self: &S) -> i32'
+impl S {
+    pub reuse Trait::unit { self }
+    pub reuse Trait::nonunit { self }
+}
diff --git a/tests/rustdoc-html/impl/blanket-impl-trumps-auto-trait-impl.rs b/tests/rustdoc-html/impl/blanket-impl-trumps-auto-trait-impl.rs
new file mode 100644
index 0000000..6444e87
--- /dev/null
+++ b/tests/rustdoc-html/impl/blanket-impl-trumps-auto-trait-impl.rs
@@ -0,0 +1,26 @@
+// The presence of built-in or user-written trait impls disqualifies potential built-in auto trait
+// impls for a type. Here we have a blanket impl of an auto trait which suppresses all hypothetical
+// auto trait impls.
+//
+// Check that we don't claim that there's an auto trait impl & ensure that we show the blanket impl.
+// Erroneously we once used to omit the blanket impl since auto trait impls & blanket impls used to
+// share the same cache and auto trait impls get generated first. Now, they have separate caches.
+//
+// issue: <https://github.com/rust-lang/rust/issues/148980>
+
+#![feature(auto_traits)]
+#![crate_name = "it"]
+
+pub auto trait Marker {}
+
+//@ has 'it/struct.Subject.html'
+#[derive(Clone, Copy)]
+pub struct Subject;
+
+// NOTE: `#synthetic-implementations-list` contains auto trait impls only despite its name.
+//@ !has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' \
+//        'Marker for Subject'
+
+//@ has - '//*[@id="blanket-implementations-list"]//*[@class="impl"]' \
+//        'Marker for Twhere T: Copy'
+impl<T: Copy> Marker for T {}
diff --git a/tests/rustdoc-html/intra-doc/self-impl-in-submodule-84827.rs b/tests/rustdoc-html/intra-doc/self-impl-in-submodule-84827.rs
new file mode 100644
index 0000000..fba5a78
--- /dev/null
+++ b/tests/rustdoc-html/intra-doc/self-impl-in-submodule-84827.rs
@@ -0,0 +1,43 @@
+// https://github.com/rust-lang/rust/issues/84827
+//
+// Regression test for resolving `Self` in intra-doc links inside an `impl`
+// block in a submodule. The `Self` type comes from the impl, not from names
+// in scope, so:
+//   1. It resolves even when the implemented type is not in scope.
+//   2. It resolves to the actual `Self` type, not to a different type with
+//      the same name that happens to be in scope.
+
+#![crate_name = "foo"]
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(unused_imports)]
+
+pub struct Foo {
+    pub foo: i32,
+}
+
+// Case 1: `Foo` is not in scope inside `bar`, but `Self::foo` still resolves
+// to the field on `crate::Foo`.
+pub mod bar {
+    //@ has foo/struct.Foo.html '//a[@href="struct.Foo.html#structfield.foo"]' 'Self::foo'
+    impl crate::Foo {
+        /// Baz the [`Self::foo`].
+        pub fn baz(&self) {}
+    }
+}
+
+// Case 2: A different type named `Foo` is in scope inside `baz`. `Self::foo`
+// must still resolve to `crate::Foo::foo`, not to `crate::other::Foo` (which
+// is a unit struct and has no `foo` field).
+pub mod baz {
+    use crate::other::Foo;
+
+    //@ has foo/struct.Foo.html '//a[@href="struct.Foo.html#structfield.foo"]' 'Self::foo'
+    impl crate::Foo {
+        /// Quux the [`Self::foo`].
+        pub fn quux(&self) {}
+    }
+}
+
+pub mod other {
+    pub struct Foo;
+}
diff --git a/tests/rustdoc-html/macro-expansion/c-var-args.rs b/tests/rustdoc-html/macro-expansion/c-var-args.rs
new file mode 100644
index 0000000..1d42036
--- /dev/null
+++ b/tests/rustdoc-html/macro-expansion/c-var-args.rs
@@ -0,0 +1,19 @@
+// Ensure that C var args (`va_list`) work.
+// Regression test for <https://github.com/rust-lang/rust/issues/156486>.
+
+//@ compile-flags: -Zunstable-options --generate-macro-expansion
+
+#![crate_name = "foo"]
+
+//@ has 'src/foo/c-var-args.rs.html'
+
+macro_rules! print {
+    () => {
+        fn printf(...);
+    };
+}
+
+//@ has - '//*[@class="expansion"]/*[@class="expanded"]' 'fn printf(...);'
+extern "C" {
+    print! {}
+}
diff --git a/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs b/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs
new file mode 100644
index 0000000..33b2fe9
--- /dev/null
+++ b/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs
@@ -0,0 +1,67 @@
+// This test ensures that `cfg`s are correctly propagated for re-export chains
+// where the outermost is a glob re-export.
+
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+//@ has 'foo/index.html'
+//@ count - '//*[@class="item-table"]/dt' 3
+
+//@ has 'foo/index.html'
+//@ has - '//dt/a[@title="struct foo::A"]/../*[@class="stab portability"]' 'Non-bar and non-foo'
+
+//@ has 'foo/struct.A.html'
+//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+//    'Available on non-crate feature bar and non-crate feature foo only.'
+
+mod a {
+    mod inner {
+        pub struct A {}
+    }
+    #[cfg(not(feature = "bar"))]
+    pub use self::inner::A;
+}
+#[cfg(not(feature = "foo"))]
+pub use a::*;
+
+//@ has 'foo/index.html'
+//@ has - '//dt/a[@title="struct foo::B"]/../*[@class="stab portability"]' 'Non-bar and non-baz and non-foo'
+
+//@ has 'foo/struct.B.html'
+//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+//    'Available on non-crate feature bar and non-crate feature baz and non-crate feature foo only.'
+
+mod b {
+    mod inner {
+        mod innermost {
+            pub struct B {}
+        }
+        #[cfg(not(feature = "baz"))]
+        pub use self::innermost::B;
+    }
+    #[cfg(not(feature = "bar"))]
+    pub use self::inner::*;
+}
+#[cfg(not(feature = "foo"))]
+pub use b::*;
+
+//@ has 'foo/index.html'
+//@ has - '//dt/a[@title="struct foo::C"]/../*[@class="stab portability"]' 'Non-bar and non-baz and non-foo'
+
+//@ has 'foo/struct.C.html'
+//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
+//    'Available on non-crate feature bar and non-crate feature baz and non-crate feature foo only.'
+
+mod c {
+    mod inner {
+        mod innermost {
+            #[cfg(not(feature = "baz"))]
+            pub struct C {}
+        }
+        pub use self::innermost::*;
+    }
+    #[cfg(not(feature = "bar"))]
+    pub use self::inner::*;
+}
+#[cfg(not(feature = "foo"))]
+pub use c::*;
diff --git a/tests/rustdoc-json/attrs/derive_helper.rs b/tests/rustdoc-json/attrs/derive_helper.rs
new file mode 100644
index 0000000..278d007
--- /dev/null
+++ b/tests/rustdoc-json/attrs/derive_helper.rs
@@ -0,0 +1,7 @@
+//@ is "$.index[?(@.name=='A')].attrs" '[{"other": "#[default]"}]'
+#[derive(Default)]
+pub enum Test {
+    #[default]
+    A,
+    B,
+}
diff --git a/tests/ui-fulldeps/polymorphic-drop-glue.rs b/tests/ui-fulldeps/polymorphic-drop-glue.rs
new file mode 100644
index 0000000..0617d78
--- /dev/null
+++ b/tests/ui-fulldeps/polymorphic-drop-glue.rs
@@ -0,0 +1,75 @@
+//@ run-pass
+//@ run-flags: --sysroot {{sysroot-base}} --edition=2021
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+//@ ignore-cross-compile
+//@ ignore-remote
+//@ ignore-backends: gcc
+#![feature(rustc_private)]
+
+extern crate rustc_driver;
+extern crate rustc_hir;
+extern crate rustc_interface;
+extern crate rustc_middle;
+extern crate rustc_mir_transform;
+extern crate rustc_span;
+
+use std::process::ExitCode;
+
+use rustc_driver::Compilation;
+use rustc_hir::LangItem;
+use rustc_hir::def::DefKind;
+use rustc_interface::interface::Compiler;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::DUMMY_SP;
+
+fn main() -> ExitCode {
+    rustc_driver::catch_with_exit_code(move || {
+        std::fs::write(
+            "drop_glue_polymorphic_const_generic_input.rs",
+            r#"
+                struct Unit;
+
+                struct ContainsArray<const K: usize> {
+                    array: [Unit; K],
+                    make_non_trivial_drop: Box<u32>,
+                }
+
+                fn foo(_: ContainsArray<42>) {}
+            "#,
+        )
+        .unwrap();
+
+        let mut args: Vec<_> = std::env::args().collect();
+        args.push("--crate-type=lib".to_owned());
+        args.push("drop_glue_polymorphic_const_generic_input.rs".to_owned());
+
+        rustc_driver::run_compiler(&args, &mut CompilerCalls);
+    })
+}
+
+struct CompilerCalls;
+
+impl rustc_driver::Callbacks for CompilerCalls {
+    fn after_analysis<'tcx>(&mut self, _compiler: &Compiler, tcx: TyCtxt<'tcx>) -> Compilation {
+        tcx.sess.dcx().abort_if_errors();
+
+        let drop_glue = tcx.require_lang_item(LangItem::DropGlue, DUMMY_SP);
+        let contains_array = tcx
+            .hir_crate_items(())
+            .free_items()
+            .map(|id| id.owner_id.to_def_id())
+            .find(|&def_id| {
+                tcx.def_kind(def_id) == DefKind::Struct
+                    && tcx.def_path_str(def_id).ends_with("ContainsArray")
+            })
+            .unwrap();
+
+        // Regression test for ICE due to the drop glue code not correctly handling generic
+        // contexts.
+        let ty = tcx.type_of(contains_array).instantiate_identity().skip_norm_wip();
+        let typing_env = ty::TypingEnv::post_analysis(tcx, contains_array);
+        rustc_mir_transform::build_drop_shim(tcx, drop_glue, Some(ty), typing_env);
+
+        Compilation::Stop
+    }
+}
diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr
index d8cc39c..226d880 100644
--- a/tests/ui/abi/pass-indirectly-attr.stderr
+++ b/tests/ui/abi/pass-indirectly-attr.stderr
@@ -123,16 +123,7 @@
                    mode: Cast {
                        pad_i32: false,
                        cast: CastTarget {
-                           prefix: [
-                               None,
-                               None,
-                               None,
-                               None,
-                               None,
-                               None,
-                               None,
-                               None,
-                           ],
+                           prefix: [],
                            rest_offset: None,
                            rest: Uniform {
                                unit: Reg {
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.rs b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.rs
new file mode 100644
index 0000000..d994e26
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.rs
@@ -0,0 +1,31 @@
+// We used to lower the ambiguous `T::f(..)` to `<T as B>::f::{type#0}` after emitting the error.
+// Meaning we picked one of the candidates and proceeded instead of bailing out early.
+// However, sensibly RBV doesn't register any bound vars for ambiguous RTN[^1], so later on when
+// wrapping the predicate (here: WellFormed) into a Binder we would correctly fail bound var
+// validation (in debug mode).
+//
+// We now bail out early and thus prevent nonsensical types from getting leaked to subsequent
+// compiler passes.
+//
+// [^1]: It actually maintains its own bespoke lowering function for type-relative paths that
+//       relatively closely mirrors the one in HIR ty lowering.
+
+// issue: <https://github.com/rust-lang/rust/issues/139387>
+//@ needs-rustc-debug-assertions
+#![feature(return_type_notation)]
+
+trait A {
+    fn f() -> impl Sized;
+}
+
+trait B {
+    fn f<'b>() -> impl Sized;
+}
+
+fn f<T: A + B>()
+where
+    T::f(..):, //~ ERROR ambiguous associated function
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.stderr
new file mode 100644
index 0000000..5b68040
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous-late-bound-vars.stderr
@@ -0,0 +1,26 @@
+error[E0221]: ambiguous associated function `f` in bounds of `T`
+  --> $DIR/path-ambiguous-late-bound-vars.rs:27:5
+   |
+LL |     fn f() -> impl Sized;
+   |     --------------------- ambiguous `f` from `A`
+...
+LL |     fn f<'b>() -> impl Sized;
+   |     ------------------------- ambiguous `f` from `B`
+...
+LL |     T::f(..):,
+   |     ^^^^^^^^ ambiguous associated function `f`
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL -     T::f(..):,
+LL +     <T as B>::f(..):,
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL -     T::f(..):,
+LL +     <T as A>::f(..):,
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0221`.
diff --git a/tests/ui/async-await/async-closures/wrong-suggestion-result.rs b/tests/ui/async-await/async-closures/wrong-suggestion-result.rs
new file mode 100644
index 0000000..cb8747b
--- /dev/null
+++ b/tests/ui/async-await/async-closures/wrong-suggestion-result.rs
@@ -0,0 +1,28 @@
+//@ edition: 2024
+
+async fn once<O, F: AsyncFnOnce() -> O>(f: F) -> O {
+    Ok::<(), ()>(())?;
+    //~^ ERROR: the `?` operator can only be used in an async function that returns
+
+    f()
+    //~^ ERROR mismatched types
+}
+
+async fn fnref<O, F: AsyncFn() -> O>(f: F) -> O {
+    Ok::<(), ()>(())?;
+    //~^ ERROR: the `?` operator can only be used in an async function that returns
+
+    f()
+    //~^ ERROR mismatched types
+}
+
+
+async fn fnmut<O, F: AsyncFnMut() -> O>(f: F) -> O {
+    Ok::<(), ()>(())?;
+    //~^ ERROR: the `?` operator can only be used in an async function that returns
+
+    f()
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-closures/wrong-suggestion-result.stderr b/tests/ui/async-await/async-closures/wrong-suggestion-result.stderr
new file mode 100644
index 0000000..7070205
--- /dev/null
+++ b/tests/ui/async-await/async-closures/wrong-suggestion-result.stderr
@@ -0,0 +1,94 @@
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/wrong-suggestion-result.rs:4:21
+   |
+LL |   async fn once<O, F: AsyncFnOnce() -> O>(f: F) -> O {
+   |  ____________________________________________________-
+LL | |     Ok::<(), ()>(())?;
+   | |                     ^ cannot use the `?` operator in an async function that returns `O`
+...  |
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+help: consider restricting type parameter `O` with unstable trait `FromResidual`
+   |
+LL | async fn once<O: std::ops::FromResidual<std::result::Result<std::convert::Infallible, ()>>, F: AsyncFnOnce() -> O>(f: F) -> O {
+   |                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-suggestion-result.rs:7:5
+   |
+LL | async fn once<O, F: AsyncFnOnce() -> O>(f: F) -> O {
+   |               - expected this type parameter     - expected `O` because of return type
+...
+LL |     f()
+   |     ^^^ expected type parameter `O`, found associated type
+   |
+   = note: expected type parameter `O`
+             found associated type `<F as AsyncFnOnce<()>>::CallOnceFuture`
+   = help: you may have forgotten to await an async function
+   = note: it is currently not possible to add bounds constraining the future returned from an async function (`CallOnceFuture`)
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/wrong-suggestion-result.rs:12:21
+   |
+LL |   async fn fnref<O, F: AsyncFn() -> O>(f: F) -> O {
+   |  _________________________________________________-
+LL | |     Ok::<(), ()>(())?;
+   | |                     ^ cannot use the `?` operator in an async function that returns `O`
+...  |
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+help: consider restricting type parameter `O` with unstable trait `FromResidual`
+   |
+LL | async fn fnref<O: std::ops::FromResidual<std::result::Result<std::convert::Infallible, ()>>, F: AsyncFn() -> O>(f: F) -> O {
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-suggestion-result.rs:15:5
+   |
+LL | async fn fnref<O, F: AsyncFn() -> O>(f: F) -> O {
+   |                - expected this type parameter - expected `O` because of return type
+...
+LL |     f()
+   |     ^^^ expected type parameter `O`, found associated type
+   |
+   = note: expected type parameter `O`
+             found associated type `<F as AsyncFnMut<()>>::CallRefFuture<'_>`
+   = help: you may have forgotten to await an async function
+   = note: it is currently not possible to add bounds constraining the future returned from an async function (`CallRefFuture`)
+
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/wrong-suggestion-result.rs:21:21
+   |
+LL |   async fn fnmut<O, F: AsyncFnMut() -> O>(f: F) -> O {
+   |  ____________________________________________________-
+LL | |     Ok::<(), ()>(())?;
+   | |                     ^ cannot use the `?` operator in an async function that returns `O`
+...  |
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+help: consider restricting type parameter `O` with unstable trait `FromResidual`
+   |
+LL | async fn fnmut<O: std::ops::FromResidual<std::result::Result<std::convert::Infallible, ()>>, F: AsyncFnMut() -> O>(f: F) -> O {
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-suggestion-result.rs:24:5
+   |
+LL | async fn fnmut<O, F: AsyncFnMut() -> O>(f: F) -> O {
+   |                - expected this type parameter    - expected `O` because of return type
+...
+LL |     f()
+   |     ^^^ expected type parameter `O`, found associated type
+   |
+   = note: expected type parameter `O`
+             found associated type `<F as AsyncFnMut<()>>::CallRefFuture<'_>`
+   = help: you may have forgotten to await an async function
+   = note: it is currently not possible to add bounds constraining the future returned from an async function (`CallRefFuture`)
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-fn/closure-arg-type-mismatch.rs b/tests/ui/async-await/async-fn/closure-arg-type-mismatch.rs
new file mode 100644
index 0000000..be1ad20
--- /dev/null
+++ b/tests/ui/async-await/async-fn/closure-arg-type-mismatch.rs
@@ -0,0 +1,9 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/155636>
+//@ edition:2021
+
+fn foo(_: impl AsyncFn(&mut i32)) {}
+
+fn main() {
+    foo(|_: i32| async {});
+    //~^ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/async-await/async-fn/closure-arg-type-mismatch.stderr b/tests/ui/async-await/async-fn/closure-arg-type-mismatch.stderr
new file mode 100644
index 0000000..a3b47bb
--- /dev/null
+++ b/tests/ui/async-await/async-fn/closure-arg-type-mismatch.stderr
@@ -0,0 +1,24 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:7:5
+   |
+LL |     foo(|_: i32| async {});
+   |     ^^^^--------^^^^^^^^^^
+   |     |   |
+   |     |   found signature defined here
+   |     expected due to this
+   |
+   = note: expected closure signature `for<'a> fn(&'a mut _) -> _`
+              found closure signature `fn(_) -> _`
+note: required by a bound in `foo`
+  --> $DIR/closure-arg-type-mismatch.rs:4:16
+   |
+LL | fn foo(_: impl AsyncFn(&mut i32)) {}
+   |                ^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+help: consider adjusting the signature so it borrows its argument
+   |
+LL |     foo(|_: &mut i32| async {});
+   |             ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/tests/ui/attributes/arg-error-issue-121425.rs b/tests/ui/attributes/arg-error-issue-121425.rs
index c15b276..1ff36c6 100644
--- a/tests/ui/attributes/arg-error-issue-121425.rs
+++ b/tests/ui/attributes/arg-error-issue-121425.rs
@@ -2,28 +2,28 @@
 
 const N: usize = 8;
 #[repr(align(N))]
-//~^ ERROR: incorrect `repr(align)` attribute format
+//~^ ERROR: malformed `repr` attribute input
 struct T;
 
 #[repr(align('a'))]
-//~^ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer [E0589]
+//~^ ERROR: not an unsuffixed integer [E0589]
 struct H;
 
 #[repr(align("str"))]
-//~^ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer [E0589]
+//~^ ERROR: not an unsuffixed integer [E0589]
 struct L;
 
 #[repr(align())]
-//~^ ERROR: attribute format: `align` takes exactly one argument in parentheses
+//~^ ERROR: malformed `repr` attribute input
 struct X;
 
 const P: usize = 8;
 #[repr(packed(P))]
-//~^ ERROR: attribute format: `packed` expects a literal integer as argument
+//~^ ERROR: malformed `repr` attribute input
 struct A;
 
 #[repr(packed())]
-//~^ ERROR: attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+//~^ ERROR: malformed `repr` attribute input
 struct B;
 
 #[repr(packed)]
diff --git a/tests/ui/attributes/arg-error-issue-121425.stderr b/tests/ui/attributes/arg-error-issue-121425.stderr
index 1beb99b..7816ce4 100644
--- a/tests/ui/attributes/arg-error-issue-121425.stderr
+++ b/tests/ui/attributes/arg-error-issue-121425.stderr
@@ -1,40 +1,56 @@
-error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument
-  --> $DIR/arg-error-issue-121425.rs:4:14
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/arg-error-issue-121425.rs:4:1
    |
 LL | #[repr(align(N))]
-   |              ^
+   | ^^^^^^^^^^^^^-^^^
+   |              |
+   |              expected an integer literal here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+error[E0589]: invalid alignment value: not an unsuffixed integer
   --> $DIR/arg-error-issue-121425.rs:8:14
    |
 LL | #[repr(align('a'))]
    |              ^^^
 
-error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+error[E0589]: invalid alignment value: not an unsuffixed integer
   --> $DIR/arg-error-issue-121425.rs:12:14
    |
 LL | #[repr(align("str"))]
    |              ^^^^^
 
-error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
-  --> $DIR/arg-error-issue-121425.rs:16:8
+error[E0805]: malformed `repr` attribute input
+  --> $DIR/arg-error-issue-121425.rs:16:1
    |
 LL | #[repr(align())]
-   |        ^^^^^^^
+   | ^^^^^^^^^^^^--^^
+   |             |
+   |             expected an argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument
-  --> $DIR/arg-error-issue-121425.rs:21:15
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/arg-error-issue-121425.rs:21:1
    |
 LL | #[repr(packed(P))]
-   |               ^
+   | ^^^^^^^^^^^^^^-^^^
+   |               |
+   |               expected an integer literal here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
-  --> $DIR/arg-error-issue-121425.rs:25:8
+error[E0805]: malformed `repr` attribute input
+  --> $DIR/arg-error-issue-121425.rs:25:1
    |
 LL | #[repr(packed())]
-   |        ^^^^^^^^
+   | ^^^^^^^^^^^^^--^^
+   |              |
+   |              expected an argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0552, E0589, E0693.
-For more information about an error, try `rustc --explain E0552`.
+Some errors have detailed explanations: E0539, E0589, E0805.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/attributes/args-checked.rs b/tests/ui/attributes/args-checked.rs
new file mode 100644
index 0000000..18369ac
--- /dev/null
+++ b/tests/ui/attributes/args-checked.rs
@@ -0,0 +1,73 @@
+#![feature(rustc_attrs)]
+#![feature(optimize_attribute)]
+#![feature(coverage_attribute)]
+#![feature(custom_test_frameworks)]
+#![allow(unused_attributes)]
+
+#![test_runner(x = 5)]
+//~^ ERROR malformed
+#![test_runner(x(x,y,z))]
+//~^ ERROR malformed
+
+#[inline(always = 5)]
+//~^ ERROR malformed
+#[inline(always(x, y, z))]
+//~^ ERROR malformed
+#[instruction_set(arm::a32 = 5)]
+//~^ ERROR malformed
+#[instruction_set(arm::a32(x, y, z))]
+//~^ ERROR malformed
+#[optimize(size = 5)]
+//~^ ERROR malformed
+#[optimize(size(x, y, z))]
+//~^ ERROR malformed
+//~| ERROR multiple `optimize` attributes
+#[coverage(off = 5)]
+//~^ ERROR malformed
+#[coverage(off(x, y, z))]
+//~^ ERROR malformed
+#[rustc_abi(debug = 5)]
+//~^ ERROR malformed
+#[rustc_abi(debug(x, y, z))]
+//~^ ERROR malformed
+fn main() {
+
+}
+
+#[macro_export(local_inner_macros = 5)]
+//~^ ERROR valid forms for the attribute are
+//~| WARN previously accepted
+#[macro_export(local_inner_macros(x, y, z))]
+//~^ ERROR valid forms for the attribute are
+//~| WARN previously accepted
+macro_rules! m {
+    () => {};
+}
+
+#[rustc_allow_const_fn_unstable(x = 5)]
+//~^ ERROR `rustc_allow_const_fn_unstable` expects feature names
+#[rustc_allow_const_fn_unstable(x(x, y, z))]
+//~^ ERROR `rustc_allow_const_fn_unstable` expects feature names
+const fn g() {}
+
+#[used(always = 5)]
+//~^ ERROR malformed
+#[used(always(x, y, z))]
+//~^ ERROR malformed
+static H: u64 = 5;
+
+#[rustc_must_implement_one_of(eq = 5, neq)]
+//~^ ERROR malformed
+#[rustc_must_implement_one_of(eq(x, y, z), neq)]
+//~^ ERROR malformed
+trait T {
+
+}
+
+#[rustc_dump_layout(debug = 5)]
+//~^ ERROR malformed
+#[rustc_dump_layout(debug(x, y, z))]
+//~^ ERROR malformed
+enum E {
+
+}
diff --git a/tests/ui/attributes/args-checked.stderr b/tests/ui/attributes/args-checked.stderr
new file mode 100644
index 0000000..277dd67
--- /dev/null
+++ b/tests/ui/attributes/args-checked.stderr
@@ -0,0 +1,361 @@
+error[E0565]: malformed `test_runner` attribute input
+  --> $DIR/args-checked.rs:7:1
+   |
+LL | #![test_runner(x = 5)]
+   | ^^^^^^^^^^^^^^^-----^^
+   |                |
+   |                didn't expect a literal here
+   |
+help: must be of the form
+   |
+LL - #![test_runner(x = 5)]
+LL + #![test_runner(path)]
+   |
+
+error[E0565]: malformed `test_runner` attribute input
+  --> $DIR/args-checked.rs:9:1
+   |
+LL | #![test_runner(x(x,y,z))]
+   | ^^^^^^^^^^^^^^^--------^^
+   |                |
+   |                didn't expect a literal here
+   |
+help: must be of the form
+   |
+LL - #![test_runner(x(x,y,z))]
+LL + #![test_runner(path)]
+   |
+
+error[E0539]: malformed `inline` attribute input
+  --> $DIR/args-checked.rs:12:1
+   |
+LL | #[inline(always = 5)]
+   | ^^^^^^^^^----------^^
+   |          |
+   |          valid arguments are `always` or `never`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[inline(always = 5)]
+LL + #[inline(always)]
+   |
+LL - #[inline(always = 5)]
+LL + #[inline(never)]
+   |
+LL - #[inline(always = 5)]
+LL + #[inline]
+   |
+
+error[E0539]: malformed `inline` attribute input
+  --> $DIR/args-checked.rs:14:1
+   |
+LL | #[inline(always(x, y, z))]
+   | ^^^^^^^^^---------------^^
+   |          |
+   |          valid arguments are `always` or `never`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[inline(always(x, y, z))]
+LL + #[inline(always)]
+   |
+LL - #[inline(always(x, y, z))]
+LL + #[inline(never)]
+   |
+LL - #[inline(always(x, y, z))]
+LL + #[inline]
+   |
+
+error[E0539]: malformed `instruction_set` attribute input
+  --> $DIR/args-checked.rs:16:1
+   |
+LL | #[instruction_set(arm::a32 = 5)]
+   | ^^^^^^^^^^^^^^^^^^------------^^
+   |                   |
+   |                   valid arguments are `arm::a32` or `arm::t32`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
+help: must be of the form
+   |
+LL - #[instruction_set(arm::a32 = 5)]
+LL + #[instruction_set(set)]
+   |
+
+error[E0539]: malformed `instruction_set` attribute input
+  --> $DIR/args-checked.rs:18:1
+   |
+LL | #[instruction_set(arm::a32(x, y, z))]
+   | ^^^^^^^^^^^^^^^^^^-----------------^^
+   |                   |
+   |                   valid arguments are `arm::a32` or `arm::t32`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
+help: must be of the form
+   |
+LL - #[instruction_set(arm::a32(x, y, z))]
+LL + #[instruction_set(set)]
+   |
+
+error[E0539]: malformed `optimize` attribute input
+  --> $DIR/args-checked.rs:20:1
+   |
+LL | #[optimize(size = 5)]
+   | ^^^^^^^^^^^--------^^
+   |            |
+   |            valid arguments are `size`, `speed` or `none`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[optimize(size = 5)]
+LL + #[optimize(none)]
+   |
+LL - #[optimize(size = 5)]
+LL + #[optimize(size)]
+   |
+LL - #[optimize(size = 5)]
+LL + #[optimize(speed)]
+   |
+
+error[E0539]: malformed `optimize` attribute input
+  --> $DIR/args-checked.rs:22:1
+   |
+LL | #[optimize(size(x, y, z))]
+   | ^^^^^^^^^^^-------------^^
+   |            |
+   |            valid arguments are `size`, `speed` or `none`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[optimize(size(x, y, z))]
+LL + #[optimize(none)]
+   |
+LL - #[optimize(size(x, y, z))]
+LL + #[optimize(size)]
+   |
+LL - #[optimize(size(x, y, z))]
+LL + #[optimize(speed)]
+   |
+
+error: multiple `optimize` attributes
+  --> $DIR/args-checked.rs:22:1
+   |
+LL | #[optimize(size(x, y, z))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/args-checked.rs:20:1
+   |
+LL | #[optimize(size = 5)]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/args-checked.rs:25:1
+   |
+LL | #[coverage(off = 5)]
+   | ^^^^^^^^^^^-------^^
+   |            |
+   |            valid arguments are `on` or `off`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[coverage(off = 5)]
+LL + #[coverage(off)]
+   |
+LL - #[coverage(off = 5)]
+LL + #[coverage(on)]
+   |
+
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/args-checked.rs:27:1
+   |
+LL | #[coverage(off(x, y, z))]
+   | ^^^^^^^^^^^------------^^
+   |            |
+   |            valid arguments are `on` or `off`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[coverage(off(x, y, z))]
+LL + #[coverage(off)]
+   |
+LL - #[coverage(off(x, y, z))]
+LL + #[coverage(on)]
+   |
+
+error[E0539]: malformed `rustc_abi` attribute input
+  --> $DIR/args-checked.rs:29:1
+   |
+LL | #[rustc_abi(debug = 5)]
+   | ^^^^^^^^^^^-----------^
+   |            |
+   |            valid arguments are `assert_eq` or `debug`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[rustc_abi(debug = 5)]
+LL + #[rustc_abi(assert_eq)]
+   |
+LL - #[rustc_abi(debug = 5)]
+LL + #[rustc_abi(debug)]
+   |
+
+error[E0539]: malformed `rustc_abi` attribute input
+  --> $DIR/args-checked.rs:31:1
+   |
+LL | #[rustc_abi(debug(x, y, z))]
+   | ^^^^^^^^^^^----------------^
+   |            |
+   |            valid arguments are `assert_eq` or `debug`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[rustc_abi(debug(x, y, z))]
+LL + #[rustc_abi(assert_eq)]
+   |
+LL - #[rustc_abi(debug(x, y, z))]
+LL + #[rustc_abi(debug)]
+   |
+
+error: `rustc_allow_const_fn_unstable` expects feature names
+  --> $DIR/args-checked.rs:47:33
+   |
+LL | #[rustc_allow_const_fn_unstable(x = 5)]
+   |                                 ^^^^^
+
+error: `rustc_allow_const_fn_unstable` expects feature names
+  --> $DIR/args-checked.rs:49:33
+   |
+LL | #[rustc_allow_const_fn_unstable(x(x, y, z))]
+   |                                 ^^^^^^^^^^
+
+error[E0539]: malformed `used` attribute input
+  --> $DIR/args-checked.rs:53:1
+   |
+LL | #[used(always = 5)]
+   | ^^^^^^^----------^^
+   |        |
+   |        valid arguments are `compiler` or `linker`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[used(always = 5)]
+LL + #[used(compiler)]
+   |
+LL - #[used(always = 5)]
+LL + #[used(linker)]
+   |
+LL - #[used(always = 5)]
+LL + #[used]
+   |
+
+error[E0539]: malformed `used` attribute input
+  --> $DIR/args-checked.rs:55:1
+   |
+LL | #[used(always(x, y, z))]
+   | ^^^^^^^---------------^^
+   |        |
+   |        valid arguments are `compiler` or `linker`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[used(always(x, y, z))]
+LL + #[used(compiler)]
+   |
+LL - #[used(always(x, y, z))]
+LL + #[used(linker)]
+   |
+LL - #[used(always(x, y, z))]
+LL + #[used]
+   |
+
+error[E0565]: malformed `rustc_must_implement_one_of` attribute input
+  --> $DIR/args-checked.rs:59:1
+   |
+LL | #[rustc_must_implement_one_of(eq = 5, neq)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^^^
+   |                               |
+   |                               expected a valid identifier here
+   |
+help: must be of the form
+   |
+LL - #[rustc_must_implement_one_of(eq = 5, neq)]
+LL + #[rustc_must_implement_one_of(function1, function2, ...)]
+   |
+
+error[E0565]: malformed `rustc_must_implement_one_of` attribute input
+  --> $DIR/args-checked.rs:61:1
+   |
+LL | #[rustc_must_implement_one_of(eq(x, y, z), neq)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^
+   |                               |
+   |                               expected a valid identifier here
+   |
+help: must be of the form
+   |
+LL - #[rustc_must_implement_one_of(eq(x, y, z), neq)]
+LL + #[rustc_must_implement_one_of(function1, function2, ...)]
+   |
+
+error[E0565]: malformed `rustc_dump_layout` attribute input
+  --> $DIR/args-checked.rs:67:1
+   |
+LL | #[rustc_dump_layout(debug = 5)]
+   | ^^^^^^^^^^^^^^^^^^^^---------^^
+   |                     |
+   |                     didn't expect a literal here
+
+error[E0565]: malformed `rustc_dump_layout` attribute input
+  --> $DIR/args-checked.rs:69:1
+   |
+LL | #[rustc_dump_layout(debug(x, y, z))]
+   | ^^^^^^^^^^^^^^^^^^^^--------------^^
+   |                     |
+   |                     didn't expect a literal here
+
+error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
+  --> $DIR/args-checked.rs:37:1
+   |
+LL | #[macro_export(local_inner_macros = 5)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(invalid_macro_export_arguments)]` (part of `#[deny(future_incompatible)]`) on by default
+
+error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
+  --> $DIR/args-checked.rs:40:1
+   |
+LL | #[macro_export(local_inner_macros(x, y, z))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+error: aborting due to 23 previous errors
+
+Some errors have detailed explanations: E0539, E0565.
+For more information about an error, try `rustc --explain E0539`.
+Future incompatibility report: Future breakage diagnostic:
+error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
+  --> $DIR/args-checked.rs:37:1
+   |
+LL | #[macro_export(local_inner_macros = 5)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(invalid_macro_export_arguments)]` (part of `#[deny(future_incompatible)]`) on by default
+
+Future breakage diagnostic:
+error: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
+  --> $DIR/args-checked.rs:40:1
+   |
+LL | #[macro_export(local_inner_macros(x, y, z))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(invalid_macro_export_arguments)]` (part of `#[deny(future_incompatible)]`) on by default
+
diff --git a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs
index c29edbe..be9fd7d 100644
--- a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs
+++ b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs
@@ -16,13 +16,13 @@ fn main() {
 
     #[repr(nothing)]
     let _x = 0;
-    //~^^ ERROR E0552
+    //~^^ ERROR malformed `repr` attribute input
 
     #[repr(something_not_real)]
     loop {
         ()
     };
-    //~^^^^ ERROR E0552
+    //~^^^^ ERROR malformed `repr` attribute input
 
     #[repr]
     let _y = "123";
diff --git a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr
index 49f67bf..f9f17b1 100644
--- a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr
+++ b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr
@@ -35,23 +35,25 @@
    |
    = help: `#[inline]` can only be applied to functions
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/attribute-on-wrong-item-inline-repr.rs:17:12
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/attribute-on-wrong-item-inline-repr.rs:17:5
    |
 LL |     #[repr(nothing)]
-   |            ^^^^^^^
+   |     ^^^^^^^-------^^
+   |            |
+   |            valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/attribute-on-wrong-item-inline-repr.rs:21:12
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/attribute-on-wrong-item-inline-repr.rs:21:5
    |
 LL |     #[repr(something_not_real)]
-   |            ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^------------------^^
+   |            |
+   |            valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error[E0539]: malformed `repr` attribute input
   --> $DIR/attribute-on-wrong-item-inline-repr.rs:27:5
@@ -100,5 +102,4 @@
 
 error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0539, E0552.
-For more information about an error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/attributes/invalid-macro-use.stderr b/tests/ui/attributes/invalid-macro-use.stderr
index fe235ab..f02c77b 100644
--- a/tests/ui/attributes/invalid-macro-use.stderr
+++ b/tests/ui/attributes/invalid-macro-use.stderr
@@ -28,7 +28,7 @@
 LL + #[macro_use]
    |
 
-error[E0539]: malformed `macro_use` attribute input
+error[E0565]: malformed `macro_use` attribute input
   --> $DIR/invalid-macro-use.rs:10:1
    |
 LL | #[macro_use(5)]
@@ -82,7 +82,7 @@
 LL + #[macro_use]
    |
 
-error[E0539]: malformed `macro_use` attribute input
+error[E0565]: malformed `macro_use` attribute input
   --> $DIR/invalid-macro-use.rs:28:1
    |
 LL | #[macro_use(a::b)]
diff --git a/tests/ui/attributes/invalid-reprs.rs b/tests/ui/attributes/invalid-reprs.rs
index 95ed14b..f15d721 100644
--- a/tests/ui/attributes/invalid-reprs.rs
+++ b/tests/ui/attributes/invalid-reprs.rs
@@ -1,6 +1,6 @@
 fn main() {
     let y = #[repr(uwu(4))]
     //~^ ERROR attributes on expressions are experimental
-    //~| ERROR unrecognized representation hint
+    //~| ERROR malformed `repr` attribute input
     (&id(5)); //~ ERROR: cannot find function `id` in this scope
 }
diff --git a/tests/ui/attributes/invalid-reprs.stderr b/tests/ui/attributes/invalid-reprs.stderr
index 72aaff9..3cc52f5 100644
--- a/tests/ui/attributes/invalid-reprs.stderr
+++ b/tests/ui/attributes/invalid-reprs.stderr
@@ -19,16 +19,17 @@
 LL + use std::process::id;
    |
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid-reprs.rs:2:20
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid-reprs.rs:2:13
    |
 LL |     let y = #[repr(uwu(4))]
-   |                    ^^^^^^
+   |             ^^^^^^^------^^
+   |                    |
+   |                    valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0425, E0552, E0658.
+Some errors have detailed explanations: E0425, E0539, E0658.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/attributes/malformed-reprs.rs b/tests/ui/attributes/malformed-reprs.rs
index 4f99239..9827d10 100644
--- a/tests/ui/attributes/malformed-reprs.rs
+++ b/tests/ui/attributes/malformed-reprs.rs
@@ -7,7 +7,7 @@
 
 // This is a regression test for https://github.com/rust-lang/rust/issues/143479
 #[repr(align(0))]
-//~^ ERROR invalid `repr(align)` attribute: not a power of two
+//~^ ERROR not a power of two
 //~| ERROR unsupported representation for zero-variant enum [E0084]
 enum Foo {}
 
diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr
index 6e77c6e..6a5f649 100644
--- a/tests/ui/attributes/malformed-reprs.stderr
+++ b/tests/ui/attributes/malformed-reprs.stderr
@@ -21,7 +21,7 @@
 LL + #[repr]
    |
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
+error[E0589]: invalid alignment value: not a power of two
   --> $DIR/malformed-reprs.rs:9:14
    |
 LL | #[repr(align(0))]
diff --git a/tests/ui/attributes/repr-align-in-trait-issue-132391.rs b/tests/ui/attributes/repr-align-in-trait-issue-132391.rs
index b3b79e9..7b9f6c1 100644
--- a/tests/ui/attributes/repr-align-in-trait-issue-132391.rs
+++ b/tests/ui/attributes/repr-align-in-trait-issue-132391.rs
@@ -1,5 +1,5 @@
 trait MyTrait {
-    #[repr(align)] //~ ERROR invalid `repr(align)` attribute: `align` needs an argument
+    #[repr(align)] //~ ERROR malformed `repr` attribute input
     fn myfun();
 }
 
diff --git a/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr b/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr
index 4208b01..a8f5d3b 100644
--- a/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr
+++ b/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr
@@ -1,9 +1,13 @@
-error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
-  --> $DIR/repr-align-in-trait-issue-132391.rs:2:12
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/repr-align-in-trait-issue-132391.rs:2:5
    |
 LL |     #[repr(align)]
-   |            ^^^^^ help: supply an argument here: `align(...)`
+   |     ^^^^^^^-----^^
+   |            |
+   |            expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0589`.
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/issues/issue-17746.rs b/tests/ui/autoref-autoderef/reborrow-mut-self-to-ref-self-method.rs
similarity index 76%
rename from tests/ui/issues/issue-17746.rs
rename to tests/ui/autoref-autoderef/reborrow-mut-self-to-ref-self-method.rs
index 231fcb4..139208c 100644
--- a/tests/ui/issues/issue-17746.rs
+++ b/tests/ui/autoref-autoderef/reborrow-mut-self-to-ref-self-method.rs
@@ -1,6 +1,7 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/17746>.
+
 //@ check-pass
 #![allow(dead_code)]
-// Regression test for #17746
 
 fn main() {}
 
diff --git a/tests/ui/borrowck/borrowck-deref-pattern-assignment.rs b/tests/ui/borrowck/borrowck-deref-pattern-assignment.rs
new file mode 100644
index 0000000..9d20f8a
--- /dev/null
+++ b/tests/ui/borrowck/borrowck-deref-pattern-assignment.rs
@@ -0,0 +1,47 @@
+//! regression test for <https://github.com/rust-lang/rust/issues/148467>
+//! Ensure the diagnostic suggests `&(mut x)` (parenthesized) instead of `&mut x`.
+
+fn for_loop() {
+    let nums: &[u32] = &[1, 2, 3];
+    for &num in nums {
+        num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
+        println!("{num}");
+    }
+}
+
+fn let_deref(num_ref: &u32) -> u32 {
+    let &num = num_ref;
+
+    num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
+
+    num
+}
+
+fn deref_inside_pattern(option_num_ref: Option<&u32>) {
+    if let Some(&num) = option_num_ref {
+        num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
+
+        println!("{num}");
+    }
+}
+
+/// Insides of deref pattern do not need additional parens
+fn inside_of_deref(num_option_ref: &Option<u32>) {
+    if let &Some(num) = num_option_ref {
+        num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
+
+        println!("{num}");
+    }
+}
+
+/// &mut deref pattern does not need additional parens
+fn let_mut_deref(num_mut_ref: &mut u32) -> u32 {
+    let &mut num = num_mut_ref;
+
+    num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
+
+    num
+}
+
+
+fn main() {}
diff --git a/tests/ui/borrowck/borrowck-deref-pattern-assignment.stderr b/tests/ui/borrowck/borrowck-deref-pattern-assignment.stderr
new file mode 100644
index 0000000..65524e4
--- /dev/null
+++ b/tests/ui/borrowck/borrowck-deref-pattern-assignment.stderr
@@ -0,0 +1,89 @@
+error[E0384]: cannot assign twice to immutable variable `num`
+  --> $DIR/borrowck-deref-pattern-assignment.rs:7:9
+   |
+LL |     for &num in nums {
+   |          --- first assignment to `num`
+LL |         num *= 2;
+   |         ^^^^^^^^ cannot assign twice to immutable variable
+   |
+help: consider making this binding mutable
+   |
+LL -     for &num in nums {
+LL +     for &(mut num) in nums {
+   |
+
+error[E0384]: cannot assign twice to immutable variable `num`
+  --> $DIR/borrowck-deref-pattern-assignment.rs:15:5
+   |
+LL |     let &num = num_ref;
+   |          --- first assignment to `num`
+LL |
+LL |     num *= 2;
+   |     ^^^^^^^^ cannot assign twice to immutable variable
+   |
+help: consider making this binding mutable
+   |
+LL -     let &num = num_ref;
+LL +     let &(mut num) = num_ref;
+   |
+help: to modify the original value, take a borrow instead
+   |
+LL |     let &ref mut num = num_ref;
+   |          +++++++
+
+error[E0384]: cannot assign twice to immutable variable `num`
+  --> $DIR/borrowck-deref-pattern-assignment.rs:22:9
+   |
+LL |     if let Some(&num) = option_num_ref {
+   |                  --- first assignment to `num`
+LL |         num *= 2;
+   |         ^^^^^^^^ cannot assign twice to immutable variable
+   |
+help: consider making this binding mutable
+   |
+LL -     if let Some(&num) = option_num_ref {
+LL +     if let Some(&(mut num)) = option_num_ref {
+   |
+help: to modify the original value, take a borrow instead
+   |
+LL |     if let Some(&ref mut num) = option_num_ref {
+   |                  +++++++
+
+error[E0384]: cannot assign twice to immutable variable `num`
+  --> $DIR/borrowck-deref-pattern-assignment.rs:31:9
+   |
+LL |     if let &Some(num) = num_option_ref {
+   |                  --- first assignment to `num`
+LL |         num *= 2;
+   |         ^^^^^^^^ cannot assign twice to immutable variable
+   |
+help: consider making this binding mutable
+   |
+LL |     if let &Some(mut num) = num_option_ref {
+   |                  +++
+help: to modify the original value, take a borrow instead
+   |
+LL |     if let &Some(ref mut num) = num_option_ref {
+   |                  +++++++
+
+error[E0384]: cannot assign twice to immutable variable `num`
+  --> $DIR/borrowck-deref-pattern-assignment.rs:41:5
+   |
+LL |     let &mut num = num_mut_ref;
+   |              --- first assignment to `num`
+LL |
+LL |     num *= 2;
+   |     ^^^^^^^^ cannot assign twice to immutable variable
+   |
+help: consider making this binding mutable
+   |
+LL |     let &mut mut num = num_mut_ref;
+   |              +++
+help: to modify the original value, take a borrow instead
+   |
+LL |     let &mut ref mut num = num_mut_ref;
+   |              +++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs
deleted file mode 100644
index fc4f1e4..0000000
--- a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//! regression test for <https://github.com/rust-lang/rust/issues/148467>
-//! Ensure the diagnostic suggests `for &(mut x) ...` (parenthesized) instead of `&mut x`.
-
-fn main() {
-    let nums: &[u32] = &[1, 2, 3];
-    for &num in nums {
-        num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
-        println!("{num}");
-    }
-}
diff --git a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr b/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr
deleted file mode 100644
index 3c4d0e9..0000000
--- a/tests/ui/borrowck/borrowck-for-loop-deref-pattern-assignment.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0384]: cannot assign twice to immutable variable `num`
-  --> $DIR/borrowck-for-loop-deref-pattern-assignment.rs:7:9
-   |
-LL |     for &num in nums {
-   |          --- first assignment to `num`
-LL |         num *= 2;
-   |         ^^^^^^^^ cannot assign twice to immutable variable
-   |
-help: consider making this binding mutable
-   |
-LL -     for &num in nums {
-LL +     for &(mut num) in nums {
-   |
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0384`.
diff --git a/tests/ui/cfg/cfg-path-error.stderr b/tests/ui/cfg/cfg-path-error.stderr
index 6f4d6b6..8f5ff3f 100644
--- a/tests/ui/cfg/cfg-path-error.stderr
+++ b/tests/ui/cfg/cfg-path-error.stderr
@@ -1,4 +1,4 @@
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-path-error.rs:6:1
    |
 LL | #[cfg(any(foo, foo::bar))]
@@ -13,7 +13,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-path-error.rs:12:1
    |
 LL | #[cfg(any(foo::bar, foo))]
@@ -28,7 +28,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-path-error.rs:18:1
    |
 LL | #[cfg(all(foo, foo::bar))]
@@ -43,7 +43,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-path-error.rs:24:1
    |
 LL | #[cfg(all(foo::bar, foo))]
@@ -60,4 +60,4 @@
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr
index a228e47..7fb4fa4 100644
--- a/tests/ui/cfg/cfg-target-compact-errors.stderr
+++ b/tests/ui/cfg/cfg-target-compact-errors.stderr
@@ -1,4 +1,4 @@
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-target-compact-errors.rs:5:1
    |
 LL | #[cfg(target(o::o))]
@@ -73,7 +73,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-target-compact-errors.rs:32:1
    |
 LL | #[cfg(target(clippy::os = "linux"))]
@@ -90,4 +90,5 @@
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0539`.
+Some errors have detailed explanations: E0539, E0565.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/cfg/path-kw-as-cfg-pred.stderr b/tests/ui/cfg/path-kw-as-cfg-pred.stderr
index 1728943..0fd9d1b 100644
--- a/tests/ui/cfg/path-kw-as-cfg-pred.stderr
+++ b/tests/ui/cfg/path-kw-as-cfg-pred.stderr
@@ -118,7 +118,7 @@
 LL | #[cfg_attr(r#_, cfg(r#_))]
    |                     ^^^
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:20:1
    |
 LL | #[cfg(crate)]
@@ -133,7 +133,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:22:1
    |
 LL | #[cfg(super)]
@@ -148,7 +148,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:24:1
    |
 LL | #[cfg(self)]
@@ -163,7 +163,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:26:1
    |
 LL | #[cfg(Self)]
@@ -178,7 +178,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:28:1
    |
 LL | #[cfg_attr(crate, path = "foo")]
@@ -193,7 +193,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:30:1
    |
 LL | #[cfg_attr(super, path = "foo")]
@@ -208,7 +208,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:32:1
    |
 LL | #[cfg_attr(self, path = "foo")]
@@ -223,7 +223,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:34:1
    |
 LL | #[cfg_attr(Self, path = "foo")]
@@ -238,7 +238,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:36:18
    |
 LL | #[cfg_attr(true, cfg(crate))]
@@ -253,7 +253,7 @@
 LL + #[cfg_attr(true, cfg(predicate))]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:38:18
    |
 LL | #[cfg_attr(true, cfg(super))]
@@ -268,7 +268,7 @@
 LL + #[cfg_attr(true, cfg(predicate))]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:40:18
    |
 LL | #[cfg_attr(true, cfg(self))]
@@ -283,7 +283,7 @@
 LL + #[cfg_attr(true, cfg(predicate))]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:42:18
    |
 LL | #[cfg_attr(true, cfg(Self))]
@@ -362,7 +362,7 @@
 LL | #[cfg_attr(true, cfg(_))]
    |                      ^ expected identifier, found reserved identifier
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:90:1
    |
 LL | #[cfg(r#crate)]
@@ -377,7 +377,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:93:1
    |
 LL | #[cfg(r#super)]
@@ -392,7 +392,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:96:1
    |
 LL | #[cfg(r#self)]
@@ -407,7 +407,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:99:1
    |
 LL | #[cfg(r#Self)]
@@ -422,7 +422,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:102:1
    |
 LL | #[cfg_attr(r#crate, cfg(r#crate))]
@@ -437,7 +437,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:106:1
    |
 LL | #[cfg_attr(r#super, cfg(r#super))]
@@ -452,7 +452,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:110:1
    |
 LL | #[cfg_attr(r#self, cfg(r#self))]
@@ -467,7 +467,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:114:1
    |
 LL | #[cfg_attr(r#Self, cfg(r#Self))]
@@ -482,7 +482,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:9:9
    |
 LL |         #[cfg($crate)]
@@ -501,7 +501,7 @@
 LL +         #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:11:9
    |
 LL |         #[cfg_attr($crate, path = "foo")]
@@ -520,7 +520,7 @@
 LL +         #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/path-kw-as-cfg-pred.rs:13:26
    |
 LL |         #[cfg_attr(true, cfg($crate))]
@@ -539,7 +539,7 @@
 LL +         #[cfg_attr(true, cfg(predicate))]
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:16:9
    |
 LL |         cfg!($crate);
@@ -558,7 +558,7 @@
 LL +         cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:67:5
    |
 LL |     cfg!(crate);
@@ -573,7 +573,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:68:5
    |
 LL |     cfg!(super);
@@ -588,7 +588,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:69:5
    |
 LL |     cfg!(self);
@@ -603,7 +603,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:70:5
    |
 LL |     cfg!(Self);
@@ -618,7 +618,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:72:5
    |
 LL |     cfg!(r#crate);
@@ -633,7 +633,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:74:5
    |
 LL |     cfg!(r#super);
@@ -648,7 +648,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:76:5
    |
 LL |     cfg!(r#self);
@@ -663,7 +663,7 @@
 LL +     cfg!(predicate);
    |
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/path-kw-as-cfg-pred.rs:78:5
    |
 LL |     cfg!(r#Self);
@@ -698,4 +698,4 @@
 
 error: aborting due to 64 previous errors
 
-For more information about this error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 981c173..3474228 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -65,6 +65,7 @@
 `bulk-memory`
 `c`
 `cache`
+`clflushopt`
 `cmpxchg16b`
 `concurrent-functions`
 `crc`
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
index 641066b..e5f7ed3 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
@@ -1,6 +1,6 @@
 //@ edition:2021
-
 //@ check-pass
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![allow(unreachable_code)]
 #![warn(unused)]
 #![allow(dead_code)]
diff --git a/tests/ui/closures/explicit-closure-lifetime-issue-87290.rs b/tests/ui/closures/explicit-closure-lifetime-issue-87290.rs
new file mode 100644
index 0000000..cde24fa
--- /dev/null
+++ b/tests/ui/closures/explicit-closure-lifetime-issue-87290.rs
@@ -0,0 +1,17 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/87290>.
+
+//@ check-pass
+
+#![crate_type = "lib"]
+
+pub fn f<'a>(_: &'a i32, _: impl FnOnce(&mut &mut &'a i32)) {}
+
+pub fn g<'a>(p: &'a i32) {
+    f(p, |_: &mut &mut &'a i32| {})
+}
+
+pub fn h<'a>(p: &'a i32) {
+    f(p, |x: &mut &mut &'a i32| {
+        let _: &mut &mut &'a i32 = x;
+    })
+}
diff --git a/tests/ui/issues/issue-17322.rs b/tests/ui/coercion/box-dyn-to-ref-dyn.rs
similarity index 73%
rename from tests/ui/issues/issue-17322.rs
rename to tests/ui/coercion/box-dyn-to-ref-dyn.rs
index 014e6b7..e2cdbb6 100644
--- a/tests/ui/issues/issue-17322.rs
+++ b/tests/ui/coercion/box-dyn-to-ref-dyn.rs
@@ -1,3 +1,5 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/17322>.
+
 //@ run-pass
 
 use std::io::{self, Write};
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs
index d79dfa2..f116f5f 100644
--- a/tests/ui/coercion/coerce-loop-issue-122561.rs
+++ b/tests/ui/coercion/coerce-loop-issue-122561.rs
@@ -69,6 +69,24 @@ fn while_zero_times() -> bool {
     }
 }
 
+fn while_let_binding() -> bool {
+    while let x = false {
+    //~^ ERROR mismatched types
+        if x {
+            return true;
+        }
+    }
+}
+
+fn while_let_tuple() -> bool {
+    while let (x, _) = (false, true) {
+    //~^ ERROR mismatched types
+        if x {
+            return true;
+        }
+    }
+}
+
 fn while_never_type() -> ! {
     while true {
     //~^ ERROR mismatched types
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr
index 3fd6671..da69098 100644
--- a/tests/ui/coercion/coerce-loop-issue-122561.stderr
+++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr
@@ -7,7 +7,7 @@
    = note: `#[warn(while_true)]` on by default
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/coerce-loop-issue-122561.rs:73:5
+  --> $DIR/coerce-loop-issue-122561.rs:91:5
    |
 LL |     while true {
    |     ^^^^^^^^^^ help: use `loop`
@@ -171,6 +171,52 @@
 error[E0308]: mismatched types
   --> $DIR/coerce-loop-issue-122561.rs:73:5
    |
+LL |   fn while_let_binding() -> bool {
+   |                             ---- expected `bool` because of return type
+LL |       while let x = false {
+   |       ^         - this pattern always matches, consider using `loop` instead
+   |  _____|
+   | |
+LL | |
+LL | |         if x {
+LL | |             return true;
+LL | |         }
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:82:5
+   |
+LL |   fn while_let_tuple() -> bool {
+   |                           ---- expected `bool` because of return type
+LL |       while let (x, _) = (false, true) {
+   |       ^         ------ this pattern always matches, consider using `loop` instead
+   |  _____|
+   | |
+LL | |
+LL | |         if x {
+LL | |             return true;
+LL | |         }
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:91:5
+   |
 LL |   fn while_never_type() -> ! {
    |                            - expected `!` because of return type
 LL | /     while true {
@@ -188,7 +234,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:87:5
+  --> $DIR/coerce-loop-issue-122561.rs:105:5
    |
 LL | /     for i in 0.. {
 LL | |
@@ -203,7 +249,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:94:9
+  --> $DIR/coerce-loop-issue-122561.rs:112:9
    |
 LL | /         for i in 0..5 {
 LL | |
@@ -218,7 +264,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:100:9
+  --> $DIR/coerce-loop-issue-122561.rs:118:9
    |
 LL | /         while false {
 LL | |
@@ -233,7 +279,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:106:23
+  --> $DIR/coerce-loop-issue-122561.rs:124:23
    |
 LL |     let _ = |a: &[(); for x in 0..2 {}]| {};
    |                       ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
@@ -244,6 +290,6 @@
 LL |     let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {};
    |                                        +++++++++++++++++++
 
-error: aborting due to 14 previous errors; 2 warnings emitted
+error: aborting due to 16 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index 7851758..8098e09 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -59,7 +59,7 @@
 LL + #[cfg(any(a, b))]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-attr-syntax-validation.rs:25:1
    |
 LL | #[cfg("str")]
@@ -74,7 +74,7 @@
 LL + #[cfg(predicate)]
    |
 
-error[E0539]: malformed `cfg` attribute input
+error[E0565]: malformed `cfg` attribute input
   --> $DIR/cfg-attr-syntax-validation.rs:31:1
    |
 LL | #[cfg(a::b)]
@@ -133,5 +133,5 @@
 
 error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0537, E0539, E0805.
+Some errors have detailed explanations: E0537, E0539, E0565, E0805.
 For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr
index 44d4df5..0e4b6e8 100644
--- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr
@@ -37,7 +37,7 @@
 LL | #[cfg_attr(predicate, attr1, attr2, ...)]
    |            ++++++++++++++++++++++++++++
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/cfg_attr-attr-syntax-validation.rs:13:1
    |
 LL | #[cfg_attr("str")]
@@ -52,7 +52,7 @@
 LL + #[cfg_attr(predicate, attr1, attr2, ...)]
    |
 
-error[E0539]: malformed `cfg_attr` attribute input
+error[E0565]: malformed `cfg_attr` attribute input
   --> $DIR/cfg_attr-attr-syntax-validation.rs:16:1
    |
 LL | #[cfg_attr(a::b)]
@@ -177,5 +177,5 @@
 
 error: aborting due to 13 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0537, E0539, E0805.
+Some errors have detailed explanations: E0537, E0539, E0565, E0805.
 For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/ui/issues/auxiliary/issue-16643.rs b/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs
similarity index 80%
rename from tests/ui/issues/auxiliary/issue-16643.rs
rename to tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs
index 7808e01..307f23c 100644
--- a/tests/ui/issues/auxiliary/issue-16643.rs
+++ b/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs
@@ -1,3 +1,5 @@
+//! Auxiliary crate for <https://github.com/rust-lang/rust/issues/16643>.
+
 #![crate_type = "lib"]
 
 pub struct TreeBuilder<H> { pub h: H }
diff --git a/tests/ui/cross-crate/for-loop-in-match-on-self.rs b/tests/ui/cross-crate/for-loop-in-match-on-self.rs
new file mode 100644
index 0000000..e2d960e
--- /dev/null
+++ b/tests/ui/cross-crate/for-loop-in-match-on-self.rs
@@ -0,0 +1,12 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16643>.
+//! Tests that method which matches on self with for loop doesn't ICE cross-crate.
+
+//@ run-pass
+//@ aux-build:for-loop-in-match-on-self.rs
+
+
+extern crate for_loop_in_match_on_self as i;
+
+pub fn main() {
+    i::TreeBuilder { h: 3 }.process_token();
+}
diff --git a/tests/ui/definition-reachable/auxiliary/field-access-macro.rs b/tests/ui/definition-reachable/auxiliary/field-access-macro.rs
new file mode 100644
index 0000000..92a1717
--- /dev/null
+++ b/tests/ui/definition-reachable/auxiliary/field-access-macro.rs
@@ -0,0 +1,16 @@
+#![feature(decl_macro)]
+
+mod n {
+    pub struct Struct(i32);
+    pub fn get_struct() -> Struct { Struct(0) }
+
+    pub macro allow_field_access($x:expr) {
+        &mut $x.0
+    }
+}
+
+pub use n::{allow_field_access, get_struct};
+
+pub macro deny_field_access($x:expr) {
+    &mut $x.0
+}
diff --git a/tests/ui/definition-reachable/auxiliary/transitive-macro.rs b/tests/ui/definition-reachable/auxiliary/transitive-macro.rs
new file mode 100644
index 0000000..993250b
--- /dev/null
+++ b/tests/ui/definition-reachable/auxiliary/transitive-macro.rs
@@ -0,0 +1,15 @@
+#![feature(decl_macro)]
+
+mod mod1 {
+    mod mod2 {
+        pub fn foo() {}
+    }
+
+    pub(crate) macro m1() {
+        mod2::foo()
+    }
+}
+
+pub macro m() {
+    mod1::m1!()
+}
diff --git a/tests/ui/definition-reachable/field-access.rs b/tests/ui/definition-reachable/field-access.rs
new file mode 100644
index 0000000..b2776eb
--- /dev/null
+++ b/tests/ui/definition-reachable/field-access.rs
@@ -0,0 +1,11 @@
+//@ aux-build:field-access-macro.rs
+
+extern crate field_access_macro;
+
+fn main() {
+    let mut s = field_access_macro::get_struct();
+
+    let try_field_access = field_access_macro::allow_field_access!(s); // Ok
+    let try_field_access = field_access_macro::deny_field_access!(s);
+    //~^ ERROR field `0` of struct `field_access_macro::n::Struct` is private
+}
diff --git a/tests/ui/definition-reachable/field-access.stderr b/tests/ui/definition-reachable/field-access.stderr
new file mode 100644
index 0000000..b422976
--- /dev/null
+++ b/tests/ui/definition-reachable/field-access.stderr
@@ -0,0 +1,11 @@
+error[E0616]: field `0` of struct `field_access_macro::n::Struct` is private
+  --> $DIR/field-access.rs:9:28
+   |
+LL |     let try_field_access = field_access_macro::deny_field_access!(s);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field
+   |
+   = note: this error originates in the macro `field_access_macro::deny_field_access` (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 E0616`.
diff --git a/tests/ui/definition-reachable/field-method.rs b/tests/ui/definition-reachable/field-method.rs
index d15b982..94f3520 100644
--- a/tests/ui/definition-reachable/field-method.rs
+++ b/tests/ui/definition-reachable/field-method.rs
@@ -1,11 +1,11 @@
-// Check that functions accessible through a field visible to a macro are
+// Check that functions visible to macros through paths with >2 segments are
 // considered reachable
 
-//@ aux-build:nested-fn-macro.rs
+//@ aux-build:field-method-macro.rs
 //@ run-pass
 
-extern crate nested_fn_macro;
+extern crate field_method_macro;
 
 fn main() {
-    assert_eq!(nested_fn_macro::m!(), 12);
+    assert_eq!(field_method_macro::m!(), 33);
 }
diff --git a/tests/ui/definition-reachable/nested-fn.rs b/tests/ui/definition-reachable/nested-fn.rs
index 94f3520..d15b982 100644
--- a/tests/ui/definition-reachable/nested-fn.rs
+++ b/tests/ui/definition-reachable/nested-fn.rs
@@ -1,11 +1,11 @@
-// Check that functions visible to macros through paths with >2 segments are
+// Check that functions accessible through a field visible to a macro are
 // considered reachable
 
-//@ aux-build:field-method-macro.rs
+//@ aux-build:nested-fn-macro.rs
 //@ run-pass
 
-extern crate field_method_macro;
+extern crate nested_fn_macro;
 
 fn main() {
-    assert_eq!(field_method_macro::m!(), 33);
+    assert_eq!(nested_fn_macro::m!(), 12);
 }
diff --git a/tests/ui/definition-reachable/transitive.rs b/tests/ui/definition-reachable/transitive.rs
new file mode 100644
index 0000000..e5963de
--- /dev/null
+++ b/tests/ui/definition-reachable/transitive.rs
@@ -0,0 +1,10 @@
+//@ aux-build:transitive-macro.rs
+//@ build-fail
+
+extern crate transitive_macro;
+
+fn main() {
+    transitive_macro::m!();
+}
+
+//~? ERROR missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro`
diff --git a/tests/ui/definition-reachable/transitive.stderr b/tests/ui/definition-reachable/transitive.stderr
new file mode 100644
index 0000000..8449983
--- /dev/null
+++ b/tests/ui/definition-reachable/transitive.stderr
@@ -0,0 +1,10 @@
+error: missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro`
+   |
+note: missing optimized MIR for this item (was the crate `transitive_macro` compiled with `--emit=metadata`?)
+  --> $DIR/auxiliary/transitive-macro.rs:5:9
+   |
+LL |         pub fn foo() {}
+   |         ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs
index d1061dc..0ad4911 100644
--- a/tests/ui/deprecation/deprecation-sanity.rs
+++ b/tests/ui/deprecation/deprecation-sanity.rs
@@ -23,6 +23,9 @@ fn f7() { }
 
     #[deprecated("test")] //~ ERROR malformed `deprecated` attribute input [E0565]
     fn f8() { }
+
+    #[deprecated("1.2.3")] //~ ERROR malformed `deprecated` attribute input [E0565]
+    fn f9() { }
 }
 
 #[deprecated(since = "a", note = "b")]
diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr
index 427d14d..2e00b2e 100644
--- a/tests/ui/deprecation/deprecation-sanity.stderr
+++ b/tests/ui/deprecation/deprecation-sanity.stderr
@@ -55,21 +55,40 @@
    |     ^^^^^^^^^^^^^------^^
    |                  |
    |                  didn't expect a literal here
+   |
+help: try using `=` instead
+   |
+LL -     #[deprecated("test")]
+LL +     #[deprecated = "test"]
+   |
+
+error[E0565]: malformed `deprecated` attribute input
+  --> $DIR/deprecation-sanity.rs:27:5
+   |
+LL |     #[deprecated("1.2.3")]
+   |     ^^^^^^^^^^^^^-------^^
+   |                  |
+   |                  didn't expect a literal here
+   |
+help: try specifying a deprecated since version
+   |
+LL |     #[deprecated(since = "1.2.3")]
+   |                  +++++++
 
 error: multiple `deprecated` attributes
-  --> $DIR/deprecation-sanity.rs:29:1
+  --> $DIR/deprecation-sanity.rs:32:1
    |
 LL | #[deprecated(since = "a", note = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/deprecation-sanity.rs:28:1
+  --> $DIR/deprecation-sanity.rs:31:1
    |
 LL | #[deprecated(since = "a", note = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0538]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:32:1
+  --> $DIR/deprecation-sanity.rs:35:1
    |
 LL | #[deprecated(since = "a", since = "b", note = "c")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^
@@ -77,7 +96,7 @@
    |                           found `since` used as a key more than once
 
 error: `#[deprecated]` attribute cannot be used on trait impl blocks
-  --> $DIR/deprecation-sanity.rs:37:1
+  --> $DIR/deprecation-sanity.rs:40:1
    |
 LL | #[deprecated = "hello"]
    | ^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +105,7 @@
    = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements
    = note: `#[deny(useless_deprecated)]` on by default
 
-error: aborting due to 10 previous errors
+error: aborting due to 11 previous errors
 
 Some errors have detailed explanations: E0538, E0539, E0565.
 For more information about an error, try `rustc --explain E0538`.
diff --git a/tests/ui/derives/debug/derives-span-Debug.stderr b/tests/ui/derives/debug/derives-span-Debug.stderr
index e4a2560..0f322e3 100644
--- a/tests/ui/derives/debug/derives-span-Debug.stderr
+++ b/tests/ui/derives/debug/derives-span-Debug.stderr
@@ -7,7 +7,6 @@
 LL |         x: Error,
    |         ^^^^^^^^ the trait `Debug` is not implemented for `Error`
    |
-   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
 help: consider annotating `Error` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
@@ -23,7 +22,6 @@
 LL |         Error,
    |         ^^^^^ the trait `Debug` is not implemented for `Error`
    |
-   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
 help: consider annotating `Error` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
@@ -39,7 +37,6 @@
 LL |     x: Error,
    |     ^^^^^^^^ the trait `Debug` is not implemented for `Error`
    |
-   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
 help: consider annotating `Error` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
@@ -55,7 +52,6 @@
 LL |     Error,
    |     ^^^^^ the trait `Debug` is not implemented for `Error`
    |
-   = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
 help: consider annotating `Error` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
diff --git a/tests/ui/issues/issue-16530.rs b/tests/ui/derives/derive-hash-on-unit-struct.rs
similarity index 65%
rename from tests/ui/issues/issue-16530.rs
rename to tests/ui/derives/derive-hash-on-unit-struct.rs
index a24c6f0..8d261a6 100644
--- a/tests/ui/issues/issue-16530.rs
+++ b/tests/ui/derives/derive-hash-on-unit-struct.rs
@@ -1,3 +1,6 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16530>.
+//! Tests that unit struct produce same constant hash instead of ICE'ing.
+
 //@ run-pass
 #![allow(deprecated)]
 
diff --git a/tests/ui/derives/redundant-derive-note-on-unimplemented.rs b/tests/ui/derives/redundant-derive-note-on-unimplemented.rs
new file mode 100644
index 0000000..f708d3a
--- /dev/null
+++ b/tests/ui/derives/redundant-derive-note-on-unimplemented.rs
@@ -0,0 +1,15 @@
+// Regression test for the redundant `note: add `#[derive(Debug)]` to `X` or manually
+// `impl Debug for X`` that was emitted alongside the `consider annotating X with
+// `#[derive(Debug)]`` suggestion. When the derive suggestion is shown, the note is
+// redundant and should be suppressed.
+//
+// See https://github.com/rust-lang/rust/issues/157118
+
+#[derive(Debug)]
+struct S<T>(T);
+
+struct X;
+
+fn main() {
+    println!("{:?}", S(X)); //~ ERROR `X` doesn't implement `Debug`
+}
diff --git a/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr
new file mode 100644
index 0000000..dcb1639
--- /dev/null
+++ b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr
@@ -0,0 +1,31 @@
+error[E0277]: `X` doesn't implement `Debug`
+  --> $DIR/redundant-derive-note-on-unimplemented.rs:14:22
+   |
+LL |     println!("{:?}", S(X));
+   |               ----   ^^^^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |               |
+   |               required by this formatting parameter
+   |
+   = help: the trait `Debug` is not implemented for `X`
+help: the trait `Debug` is implemented for `S<T>`
+  --> $DIR/redundant-derive-note-on-unimplemented.rs:8:10
+   |
+LL | #[derive(Debug)]
+   |          ^^^^^
+note: required for `S<X>` to implement `Debug`
+  --> $DIR/redundant-derive-note-on-unimplemented.rs:9:8
+   |
+LL | #[derive(Debug)]
+   |          ----- in this derive macro expansion
+LL | struct S<T>(T);
+   |        ^ - type parameter would need to implement `Debug`
+   = help: consider manually implementing `Debug` to avoid undesired bounds
+help: consider annotating `X` with `#[derive(Debug)]`
+   |
+LL + #[derive(Debug)]
+LL | struct X;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-17771.rs b/tests/ui/dst/reborrow-mut-dyn-trait-field.rs
similarity index 63%
rename from tests/ui/issues/issue-17771.rs
rename to tests/ui/dst/reborrow-mut-dyn-trait-field.rs
index 2e27cfc..994c810 100644
--- a/tests/ui/issues/issue-17771.rs
+++ b/tests/ui/dst/reborrow-mut-dyn-trait-field.rs
@@ -1,3 +1,6 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/17771>.
+//! Tests that borrowing mut dyn trait field in a method doesn't cause ICE.
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/eii/auxiliary/unused_extern_crate_decl.rs b/tests/ui/eii/auxiliary/unused_extern_crate_decl.rs
new file mode 100644
index 0000000..7e0ba5f
--- /dev/null
+++ b/tests/ui/eii/auxiliary/unused_extern_crate_decl.rs
@@ -0,0 +1,6 @@
+//@ no-prefer-dynamic
+#![crate_type = "rlib"]
+#![feature(extern_item_impls)]
+
+#[eii(eii1)]
+pub fn decl1(x: u64);
diff --git a/tests/ui/eii/auxiliary/unused_extern_crate_impl.rs b/tests/ui/eii/auxiliary/unused_extern_crate_impl.rs
new file mode 100644
index 0000000..0cfc2c3
--- /dev/null
+++ b/tests/ui/eii/auxiliary/unused_extern_crate_impl.rs
@@ -0,0 +1,9 @@
+//@ no-prefer-dynamic
+//@ aux-build:unused_extern_crate_decl.rs
+#![crate_type = "rlib"]
+#![feature(extern_item_impls)]
+
+extern crate unused_extern_crate_decl;
+
+#[unused_extern_crate_decl::eii1]
+fn impl1(x: u64) {}
diff --git a/tests/ui/eii/dylib_needs_impl.rs b/tests/ui/eii/dylib_needs_impl.rs
index bb1ec22..1568145 100644
--- a/tests/ui/eii/dylib_needs_impl.rs
+++ b/tests/ui/eii/dylib_needs_impl.rs
@@ -3,5 +3,5 @@
 #![crate_type = "dylib"]
 #![feature(extern_item_impls)]
 
-#[eii(eii1)] //~ ERROR `#[eii1]` required, but not found
+#[eii(eii1)] //~ ERROR `#[eii1]` function required, but not found
 fn decl1(x: u64);
diff --git a/tests/ui/eii/dylib_needs_impl.stderr b/tests/ui/eii/dylib_needs_impl.stderr
index 60ef656..45c27f4 100644
--- a/tests/ui/eii/dylib_needs_impl.stderr
+++ b/tests/ui/eii/dylib_needs_impl.stderr
@@ -1,4 +1,4 @@
-error: `#[eii1]` required, but not found
+error: `#[eii1]` function required, but not found
   --> $DIR/dylib_needs_impl.rs:6:7
    |
 LL | #[eii(eii1)]
diff --git a/tests/ui/eii/privacy2.rs b/tests/ui/eii/privacy2.rs
index c11061f..b5d8660 100644
--- a/tests/ui/eii/privacy2.rs
+++ b/tests/ui/eii/privacy2.rs
@@ -5,8 +5,8 @@
 extern crate other_crate_privacy2 as codegen;
 
 // has a span but in the other crate
-//~? ERROR `#[eii2]` required, but not found
-//~? ERROR `#[eii3]` required, but not found
+//~? ERROR `#[eii2]` function required, but not found
+//~? ERROR `#[eii3]` function required, but not found
 
 #[codegen::eii1]
 fn eii1_impl(x: u64) {
diff --git a/tests/ui/eii/privacy2.stderr b/tests/ui/eii/privacy2.stderr
index f0a04bf..bf84385 100644
--- a/tests/ui/eii/privacy2.stderr
+++ b/tests/ui/eii/privacy2.stderr
@@ -16,7 +16,7 @@
 LL | fn decl1(x: u64);
    | ^^^^^^^^^^^^^^^^^
 
-error: `#[eii2]` required, but not found
+error: `#[eii2]` function required, but not found
   --> $DIR/auxiliary/other_crate_privacy2.rs:9:7
    |
 LL | #[eii(eii2)]
@@ -24,7 +24,7 @@
    |
    = help: expected at least one implementation in crate `privacy2` or any of its dependencies
 
-error: `#[eii3]` required, but not found
+error: `#[eii3]` function required, but not found
   --> $DIR/auxiliary/other_crate_privacy2.rs:13:11
    |
 LL |     #[eii(eii3)]
diff --git a/tests/ui/eii/shadow_builtin.rs b/tests/ui/eii/shadow_builtin.rs
index 5f619b7..6e6ecda 100644
--- a/tests/ui/eii/shadow_builtin.rs
+++ b/tests/ui/eii/shadow_builtin.rs
@@ -5,7 +5,7 @@
 #![feature(extern_item_impls)]
 
 #[eii(inline)]
-//~^ ERROR `#[inline]` required, but not found
+//~^ ERROR `#[inline]` function required, but not found
 fn test(x: u64);
 
 #[inline]
@@ -14,4 +14,4 @@ fn test_impl(x: u64) {
     println!("{x:?}")
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/eii/shadow_builtin.stderr b/tests/ui/eii/shadow_builtin.stderr
index d48e66a..33f60b2 100644
--- a/tests/ui/eii/shadow_builtin.stderr
+++ b/tests/ui/eii/shadow_builtin.stderr
@@ -13,7 +13,7 @@
    | ^^^^^^^^^^^^^^
    = help: use `crate::inline` to refer to this attribute macro unambiguously
 
-error: `#[inline]` required, but not found
+error: `#[inline]` function required, but not found
   --> $DIR/shadow_builtin.rs:7:7
    |
 LL | #[eii(inline)]
diff --git a/tests/ui/eii/unsafe_impl_err.rs b/tests/ui/eii/unsafe_impl_err.rs
index a6d24c4..c02f214 100644
--- a/tests/ui/eii/unsafe_impl_err.rs
+++ b/tests/ui/eii/unsafe_impl_err.rs
@@ -5,6 +5,7 @@
 #![feature(rustc_attrs)]
 #![feature(eii_internals)]
 
+// Uses manual desugaring of EII internals.
 #[eii_declaration(bar, "unsafe")]
 #[rustc_builtin_macro(eii_shared_macro)]
 macro foo() {}
@@ -18,6 +19,16 @@ fn other(x: u64) -> u64 {
     x
 }
 
+// Uses the user-facing unsafe_eii wrapper.
+#[unsafe_eii(baz)]
+fn qux(x: u64) -> u64;
+
+#[baz] //~ ERROR `#[baz]` is unsafe to implement
+fn another(x: u64) -> u64 {
+    x
+}
+
 fn main() {
     bar(0);
+    qux(0);
 }
diff --git a/tests/ui/eii/unsafe_impl_err.stderr b/tests/ui/eii/unsafe_impl_err.stderr
index eb917a6..0eb3acd 100644
--- a/tests/ui/eii/unsafe_impl_err.stderr
+++ b/tests/ui/eii/unsafe_impl_err.stderr
@@ -1,5 +1,5 @@
 error: `#[foo]` is unsafe to implement
-  --> $DIR/unsafe_impl_err.rs:16:1
+  --> $DIR/unsafe_impl_err.rs:17:1
    |
 LL | #[foo]
    | ^^^^^^
@@ -9,5 +9,16 @@
 LL | #[unsafe(foo)]
    |   +++++++   +
 
-error: aborting due to 1 previous error
+error: `#[baz]` is unsafe to implement
+  --> $DIR/unsafe_impl_err.rs:26:1
+   |
+LL | #[baz]
+   | ^^^^^^
+   |
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | #[unsafe(baz)]
+   |   +++++++   +
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/eii/unsafe_impl_ok.rs b/tests/ui/eii/unsafe_impl_ok.rs
index 1af6d63..f7667af 100644
--- a/tests/ui/eii/unsafe_impl_ok.rs
+++ b/tests/ui/eii/unsafe_impl_ok.rs
@@ -1,12 +1,12 @@
 //@ compile-flags: --crate-type rlib
 //@ check-pass
-// Uses manual desugaring of EII internals:
 // Tests whether it's okay to implement an unsafe EII with an unsafe implementation.
 #![feature(extern_item_impls)]
 #![feature(decl_macro)]
 #![feature(rustc_attrs)]
 #![feature(eii_internals)]
 
+// Uses manual desugaring of EII internals.
 #[eii_declaration(bar, "unsafe")]
 #[rustc_builtin_macro(eii_shared_macro)]
 macro foo() {}
@@ -20,6 +20,16 @@ fn other(x: u64) -> u64 {
     x
 }
 
+// Uses the user-facing unsafe_eii wrapper.
+#[unsafe_eii(baz)]
+fn qux(x: u64) -> u64;
+
+#[unsafe(baz)]
+fn another(x: u64) -> u64 {
+    x
+}
+
 fn main() {
     bar(0);
+    qux(0);
 }
diff --git a/tests/ui/eii/unused_extern_crate.rs b/tests/ui/eii/unused_extern_crate.rs
new file mode 100644
index 0000000..0fef1c3
--- /dev/null
+++ b/tests/ui/eii/unused_extern_crate.rs
@@ -0,0 +1,11 @@
+//@ aux-build:unused_extern_crate_decl.rs
+//@ aux-build:unused_extern_crate_impl.rs
+// Tests that dependencies that contain an EII decl without any EII impl are
+// still considered unused.
+#![feature(extern_item_impls)]
+#![deny(unused_extern_crates)]
+
+extern crate unused_extern_crate_decl; //~ ERROR unused extern crate
+extern crate unused_extern_crate_impl;
+
+fn main() {}
diff --git a/tests/ui/eii/unused_extern_crate.stderr b/tests/ui/eii/unused_extern_crate.stderr
new file mode 100644
index 0000000..03fe49e
--- /dev/null
+++ b/tests/ui/eii/unused_extern_crate.stderr
@@ -0,0 +1,19 @@
+error: unused extern crate
+  --> $DIR/unused_extern_crate.rs:8:1
+   |
+LL | extern crate unused_extern_crate_decl;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+note: the lint level is defined here
+  --> $DIR/unused_extern_crate.rs:6:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: remove the unused `extern crate`
+   |
+LL - extern crate unused_extern_crate_decl;
+LL +
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.rs b/tests/ui/error-codes/E0152-duplicate-lang-items.rs
index 4b24320..17f235c 100644
--- a/tests/ui/error-codes/E0152-duplicate-lang-items.rs
+++ b/tests/ui/error-codes/E0152-duplicate-lang-items.rs
@@ -12,9 +12,9 @@
 
 use core::panic::PanicInfo;
 
-#[lang = "panic_impl"]
-fn panic_impl(info: &PanicInfo) -> ! {
-    //~^ ERROR: found duplicate lang item `panic_impl`
+#[lang = "eh_personality"]
+fn personality() {
+    //~^ ERROR: found duplicate lang item `eh_personality`
     //~| NOTE first defined in crate `std`
     loop {}
 }
diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
index 55d5206..3e6cbd2 100644
--- a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
+++ b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
@@ -1,7 +1,7 @@
-error[E0152]: found duplicate lang item `panic_impl`
+error[E0152]: found duplicate lang item `eh_personality`
   --> $DIR/E0152-duplicate-lang-items.rs:16:1
    |
-LL | / fn panic_impl(info: &PanicInfo) -> ! {
+LL | / fn personality() {
 LL | |
 LL | |
 LL | |     loop {}
diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr
index d1aff04..0c500d2 100644
--- a/tests/ui/error-codes/E0565-1.stderr
+++ b/tests/ui/error-codes/E0565-1.stderr
@@ -5,6 +5,12 @@
    | ^^^^^^^^^^^^^-------^^
    |              |
    |              didn't expect a literal here
+   |
+help: try using `=` instead
+   |
+LL - #[deprecated("since")]
+LL + #[deprecated = "since"]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0565.stderr b/tests/ui/error-codes/E0565.stderr
index 6e56600..7d22501 100644
--- a/tests/ui/error-codes/E0565.stderr
+++ b/tests/ui/error-codes/E0565.stderr
@@ -1,8 +1,12 @@
-error[E0565]: meta item in `repr` must be an identifier
+error[E0565]: malformed `repr` attribute input
   --> $DIR/E0565.rs:2:1
    |
 LL | #[repr("C")]
-   | ^^^^^^^^^^^^
+   | ^^^^^^^---^^
+   |        |
+   |        expected a valid identifier here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.rs b/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.rs
new file mode 100644
index 0000000..8200efa
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "clflushopt")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.stderr b/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.stderr
new file mode 100644
index 0000000..722bf86
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-clflushopt_target_feature.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `clflushopt` is currently unstable
+  --> $DIR/feature-gate-clflushopt_target_feature.rs:2:18
+   |
+LL | #[target_feature(enable = "clflushopt")]
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #157096 <https://github.com/rust-lang/rust/issues/157096> for more information
+   = help: add `#![feature(clflushopt_target_feature)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fmt/format-args-argument-span.stderr b/tests/ui/fmt/format-args-argument-span.stderr
index a486abe..76fc178 100644
--- a/tests/ui/fmt/format-args-argument-span.stderr
+++ b/tests/ui/fmt/format-args-argument-span.stderr
@@ -25,7 +25,6 @@
    |                   ^^^^^ `DisplayOnly` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for `DisplayOnly`
-   = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly`
 help: consider annotating `DisplayOnly` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
@@ -41,7 +40,6 @@
    |                   required by this formatting parameter
    |
    = help: the trait `Debug` is not implemented for `DisplayOnly`
-   = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly`
 help: consider annotating `DisplayOnly` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
diff --git a/tests/ui/fmt/non-source-literals.stderr b/tests/ui/fmt/non-source-literals.stderr
index 953a4a6..39dc356 100644
--- a/tests/ui/fmt/non-source-literals.stderr
+++ b/tests/ui/fmt/non-source-literals.stderr
@@ -31,7 +31,6 @@
    |                                          ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for `NonDebug`
-   = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug`
 help: consider annotating `NonDebug` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
@@ -45,7 +44,6 @@
    |                                               ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for `NonDebug`
-   = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug`
 help: consider annotating `NonDebug` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
diff --git a/tests/ui/force-inlining/deny-async.stderr b/tests/ui/force-inlining/deny-async.stderr
index d6516ed..bd24bc6 100644
--- a/tests/ui/force-inlining/deny-async.stderr
+++ b/tests/ui/force-inlining/deny-async.stderr
@@ -20,14 +20,6 @@
    |
    = note: incompatible due to: #[rustc_no_mir_inline]
 
-error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
-  --> $DIR/deny-async.rs:22:5
-   |
-LL |     callee();
-   |     ^^^^^^^^ ...`callee` called here
-   |
-   = note: could not be inlined due to: #[rustc_no_mir_inline]
-
 error: `callee_justified` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
   --> $DIR/deny-async.rs:24:5
    |
@@ -37,5 +29,13 @@
    = note: could not be inlined due to: #[rustc_no_mir_inline]
    = note: `callee_justified` is required to be inlined to: the test requires it
 
+error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
+  --> $DIR/deny-async.rs:22:5
+   |
+LL |     callee();
+   |     ^^^^^^^^ ...`callee` called here
+   |
+   = note: could not be inlined due to: #[rustc_no_mir_inline]
+
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/imports/ambiguous-1.rs b/tests/ui/imports/ambiguous-1.rs
index 31f39ee..6c8e7da 100644
--- a/tests/ui/imports/ambiguous-1.rs
+++ b/tests/ui/imports/ambiguous-1.rs
@@ -1,8 +1,5 @@
-//@ check-pass
 // https://github.com/rust-lang/rust/pull/112743#issuecomment-1601986883
 
-#![warn(ambiguous_glob_imports)]
-
 macro_rules! m {
     () => {
       pub fn id() {}
@@ -27,6 +24,5 @@ mod handwritten {
 
 fn main() {
     id();
-    //~^ WARNING `id` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~^ ERROR `id` is ambiguous
 }
diff --git a/tests/ui/imports/ambiguous-1.stderr b/tests/ui/imports/ambiguous-1.stderr
index 603a893..b891baa 100644
--- a/tests/ui/imports/ambiguous-1.stderr
+++ b/tests/ui/imports/ambiguous-1.stderr
@@ -1,5 +1,25 @@
+error[E0659]: `id` is ambiguous
+  --> $DIR/ambiguous-1.rs:26:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-1.rs:10:13
+   |
+LL |     pub use self::evp::*;
+   |             ^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-1.rs:12:13
+   |
+LL |     pub use self::handwritten::*;
+   |             ^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+
 warning: ambiguous glob re-exports
-  --> $DIR/ambiguous-1.rs:13:13
+  --> $DIR/ambiguous-1.rs:10:13
    |
 LL |     pub use self::evp::*;
    |             ^^^^^^^^^^^^ the name `id` in the value namespace is first re-exported here
@@ -9,60 +29,6 @@
    |
    = note: `#[warn(ambiguous_glob_reexports)]` on by default
 
-warning: `id` is ambiguous
-  --> $DIR/ambiguous-1.rs:29:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-1.rs:13:13
-   |
-LL |     pub use self::evp::*;
-   |             ^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-1.rs:15:13
-   |
-LL |     pub use self::handwritten::*;
-   |             ^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-note: the lint level is defined here
-  --> $DIR/ambiguous-1.rs:4:9
-   |
-LL | #![warn(ambiguous_glob_imports)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 1 previous error; 1 warning emitted
 
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: `id` is ambiguous
-  --> $DIR/ambiguous-1.rs:29:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-1.rs:13:13
-   |
-LL |     pub use self::evp::*;
-   |             ^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-1.rs:15:13
-   |
-LL |     pub use self::handwritten::*;
-   |             ^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-note: the lint level is defined here
-  --> $DIR/ambiguous-1.rs:4:9
-   |
-LL | #![warn(ambiguous_glob_imports)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-10.rs b/tests/ui/imports/ambiguous-10.rs
index 166b01e..362633b 100644
--- a/tests/ui/imports/ambiguous-10.rs
+++ b/tests/ui/imports/ambiguous-10.rs
@@ -14,5 +14,4 @@ pub enum Token {}
 use crate::b::*;
 fn c(_: Token) {}
 //~^ ERROR `Token` is ambiguous
-//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 fn main() { }
diff --git a/tests/ui/imports/ambiguous-10.stderr b/tests/ui/imports/ambiguous-10.stderr
index edd7877..e3f126d 100644
--- a/tests/ui/imports/ambiguous-10.stderr
+++ b/tests/ui/imports/ambiguous-10.stderr
@@ -1,4 +1,4 @@
-error: `Token` is ambiguous
+error[E0659]: `Token` is ambiguous
   --> $DIR/ambiguous-10.rs:15:9
    |
 LL | fn c(_: Token) {}
@@ -17,33 +17,7 @@
 LL | use crate::b::*;
    |     ^^^^^^^^^^^
    = help: consider adding an explicit import of `Token` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `Token` is ambiguous
-  --> $DIR/ambiguous-10.rs:15:9
-   |
-LL | fn c(_: Token) {}
-   |         ^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `Token` could refer to the enum imported here
-  --> $DIR/ambiguous-10.rs:13:5
-   |
-LL | use crate::a::*;
-   |     ^^^^^^^^^^^
-   = help: consider adding an explicit import of `Token` to disambiguate
-note: `Token` could also refer to the enum imported here
-  --> $DIR/ambiguous-10.rs:14:5
-   |
-LL | use crate::b::*;
-   |     ^^^^^^^^^^^
-   = help: consider adding an explicit import of `Token` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-12.rs b/tests/ui/imports/ambiguous-12.rs
index 543396b..54bdf26 100644
--- a/tests/ui/imports/ambiguous-12.rs
+++ b/tests/ui/imports/ambiguous-12.rs
@@ -20,5 +20,4 @@ pub mod public {
 fn main() {
     b();
     //~^ ERROR `b` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
diff --git a/tests/ui/imports/ambiguous-12.stderr b/tests/ui/imports/ambiguous-12.stderr
index e20eec2..099abd6 100644
--- a/tests/ui/imports/ambiguous-12.stderr
+++ b/tests/ui/imports/ambiguous-12.stderr
@@ -1,4 +1,4 @@
-error: `b` is ambiguous
+error[E0659]: `b` is ambiguous
   --> $DIR/ambiguous-12.rs:21:5
    |
 LL |     b();
@@ -17,33 +17,7 @@
 LL | use crate::public::*;
    |     ^^^^^^^^^^^^^^^^
    = help: consider adding an explicit import of `b` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `b` is ambiguous
-  --> $DIR/ambiguous-12.rs:21:5
-   |
-LL |     b();
-   |     ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `b` could refer to the function imported here
-  --> $DIR/ambiguous-12.rs:17:5
-   |
-LL | use crate::ciphertext::*;
-   |     ^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `b` to disambiguate
-note: `b` could also refer to the function imported here
-  --> $DIR/ambiguous-12.rs:18:5
-   |
-LL | use crate::public::*;
-   |     ^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `b` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-13.rs b/tests/ui/imports/ambiguous-13.rs
index 3569dd5..7dc617c 100644
--- a/tests/ui/imports/ambiguous-13.rs
+++ b/tests/ui/imports/ambiguous-13.rs
@@ -17,5 +17,4 @@ pub mod content {
 
 fn a(_: Rect) {}
 //~^ ERROR `Rect` is ambiguous
-//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 fn main() { }
diff --git a/tests/ui/imports/ambiguous-13.stderr b/tests/ui/imports/ambiguous-13.stderr
index c1dfac5..1d105ee 100644
--- a/tests/ui/imports/ambiguous-13.stderr
+++ b/tests/ui/imports/ambiguous-13.stderr
@@ -1,4 +1,4 @@
-error: `Rect` is ambiguous
+error[E0659]: `Rect` is ambiguous
   --> $DIR/ambiguous-13.rs:18:9
    |
 LL | fn a(_: Rect) {}
@@ -17,33 +17,7 @@
 LL | use crate::content::*;
    |     ^^^^^^^^^^^^^^^^^
    = help: consider adding an explicit import of `Rect` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `Rect` is ambiguous
-  --> $DIR/ambiguous-13.rs:18:9
-   |
-LL | fn a(_: Rect) {}
-   |         ^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `Rect` could refer to the struct imported here
-  --> $DIR/ambiguous-13.rs:15:5
-   |
-LL | use crate::object::*;
-   |     ^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `Rect` to disambiguate
-note: `Rect` could also refer to the struct imported here
-  --> $DIR/ambiguous-13.rs:16:5
-   |
-LL | use crate::content::*;
-   |     ^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `Rect` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-15.rs b/tests/ui/imports/ambiguous-15.rs
index 07d8893..72c2940 100644
--- a/tests/ui/imports/ambiguous-15.rs
+++ b/tests/ui/imports/ambiguous-15.rs
@@ -21,6 +21,5 @@ pub trait Error {}
 use self::t3::*;
 fn a<E: Error>(_: E) {}
 //~^ ERROR `Error` is ambiguous
-//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 fn main() {}
diff --git a/tests/ui/imports/ambiguous-15.stderr b/tests/ui/imports/ambiguous-15.stderr
index cb9f6eb..fb3551d 100644
--- a/tests/ui/imports/ambiguous-15.stderr
+++ b/tests/ui/imports/ambiguous-15.stderr
@@ -1,4 +1,4 @@
-error: `Error` is ambiguous
+error[E0659]: `Error` is ambiguous
   --> $DIR/ambiguous-15.rs:22:9
    |
 LL | fn a<E: Error>(_: E) {}
@@ -17,33 +17,7 @@
 LL | pub use t2::*;
    |         ^^^^^
    = help: consider adding an explicit import of `Error` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `Error` is ambiguous
-  --> $DIR/ambiguous-15.rs:22:9
-   |
-LL | fn a<E: Error>(_: E) {}
-   |         ^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `Error` could refer to the trait imported here
-  --> $DIR/ambiguous-15.rs:21:5
-   |
-LL | use self::t3::*;
-   |     ^^^^^^^^^^^
-   = help: consider adding an explicit import of `Error` to disambiguate
-note: `Error` could also refer to the enum imported here
-  --> $DIR/ambiguous-15.rs:15:9
-   |
-LL | pub use t2::*;
-   |         ^^^^^
-   = help: consider adding an explicit import of `Error` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-16.rs b/tests/ui/imports/ambiguous-16.rs
index f31c78d..a20c0e3 100644
--- a/tests/ui/imports/ambiguous-16.rs
+++ b/tests/ui/imports/ambiguous-16.rs
@@ -21,6 +21,5 @@ mod public_message_in {
 
 use crate::framing::ConfirmedTranscriptHashInput;
 //~^ ERROR `ConfirmedTranscriptHashInput` is ambiguous
-//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 fn main() { }
diff --git a/tests/ui/imports/ambiguous-16.stderr b/tests/ui/imports/ambiguous-16.stderr
index cad19b8..c18242d 100644
--- a/tests/ui/imports/ambiguous-16.stderr
+++ b/tests/ui/imports/ambiguous-16.stderr
@@ -1,4 +1,4 @@
-error: `ConfirmedTranscriptHashInput` is ambiguous
+error[E0659]: `ConfirmedTranscriptHashInput` is ambiguous
   --> $DIR/ambiguous-16.rs:22:21
    |
 LL | use crate::framing::ConfirmedTranscriptHashInput;
@@ -17,33 +17,7 @@
 LL |     pub use self::public_message_in::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: consider adding an explicit import of `ConfirmedTranscriptHashInput` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `ConfirmedTranscriptHashInput` is ambiguous
-  --> $DIR/ambiguous-16.rs:22:21
-   |
-LL | use crate::framing::ConfirmedTranscriptHashInput;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `ConfirmedTranscriptHashInput` could refer to the struct imported here
-  --> $DIR/ambiguous-16.rs:18:13
-   |
-LL |     pub use self::public_message::*;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `ConfirmedTranscriptHashInput` to disambiguate
-note: `ConfirmedTranscriptHashInput` could also refer to the struct imported here
-  --> $DIR/ambiguous-16.rs:19:13
-   |
-LL |     pub use self::public_message_in::*;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `ConfirmedTranscriptHashInput` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-17.rs b/tests/ui/imports/ambiguous-17.rs
index 3a51c15..5ba51ce 100644
--- a/tests/ui/imports/ambiguous-17.rs
+++ b/tests/ui/imports/ambiguous-17.rs
@@ -25,5 +25,4 @@ mod evp {
 fn main() {
     id();
     //~^ ERROR `id` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
diff --git a/tests/ui/imports/ambiguous-17.stderr b/tests/ui/imports/ambiguous-17.stderr
index 80d152f..b46a943 100644
--- a/tests/ui/imports/ambiguous-17.stderr
+++ b/tests/ui/imports/ambiguous-17.stderr
@@ -1,3 +1,23 @@
+error[E0659]: `id` is ambiguous
+  --> $DIR/ambiguous-17.rs:26:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-17.rs:4:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-17.rs:5:9
+   |
+LL | pub use handwritten::*;
+   |         ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+
 warning: ambiguous glob re-exports
   --> $DIR/ambiguous-17.rs:4:9
    |
@@ -8,52 +28,6 @@
    |
    = note: `#[warn(ambiguous_glob_reexports)]` on by default
 
-error: `id` is ambiguous
-  --> $DIR/ambiguous-17.rs:26:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-17.rs:4:9
-   |
-LL | pub use evp::*;
-   |         ^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-17.rs:5:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
 error: aborting due to 1 previous error; 1 warning emitted
 
-Future incompatibility report: Future breakage diagnostic:
-error: `id` is ambiguous
-  --> $DIR/ambiguous-17.rs:26:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-17.rs:4:9
-   |
-LL | pub use evp::*;
-   |         ^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-17.rs:5:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-2.rs b/tests/ui/imports/ambiguous-2.rs
deleted file mode 100644
index 65c971c..0000000
--- a/tests/ui/imports/ambiguous-2.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ aux-build: ../ambiguous-1.rs
-// https://github.com/rust-lang/rust/pull/113099#issuecomment-1633574396
-
-extern crate ambiguous_1;
-
-fn main() {
-    ambiguous_1::id(); //~ ERROR `id` is ambiguous
-                       //~| WARN this was previously accepted
-}
diff --git a/tests/ui/imports/ambiguous-2.stderr b/tests/ui/imports/ambiguous-2.stderr
deleted file mode 100644
index a07f09c..0000000
--- a/tests/ui/imports/ambiguous-2.stderr
+++ /dev/null
@@ -1,49 +0,0 @@
-error: `id` is ambiguous
-  --> $DIR/ambiguous-2.rs:7:18
-   |
-LL |     ambiguous_1::id();
-   |                  ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-1.rs:13:13
-   |
-LL |     pub use self::evp::*;
-   |             ^^^^^^^^^
-   = help: consider updating this dependency to resolve this error
-   = help: if updating the dependency does not resolve the problem report the problem to the author of the relevant crate
-note: `id` could also refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-1.rs:15:13
-   |
-LL |     pub use self::handwritten::*;
-   |             ^^^^^^^^^^^^^^^^^
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
-error: aborting due to 1 previous error
-
-Future incompatibility report: Future breakage diagnostic:
-error: `id` is ambiguous
-  --> $DIR/ambiguous-2.rs:7:18
-   |
-LL |     ambiguous_1::id();
-   |                  ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-1.rs:13:13
-   |
-LL |     pub use self::evp::*;
-   |             ^^^^^^^^^
-   = help: consider updating this dependency to resolve this error
-   = help: if updating the dependency does not resolve the problem report the problem to the author of the relevant crate
-note: `id` could also refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-1.rs:15:13
-   |
-LL |     pub use self::handwritten::*;
-   |             ^^^^^^^^^^^^^^^^^
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
diff --git a/tests/ui/imports/ambiguous-3.rs b/tests/ui/imports/ambiguous-3.rs
index ff0dcc2..4919d9f 100644
--- a/tests/ui/imports/ambiguous-3.rs
+++ b/tests/ui/imports/ambiguous-3.rs
@@ -4,7 +4,6 @@ fn main() {
     use a::*;
     x();
     //~^ ERROR `x` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 mod a {
diff --git a/tests/ui/imports/ambiguous-3.stderr b/tests/ui/imports/ambiguous-3.stderr
index 1e4aad8..6c3031a 100644
--- a/tests/ui/imports/ambiguous-3.stderr
+++ b/tests/ui/imports/ambiguous-3.stderr
@@ -1,4 +1,4 @@
-error: `x` is ambiguous
+error[E0659]: `x` is ambiguous
   --> $DIR/ambiguous-3.rs:5:5
    |
 LL |     x();
@@ -6,44 +6,18 @@
    |
    = note: ambiguous because of multiple glob imports of a name in the same module
 note: `x` could refer to the function imported here
-  --> $DIR/ambiguous-3.rs:18:13
+  --> $DIR/ambiguous-3.rs:17:13
    |
 LL |     pub use self::b::*;
    |             ^^^^^^^^^^
    = help: consider adding an explicit import of `x` to disambiguate
 note: `x` could also refer to the function imported here
-  --> $DIR/ambiguous-3.rs:19:13
+  --> $DIR/ambiguous-3.rs:18:13
    |
 LL |     pub use self::c::*;
    |             ^^^^^^^^^^
    = help: consider adding an explicit import of `x` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `x` is ambiguous
-  --> $DIR/ambiguous-3.rs:5:5
-   |
-LL |     x();
-   |     ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `x` could refer to the function imported here
-  --> $DIR/ambiguous-3.rs:18:13
-   |
-LL |     pub use self::b::*;
-   |             ^^^^^^^^^^
-   = help: consider adding an explicit import of `x` to disambiguate
-note: `x` could also refer to the function imported here
-  --> $DIR/ambiguous-3.rs:19:13
-   |
-LL |     pub use self::c::*;
-   |             ^^^^^^^^^^
-   = help: consider adding an explicit import of `x` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-4-extern.rs b/tests/ui/imports/ambiguous-4-extern.rs
index 125612d..a062b38 100644
--- a/tests/ui/imports/ambiguous-4-extern.rs
+++ b/tests/ui/imports/ambiguous-4-extern.rs
@@ -1,9 +1,6 @@
 //@ edition:2015
-//@ check-pass
 // https://github.com/rust-lang/rust/pull/112743#issuecomment-1601986883
 
-#![warn(ambiguous_glob_imports)]
-
 macro_rules! m {
     () => {
       pub fn id() {}
@@ -24,6 +21,5 @@ mod handwritten {
 
 fn main() {
     id();
-    //~^ WARNING `id` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~^ ERROR `id` is ambiguous
 }
diff --git a/tests/ui/imports/ambiguous-4-extern.stderr b/tests/ui/imports/ambiguous-4-extern.stderr
index 4658071..dae8432 100644
--- a/tests/ui/imports/ambiguous-4-extern.stderr
+++ b/tests/ui/imports/ambiguous-4-extern.stderr
@@ -1,5 +1,25 @@
+error[E0659]: `id` is ambiguous
+  --> $DIR/ambiguous-4-extern.rs:23:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-4-extern.rs:10:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-4-extern.rs:11:9
+   |
+LL | pub use handwritten::*;
+   |         ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+
 warning: ambiguous glob re-exports
-  --> $DIR/ambiguous-4-extern.rs:13:9
+  --> $DIR/ambiguous-4-extern.rs:10:9
    |
 LL | pub use evp::*;
    |         ^^^^^^ the name `id` in the value namespace is first re-exported here
@@ -8,60 +28,6 @@
    |
    = note: `#[warn(ambiguous_glob_reexports)]` on by default
 
-warning: `id` is ambiguous
-  --> $DIR/ambiguous-4-extern.rs:26:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-4-extern.rs:13:9
-   |
-LL | pub use evp::*;
-   |         ^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-4-extern.rs:14:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-note: the lint level is defined here
-  --> $DIR/ambiguous-4-extern.rs:5:9
-   |
-LL | #![warn(ambiguous_glob_imports)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 1 previous error; 1 warning emitted
 
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: `id` is ambiguous
-  --> $DIR/ambiguous-4-extern.rs:26:5
-   |
-LL |     id();
-   |     ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function imported here
-  --> $DIR/ambiguous-4-extern.rs:13:9
-   |
-LL | pub use evp::*;
-   |         ^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-note: `id` could also refer to the function imported here
-  --> $DIR/ambiguous-4-extern.rs:14:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `id` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-note: the lint level is defined here
-  --> $DIR/ambiguous-4-extern.rs:5:9
-   |
-LL | #![warn(ambiguous_glob_imports)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-4.rs b/tests/ui/imports/ambiguous-4.rs
deleted file mode 100644
index e66d231f..0000000
--- a/tests/ui/imports/ambiguous-4.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ edition:2015
-//@ aux-build: ../ambiguous-4-extern.rs
-
-extern crate ambiguous_4_extern;
-
-fn main() {
-    ambiguous_4_extern::id(); //~ ERROR `id` is ambiguous
-                              //~| WARN this was previously accepted
-}
diff --git a/tests/ui/imports/ambiguous-4.stderr b/tests/ui/imports/ambiguous-4.stderr
deleted file mode 100644
index 0d20766..0000000
--- a/tests/ui/imports/ambiguous-4.stderr
+++ /dev/null
@@ -1,49 +0,0 @@
-error: `id` is ambiguous
-  --> $DIR/ambiguous-4.rs:7:25
-   |
-LL |     ambiguous_4_extern::id();
-   |                         ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-4-extern.rs:13:9
-   |
-LL | pub use evp::*;
-   |         ^^^
-   = help: consider updating this dependency to resolve this error
-   = help: if updating the dependency does not resolve the problem report the problem to the author of the relevant crate
-note: `id` could also refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-4-extern.rs:14:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
-error: aborting due to 1 previous error
-
-Future incompatibility report: Future breakage diagnostic:
-error: `id` is ambiguous
-  --> $DIR/ambiguous-4.rs:7:25
-   |
-LL |     ambiguous_4_extern::id();
-   |                         ^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `id` could refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-4-extern.rs:13:9
-   |
-LL | pub use evp::*;
-   |         ^^^
-   = help: consider updating this dependency to resolve this error
-   = help: if updating the dependency does not resolve the problem report the problem to the author of the relevant crate
-note: `id` could also refer to the function defined here
-  --> $DIR/auxiliary/../ambiguous-4-extern.rs:14:9
-   |
-LL | pub use handwritten::*;
-   |         ^^^^^^^^^^^
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
diff --git a/tests/ui/imports/ambiguous-5.rs b/tests/ui/imports/ambiguous-5.rs
index 8f89c96..a88dbf4 100644
--- a/tests/ui/imports/ambiguous-5.rs
+++ b/tests/ui/imports/ambiguous-5.rs
@@ -11,7 +11,6 @@ mod gpos {
     use super::*;
     struct MarkRecord(Class);
     //~^ ERROR`Class` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 mod gsubgpos {
diff --git a/tests/ui/imports/ambiguous-5.stderr b/tests/ui/imports/ambiguous-5.stderr
index 8cc37c6..e2dfe4d 100644
--- a/tests/ui/imports/ambiguous-5.stderr
+++ b/tests/ui/imports/ambiguous-5.stderr
@@ -1,4 +1,4 @@
-error: `Class` is ambiguous
+error[E0659]: `Class` is ambiguous
   --> $DIR/ambiguous-5.rs:12:23
    |
 LL |     struct MarkRecord(Class);
@@ -17,33 +17,7 @@
 LL |     use super::gsubgpos::*;
    |         ^^^^^^^^^^^^^^^^^^
    = help: consider adding an explicit import of `Class` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `Class` is ambiguous
-  --> $DIR/ambiguous-5.rs:12:23
-   |
-LL |     struct MarkRecord(Class);
-   |                       ^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `Class` could refer to the struct imported here
-  --> $DIR/ambiguous-5.rs:11:9
-   |
-LL |     use super::*;
-   |         ^^^^^^^^
-   = help: consider adding an explicit import of `Class` to disambiguate
-note: `Class` could also refer to the struct imported here
-  --> $DIR/ambiguous-5.rs:10:9
-   |
-LL |     use super::gsubgpos::*;
-   |         ^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `Class` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-6.rs b/tests/ui/imports/ambiguous-6.rs
index 1c6e343..71667a8 100644
--- a/tests/ui/imports/ambiguous-6.rs
+++ b/tests/ui/imports/ambiguous-6.rs
@@ -5,7 +5,6 @@ pub fn foo() -> u32 {
     use sub::*;
     C
     //~^ ERROR `C` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 mod sub {
diff --git a/tests/ui/imports/ambiguous-6.stderr b/tests/ui/imports/ambiguous-6.stderr
index ea5b2d2..f1a4fb6 100644
--- a/tests/ui/imports/ambiguous-6.stderr
+++ b/tests/ui/imports/ambiguous-6.stderr
@@ -1,4 +1,4 @@
-error: `C` is ambiguous
+error[E0659]: `C` is ambiguous
   --> $DIR/ambiguous-6.rs:6:5
    |
 LL |     C
@@ -6,44 +6,18 @@
    |
    = note: ambiguous because of multiple glob imports of a name in the same module
 note: `C` could refer to the constant imported here
-  --> $DIR/ambiguous-6.rs:15:13
+  --> $DIR/ambiguous-6.rs:14:13
    |
 LL |     pub use mod1::*;
    |             ^^^^^^^
    = help: consider adding an explicit import of `C` to disambiguate
 note: `C` could also refer to the constant imported here
-  --> $DIR/ambiguous-6.rs:16:13
+  --> $DIR/ambiguous-6.rs:15:13
    |
 LL |     pub use mod2::*;
    |             ^^^^^^^
    = help: consider adding an explicit import of `C` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 error: aborting due to 1 previous error
 
-Future incompatibility report: Future breakage diagnostic:
-error: `C` is ambiguous
-  --> $DIR/ambiguous-6.rs:6:5
-   |
-LL |     C
-   |     ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `C` could refer to the constant imported here
-  --> $DIR/ambiguous-6.rs:15:13
-   |
-LL |     pub use mod1::*;
-   |             ^^^^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-note: `C` could also refer to the constant imported here
-  --> $DIR/ambiguous-6.rs:16:13
-   |
-LL |     pub use mod2::*;
-   |             ^^^^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-9.rs b/tests/ui/imports/ambiguous-9.rs
index c10b126..5879603 100644
--- a/tests/ui/imports/ambiguous-9.rs
+++ b/tests/ui/imports/ambiguous-9.rs
@@ -22,7 +22,5 @@ pub fn date_range() {}
 fn main() {
     date_range();
     //~^ ERROR `date_range` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     //~| ERROR `date_range` is ambiguous
-    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr
index bbbce63..b6e4c30 100644
--- a/tests/ui/imports/ambiguous-9.stderr
+++ b/tests/ui/imports/ambiguous-9.stderr
@@ -1,3 +1,43 @@
+error[E0659]: `date_range` is ambiguous
+  --> $DIR/ambiguous-9.rs:23:5
+   |
+LL |     date_range();
+   |     ^^^^^^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `date_range` could refer to the function imported here
+  --> $DIR/ambiguous-9.rs:19:5
+   |
+LL | use dsl::*;
+   |     ^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+note: `date_range` could also refer to the function imported here
+  --> $DIR/ambiguous-9.rs:20:5
+   |
+LL | use prelude::*;
+   |     ^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+
+error[E0659]: `date_range` is ambiguous
+  --> $DIR/ambiguous-9.rs:23:5
+   |
+LL |     date_range();
+   |     ^^^^^^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `date_range` could refer to the function imported here
+  --> $DIR/ambiguous-9.rs:7:13
+   |
+LL |     pub use self::range::*;
+   |             ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+note: `date_range` could also refer to the function imported here
+  --> $DIR/ambiguous-9.rs:8:9
+   |
+LL |     use super::prelude::*;
+   |         ^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+
 warning: ambiguous glob re-exports
   --> $DIR/ambiguous-9.rs:7:13
    |
@@ -8,29 +48,6 @@
    |
    = note: `#[warn(ambiguous_glob_reexports)]` on by default
 
-error: `date_range` is ambiguous
-  --> $DIR/ambiguous-9.rs:23:5
-   |
-LL |     date_range();
-   |     ^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `date_range` could refer to the function imported here
-  --> $DIR/ambiguous-9.rs:7:13
-   |
-LL |     pub use self::range::*;
-   |             ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-note: `date_range` could also refer to the function imported here
-  --> $DIR/ambiguous-9.rs:8:9
-   |
-LL |     use super::prelude::*;
-   |         ^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
 warning: ambiguous glob re-exports
   --> $DIR/ambiguous-9.rs:15:13
    |
@@ -39,75 +56,6 @@
 LL |     pub use super::dsl::*;
    |             ------------- but the name `date_range` in the value namespace is also re-exported here
 
-error: `date_range` is ambiguous
-  --> $DIR/ambiguous-9.rs:23:5
-   |
-LL |     date_range();
-   |     ^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `date_range` could refer to the function imported here
-  --> $DIR/ambiguous-9.rs:19:5
-   |
-LL | use dsl::*;
-   |     ^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-note: `date_range` could also refer to the function imported here
-  --> $DIR/ambiguous-9.rs:20:5
-   |
-LL | use prelude::*;
-   |     ^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-
 error: aborting due to 2 previous errors; 2 warnings emitted
 
-Future incompatibility report: Future breakage diagnostic:
-error: `date_range` is ambiguous
-  --> $DIR/ambiguous-9.rs:23:5
-   |
-LL |     date_range();
-   |     ^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `date_range` could refer to the function imported here
-  --> $DIR/ambiguous-9.rs:7:13
-   |
-LL |     pub use self::range::*;
-   |             ^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-note: `date_range` could also refer to the function imported here
-  --> $DIR/ambiguous-9.rs:8:9
-   |
-LL |     use super::prelude::*;
-   |         ^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
-error: `date_range` is ambiguous
-  --> $DIR/ambiguous-9.rs:23:5
-   |
-LL |     date_range();
-   |     ^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `date_range` could refer to the function imported here
-  --> $DIR/ambiguous-9.rs:19:5
-   |
-LL | use dsl::*;
-   |     ^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-note: `date_range` could also refer to the function imported here
-  --> $DIR/ambiguous-9.rs:20:5
-   |
-LL | use prelude::*;
-   |     ^^^^^^^^^^
-   = help: consider adding an explicit import of `date_range` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-panic-globvsglob.rs b/tests/ui/imports/ambiguous-panic-globvsglob.rs
index 4ff3cc8..4b35d60 100644
--- a/tests/ui/imports/ambiguous-panic-globvsglob.rs
+++ b/tests/ui/imports/ambiguous-panic-globvsglob.rs
@@ -18,6 +18,5 @@ fn foo() {
     panic!();
     //~^ WARN: `panic` is ambiguous [ambiguous_panic_imports]
     //~| WARN: this was previously accepted by the compiler
-    //~| ERROR: `panic` is ambiguous [ambiguous_glob_imports]
-    //~| WARN: this was previously accepted by the compiler
+    //~| ERROR: `panic` is ambiguous
 }
diff --git a/tests/ui/imports/ambiguous-panic-globvsglob.stderr b/tests/ui/imports/ambiguous-panic-globvsglob.stderr
index 981c9b0..8fd7852 100644
--- a/tests/ui/imports/ambiguous-panic-globvsglob.stderr
+++ b/tests/ui/imports/ambiguous-panic-globvsglob.stderr
@@ -1,4 +1,4 @@
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/ambiguous-panic-globvsglob.rs:18:5
    |
 LL |     panic!();
@@ -17,9 +17,6 @@
 LL |     use m2::*;
    |         ^^^^^
    = help: consider adding an explicit import of `panic` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
 warning: `panic` is ambiguous
   --> $DIR/ambiguous-panic-globvsglob.rs:18:5
@@ -42,27 +39,4 @@
 
 error: aborting due to 1 previous error; 1 warning emitted
 
-Future incompatibility report: Future breakage diagnostic:
-error: `panic` is ambiguous
-  --> $DIR/ambiguous-panic-globvsglob.rs:18:5
-   |
-LL |     panic!();
-   |     ^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `panic` could refer to the macro imported here
-  --> $DIR/ambiguous-panic-globvsglob.rs:12:9
-   |
-LL |     use m1::*;
-   |         ^^^^^
-   = help: consider adding an explicit import of `panic` to disambiguate
-note: `panic` could also refer to the macro imported here
-  --> $DIR/ambiguous-panic-globvsglob.rs:13:9
-   |
-LL |     use m2::*;
-   |         ^^^^^
-   = help: consider adding an explicit import of `panic` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/glob-conflict-cross-crate-3.rs b/tests/ui/imports/glob-conflict-cross-crate-3.rs
index 31c234b..74415cf 100644
--- a/tests/ui/imports/glob-conflict-cross-crate-3.rs
+++ b/tests/ui/imports/glob-conflict-cross-crate-3.rs
@@ -14,5 +14,4 @@ fn main() {
     //~^ ERROR `C` is ambiguous
     //~| ERROR `C` is ambiguous
     //~| WARN this was previously accepted
-    //~| WARN this was previously accepted
 }
diff --git a/tests/ui/imports/glob-conflict-cross-crate-3.stderr b/tests/ui/imports/glob-conflict-cross-crate-3.stderr
index 8a9ece9..50a9adc 100644
--- a/tests/ui/imports/glob-conflict-cross-crate-3.stderr
+++ b/tests/ui/imports/glob-conflict-cross-crate-3.stderr
@@ -1,3 +1,23 @@
+error[E0659]: `C` is ambiguous
+  --> $DIR/glob-conflict-cross-crate-3.rs:13:13
+   |
+LL |     let _a: C = 1;
+   |             ^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `C` could refer to the type alias imported here
+  --> $DIR/glob-conflict-cross-crate-3.rs:9:5
+   |
+LL | use glob_conflict_cross_crate_2_extern::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `C` to disambiguate
+note: `C` could also refer to the type alias imported here
+  --> $DIR/glob-conflict-cross-crate-3.rs:10:5
+   |
+LL | use a::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `C` to disambiguate
+
 error: `C` is ambiguous
   --> $DIR/glob-conflict-cross-crate-3.rs:13:13
    |
@@ -21,30 +41,9 @@
    = note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
    = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
-error: `C` is ambiguous
-  --> $DIR/glob-conflict-cross-crate-3.rs:13:13
-   |
-LL |     let _a: C = 1;
-   |             ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `C` could refer to the type alias imported here
-  --> $DIR/glob-conflict-cross-crate-3.rs:9:5
-   |
-LL | use glob_conflict_cross_crate_2_extern::*;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-note: `C` could also refer to the type alias imported here
-  --> $DIR/glob-conflict-cross-crate-3.rs:10:5
-   |
-LL | use a::*;
-   |     ^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0659`.
 Future incompatibility report: Future breakage diagnostic:
 error: `C` is ambiguous
   --> $DIR/glob-conflict-cross-crate-3.rs:13:13
@@ -69,27 +68,3 @@
    = note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
    = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
-Future breakage diagnostic:
-error: `C` is ambiguous
-  --> $DIR/glob-conflict-cross-crate-3.rs:13:13
-   |
-LL |     let _a: C = 1;
-   |             ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `C` could refer to the type alias imported here
-  --> $DIR/glob-conflict-cross-crate-3.rs:9:5
-   |
-LL | use glob_conflict_cross_crate_2_extern::*;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-note: `C` could also refer to the type alias imported here
-  --> $DIR/glob-conflict-cross-crate-3.rs:10:5
-   |
-LL | use a::*;
-   |     ^^^^
-   = help: consider adding an explicit import of `C` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.rs b/tests/ui/imports/unresolved-seg-after-ambiguous.rs
index 67366de..00a3c5b 100644
--- a/tests/ui/imports/unresolved-seg-after-ambiguous.rs
+++ b/tests/ui/imports/unresolved-seg-after-ambiguous.rs
@@ -17,8 +17,6 @@ mod d {
 }
 
 use self::a::E::in_exist;
-//~^ ERROR: unresolved import `self::a::E`
-//~| ERROR: `E` is ambiguous
-//~| WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~^ ERROR: `E` is ambiguous
 
 fn main() {}
diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.stderr b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr
index c21faff..e712d80 100644
--- a/tests/ui/imports/unresolved-seg-after-ambiguous.stderr
+++ b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr
@@ -1,10 +1,4 @@
-error[E0432]: unresolved import `self::a::E`
-  --> $DIR/unresolved-seg-after-ambiguous.rs:19:14
-   |
-LL | use self::a::E::in_exist;
-   |              ^ `E` is a struct, not a module
-
-error: `E` is ambiguous
+error[E0659]: `E` is ambiguous
   --> $DIR/unresolved-seg-after-ambiguous.rs:19:14
    |
 LL | use self::a::E::in_exist;
@@ -23,34 +17,7 @@
 LL |         pub use self::d::*;
    |                 ^^^^^^^^^^
    = help: consider adding an explicit import of `E` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0432`.
-Future incompatibility report: Future breakage diagnostic:
-error: `E` is ambiguous
-  --> $DIR/unresolved-seg-after-ambiguous.rs:19:14
-   |
-LL | use self::a::E::in_exist;
-   |              ^ ambiguous name
-   |
-   = note: ambiguous because of multiple glob imports of a name in the same module
-note: `E` could refer to the struct imported here
-  --> $DIR/unresolved-seg-after-ambiguous.rs:13:17
-   |
-LL |         pub use self::c::*;
-   |                 ^^^^^^^^^^
-   = help: consider adding an explicit import of `E` to disambiguate
-note: `E` could also refer to the struct imported here
-  --> $DIR/unresolved-seg-after-ambiguous.rs:12:17
-   |
-LL |         pub use self::d::*;
-   |                 ^^^^^^^^^^
-   = help: consider adding an explicit import of `E` to disambiguate
-   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
-   = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/issues/.gitattributes b/tests/ui/issues/.gitattributes
deleted file mode 100644
index 4517a4a..0000000
--- a/tests/ui/issues/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-issue-16278.rs -text
diff --git a/tests/ui/issues/issue-16643.rs b/tests/ui/issues/issue-16643.rs
deleted file mode 100644
index 6cef11f..0000000
--- a/tests/ui/issues/issue-16643.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ run-pass
-//@ aux-build:issue-16643.rs
-
-
-extern crate issue_16643 as i;
-
-pub fn main() {
-    i::TreeBuilder { h: 3 }.process_token();
-}
diff --git a/tests/ui/lexer/.gitattributes b/tests/ui/lexer/.gitattributes
new file mode 100644
index 0000000..e09c7e6
--- /dev/null
+++ b/tests/ui/lexer/.gitattributes
@@ -0,0 +1 @@
+crlf-in-byte-string-literal.rs -text
diff --git a/tests/ui/issues/issue-16278.rs b/tests/ui/lexer/crlf-in-byte-string-literal.rs
similarity index 71%
rename from tests/ui/issues/issue-16278.rs
rename to tests/ui/lexer/crlf-in-byte-string-literal.rs
index 0d3b4a9..1290133 100644
--- a/tests/ui/issues/issue-16278.rs
+++ b/tests/ui/lexer/crlf-in-byte-string-literal.rs
@@ -1,3 +1,5 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16278>.
+
 //@ run-pass
 // ignore-tidy-cr
 
diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr
index fdc644e..2605305 100644
--- a/tests/ui/link-native-libs/issue-43925.stderr
+++ b/tests/ui/link-native-libs/issue-43925.stderr
@@ -7,7 +7,7 @@
    = help: add `#![feature(link_cfg)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0539]: malformed `link` attribute input
+error[E0565]: malformed `link` attribute input
   --> $DIR/issue-43925.rs:1:1
    |
 LL | #[link(name = "foo", cfg("rlib"))]
@@ -19,5 +19,5 @@
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0539, E0658.
-For more information about an error, try `rustc --explain E0539`.
+Some errors have detailed explanations: E0565, E0658.
+For more information about an error, try `rustc --explain E0565`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr
index 4a4a193..50bed93 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr
@@ -148,7 +148,7 @@
    |
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
 
-error[E0539]: malformed `link` attribute input
+error[E0565]: malformed `link` attribute input
   --> $DIR/link-attr-validation-late.rs:25:1
    |
 LL | #[link(name = "...", cfg("literal"))]
diff --git a/tests/ui/linkage-attr/unstable-flavor.llbc.stderr b/tests/ui/linkage-attr/unstable-flavor.llbc.stderr
new file mode 100644
index 0000000..796daa4
--- /dev/null
+++ b/tests/ui/linkage-attr/unstable-flavor.llbc.stderr
@@ -0,0 +1,2 @@
+error: the linker flavor `llbc` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values
+
diff --git a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr
deleted file mode 100644
index 2ebdc1a..0000000
--- a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the linker flavor `ptx` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values
-
diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs
index 5412e24..adb34a9 100644
--- a/tests/ui/linkage-attr/unstable-flavor.rs
+++ b/tests/ui/linkage-attr/unstable-flavor.rs
@@ -2,14 +2,14 @@
 // unique codepath checking all unstable options (see `LinkerFlavorCli::is_unstable` and its
 // caller). If it passes, all the other unstable options are rejected as well.
 //
-//@ revisions: bpf ptx
+//@ revisions: bpf llbc
 //@ [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib
 //@ [bpf] needs-llvm-components: bpf
-//@ [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib
-//@ [ptx] needs-llvm-components: nvptx
+//@ [llbc] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=llbc --crate-type=rlib
+//@ [llbc] needs-llvm-components: nvptx
 
 #![feature(no_core)]
 #![no_core]
 
 //[bpf]~? ERROR the linker flavor `bpf` is unstable
-//[ptx]~? ERROR the linker flavor `ptx` is unstable
+//[llbc]~? ERROR the linker flavor `llbc` is unstable
diff --git a/tests/ui/lint/unused/unused-assign-148960.rs b/tests/ui/lint/unused/unused-assign-148960.rs
index 2e51c01..b7e129a 100644
--- a/tests/ui/lint/unused/unused-assign-148960.rs
+++ b/tests/ui/lint/unused/unused-assign-148960.rs
@@ -1,4 +1,5 @@
 //@ check-fail
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![deny(unused)]
 #![allow(dead_code)]
 
diff --git a/tests/ui/lint/unused/unused-assign-148960.stderr b/tests/ui/lint/unused/unused-assign-148960.stderr
index aa5326c..60966be 100644
--- a/tests/ui/lint/unused/unused-assign-148960.stderr
+++ b/tests/ui/lint/unused/unused-assign-148960.stderr
@@ -1,5 +1,5 @@
 error: value assigned to `value` is never read
-  --> $DIR/unused-assign-148960.rs:6:21
+  --> $DIR/unused-assign-148960.rs:7:21
    |
 LL |     let mut value = b"0".to_vec();
    |                     ^^^^^^^^^^^^^ this value is reassigned later and never used
@@ -7,14 +7,14 @@
    |     ----- `value` is overwritten here before the previous value is read
    |
 note: the lint level is defined here
-  --> $DIR/unused-assign-148960.rs:2:9
+  --> $DIR/unused-assign-148960.rs:3:9
    |
 LL | #![deny(unused)]
    |         ^^^^^^
    = note: `#[deny(unused_assignments)]` implied by `#[deny(unused)]`
 
 error: value assigned to `x` is never read
-  --> $DIR/unused-assign-148960.rs:12:17
+  --> $DIR/unused-assign-148960.rs:13:17
    |
 LL |     let mut x = 1;
    |                 ^ this value is reassigned later and never used
@@ -22,7 +22,7 @@
    |     ----- `x` is overwritten here before the previous value is read
 
 error: value assigned to `x` is never read
-  --> $DIR/unused-assign-148960.rs:13:5
+  --> $DIR/unused-assign-148960.rs:14:5
    |
 LL |     x = 2;
    |     ^^^^^ this value is reassigned later and never used
@@ -30,7 +30,7 @@
    |     ----- `x` is overwritten here before the previous value is read
 
 error: value assigned to `p` is never read
-  --> $DIR/unused-assign-148960.rs:24:17
+  --> $DIR/unused-assign-148960.rs:25:17
    |
 LL |     let mut p = Point { x: 1, y: 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^ this value is reassigned later and never used
@@ -38,7 +38,7 @@
    |     ------------------------ `p` is overwritten here before the previous value is read
 
 error: variable `foo` is assigned to, but never used
-  --> $DIR/unused-assign-148960.rs:38:9
+  --> $DIR/unused-assign-148960.rs:39:9
    |
 LL |     let mut foo = Foo;
    |         ^^^^^^^
@@ -52,7 +52,7 @@
    |
 
 error: value assigned to `foo` is never read
-  --> $DIR/unused-assign-148960.rs:39:5
+  --> $DIR/unused-assign-148960.rs:40:5
    |
 LL |     foo = Foo;
    |     ^^^
diff --git a/tests/ui/liveness/liveness-consts.rs b/tests/ui/liveness/liveness-consts.rs
index 7e56bf8..b239e12 100644
--- a/tests/ui/liveness/liveness-consts.rs
+++ b/tests/ui/liveness/liveness-consts.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![warn(unused)]
 #![allow(unreachable_code)]
 
diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr
index 6b4acf1..f4a5b82 100644
--- a/tests/ui/liveness/liveness-consts.stderr
+++ b/tests/ui/liveness/liveness-consts.stderr
@@ -1,30 +1,30 @@
 warning: unused variable: `e`
-  --> $DIR/liveness-consts.rs:26:13
+  --> $DIR/liveness-consts.rs:27:13
    |
 LL |         let e = 1;
    |             ^ help: if this is intentional, prefix it with an underscore: `_e`
    |
 note: the lint level is defined here
-  --> $DIR/liveness-consts.rs:2:9
+  --> $DIR/liveness-consts.rs:3:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: unused variable: `s`
-  --> $DIR/liveness-consts.rs:35:24
+  --> $DIR/liveness-consts.rs:36:24
    |
 LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
    |                        ^ help: if this is intentional, prefix it with an underscore: `_s`
 
 warning: unused variable: `z`
-  --> $DIR/liveness-consts.rs:35:55
+  --> $DIR/liveness-consts.rs:36:55
    |
 LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
    |                                                       ^ help: if this is intentional, prefix it with an underscore: `_z`
 
 warning: variable `a` is assigned to, but never used
-  --> $DIR/liveness-consts.rs:7:9
+  --> $DIR/liveness-consts.rs:8:9
    |
 LL |     let mut a = 0;
    |         ^^^^^
@@ -32,7 +32,7 @@
    = note: consider using `_a` instead
 
 warning: value assigned to `a` is never read
-  --> $DIR/liveness-consts.rs:11:9
+  --> $DIR/liveness-consts.rs:12:9
    |
 LL |         a += 1;
    |         ^^^^^^
@@ -41,7 +41,7 @@
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness-consts.rs:18:17
+  --> $DIR/liveness-consts.rs:19:17
    |
 LL |     let mut b = 1;
    |                 ^ this value is reassigned later and never used
@@ -49,7 +49,7 @@
    |     ------ `b` is overwritten here before the previous value is read
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness-consts.rs:19:5
+  --> $DIR/liveness-consts.rs:20:5
    |
 LL |     b += 1;
    |     ^^^^^^ this value is reassigned later and never used
@@ -57,13 +57,13 @@
    |     ------ `b` is overwritten here before the previous value is read
 
 warning: unused variable: `z`
-  --> $DIR/liveness-consts.rs:62:13
+  --> $DIR/liveness-consts.rs:63:13
    |
 LL |         let z = 42;
    |             ^ help: if this is intentional, prefix it with an underscore: `_z`
 
 warning: value assigned to `t` is never read
-  --> $DIR/liveness-consts.rs:44:9
+  --> $DIR/liveness-consts.rs:45:9
    |
 LL |         t = t + t;
    |         ^^^^^^^^^
@@ -71,7 +71,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `w`
-  --> $DIR/liveness-consts.rs:51:13
+  --> $DIR/liveness-consts.rs:52:13
    |
 LL |         let w = 10;
    |             ^ help: if this is intentional, prefix it with an underscore: `_w`
diff --git a/tests/ui/liveness/liveness-dead.rs b/tests/ui/liveness/liveness-dead.rs
index 004663c8..c48b28e 100644
--- a/tests/ui/liveness/liveness-dead.rs
+++ b/tests/ui/liveness/liveness-dead.rs
@@ -1,3 +1,4 @@
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![allow(dead_code)]
 #![deny(unused_assignments)]
 
diff --git a/tests/ui/liveness/liveness-dead.stderr b/tests/ui/liveness/liveness-dead.stderr
index ade0e04..2288fae 100644
--- a/tests/ui/liveness/liveness-dead.stderr
+++ b/tests/ui/liveness/liveness-dead.stderr
@@ -1,5 +1,5 @@
 error: value assigned to `x` is never read
-  --> $DIR/liveness-dead.rs:9:24
+  --> $DIR/liveness-dead.rs:10:24
    |
 LL |     let mut x: isize = 3;
    |                        ^ this value is reassigned later and never used
@@ -7,13 +7,13 @@
    |     ----- `x` is overwritten here before the previous value is read
    |
 note: the lint level is defined here
-  --> $DIR/liveness-dead.rs:2:9
+  --> $DIR/liveness-dead.rs:3:9
    |
 LL | #![deny(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
 
 error: value assigned to `x` is never read
-  --> $DIR/liveness-dead.rs:17:5
+  --> $DIR/liveness-dead.rs:18:5
    |
 LL |     x = 4;
    |     ^^^^^
@@ -21,7 +21,7 @@
    = help: maybe it is overwritten before being read?
 
 error: value passed to `x` is never read
-  --> $DIR/liveness-dead.rs:20:7
+  --> $DIR/liveness-dead.rs:21:7
    |
 LL | fn f4(mut x: i32) {
    |       ^^^^^
@@ -29,7 +29,7 @@
    = help: maybe it is overwritten before being read?
 
 error: value assigned to `x` is never read
-  --> $DIR/liveness-dead.rs:27:5
+  --> $DIR/liveness-dead.rs:28:5
    |
 LL |     x = 4;
    |     ^^^^^
diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs
index be58b48..1a3d0e5 100644
--- a/tests/ui/liveness/liveness-upvars.rs
+++ b/tests/ui/liveness/liveness-upvars.rs
@@ -1,5 +1,6 @@
 //@ edition:2018
 //@ check-pass
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![feature(coroutines, stmt_expr_attributes)]
 #![warn(unused)]
 #![allow(unreachable_code)]
diff --git a/tests/ui/liveness/liveness-upvars.stderr b/tests/ui/liveness/liveness-upvars.stderr
index 96a9227..b569acd 100644
--- a/tests/ui/liveness/liveness-upvars.stderr
+++ b/tests/ui/liveness/liveness-upvars.stderr
@@ -1,19 +1,19 @@
 warning: value captured by `last` is never read
-  --> $DIR/liveness-upvars.rs:10:9
+  --> $DIR/liveness-upvars.rs:11:9
    |
 LL |         last = Some(s);
    |         ^^^^
    |
    = help: did you mean to capture by reference instead?
 note: the lint level is defined here
-  --> $DIR/liveness-upvars.rs:4:9
+  --> $DIR/liveness-upvars.rs:5:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
 
 warning: value assigned to `last` is never read
-  --> $DIR/liveness-upvars.rs:10:9
+  --> $DIR/liveness-upvars.rs:11:9
    |
 LL |         last = Some(s);
    |         ^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `sum` is never read
-  --> $DIR/liveness-upvars.rs:22:9
+  --> $DIR/liveness-upvars.rs:23:9
    |
 LL |         sum += x;
    |         ^^^
@@ -29,7 +29,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `sum` is never read
-  --> $DIR/liveness-upvars.rs:22:9
+  --> $DIR/liveness-upvars.rs:23:9
    |
 LL |         sum += x;
    |         ^^^^^^^^
@@ -37,7 +37,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:69:9
+  --> $DIR/liveness-upvars.rs:70:9
    |
 LL |         c += 1;
    |         ^^^^^^
@@ -45,7 +45,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:63:9
+  --> $DIR/liveness-upvars.rs:64:9
    |
 LL |         c += 1;
    |         ^^^^^^
@@ -53,7 +53,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:49:9
+  --> $DIR/liveness-upvars.rs:50:9
    |
 LL |         c += 1;
    |         ^
@@ -61,7 +61,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:49:9
+  --> $DIR/liveness-upvars.rs:50:9
    |
 LL |         c += 1;
    |         ^^^^^^
@@ -69,7 +69,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:44:9
+  --> $DIR/liveness-upvars.rs:45:9
    |
 LL |         c += 1;
    |         ^
@@ -77,7 +77,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:44:9
+  --> $DIR/liveness-upvars.rs:45:9
    |
 LL |         c += 1;
    |         ^^^^^^
@@ -85,7 +85,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:38:9
+  --> $DIR/liveness-upvars.rs:39:9
    |
 LL |         c = 1;
    |         ^
@@ -93,7 +93,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:34:9
+  --> $DIR/liveness-upvars.rs:35:9
    |
 LL |         c = 1;
    |         ^
@@ -101,7 +101,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value captured by `e` is never read
-  --> $DIR/liveness-upvars.rs:82:13
+  --> $DIR/liveness-upvars.rs:83:13
    |
 LL |             e = Some("e1");
    |             ^
@@ -109,7 +109,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `e` is never read
-  --> $DIR/liveness-upvars.rs:82:13
+  --> $DIR/liveness-upvars.rs:83:13
    |
 LL |             e = Some("e1");
    |             ^^^^^^^^^^^^^^ this value is reassigned later and never used
@@ -118,7 +118,7 @@
    |             -------------- `e` is overwritten here before the previous value is read
 
 warning: value assigned to `e` is never read
-  --> $DIR/liveness-upvars.rs:84:13
+  --> $DIR/liveness-upvars.rs:85:13
    |
 LL |             e = Some("e2");
    |             ^^^^^^^^^^^^^^
@@ -126,7 +126,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `d` is never read
-  --> $DIR/liveness-upvars.rs:78:13
+  --> $DIR/liveness-upvars.rs:79:13
    |
 LL |             d = Some("d1");
    |             ^^^^^^^^^^^^^^ this value is reassigned later and never used
@@ -134,7 +134,7 @@
    |             -------------- `d` is overwritten here before the previous value is read
 
 warning: value assigned to `v` is never read
-  --> $DIR/liveness-upvars.rs:92:13
+  --> $DIR/liveness-upvars.rs:93:13
    |
 LL |             v = T::default();
    |             ^
@@ -142,7 +142,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `z` is never read
-  --> $DIR/liveness-upvars.rs:105:17
+  --> $DIR/liveness-upvars.rs:106:17
    |
 LL |                 z = T::default();
    |                 ^
@@ -150,7 +150,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `z` is never read
-  --> $DIR/liveness-upvars.rs:105:17
+  --> $DIR/liveness-upvars.rs:106:17
    |
 LL |                 z = T::default();
    |                 ^^^^^^^^^^^^^^^^
@@ -158,7 +158,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value captured by `state` is never read
-  --> $DIR/liveness-upvars.rs:131:9
+  --> $DIR/liveness-upvars.rs:132:9
    |
 LL |         state = 4;
    |         ^^^^^
@@ -166,7 +166,7 @@
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `state` is never read
-  --> $DIR/liveness-upvars.rs:131:9
+  --> $DIR/liveness-upvars.rs:132:9
    |
 LL |         state = 4;
    |         ^^^^^^^^^ this value is reassigned later and never used
@@ -175,7 +175,7 @@
    |         --------- `state` is overwritten here before the previous value is read
 
 warning: value assigned to `state` is never read
-  --> $DIR/liveness-upvars.rs:134:9
+  --> $DIR/liveness-upvars.rs:135:9
    |
 LL |         state = 5;
    |         ^^^^^^^^^
@@ -183,7 +183,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `s` is never read
-  --> $DIR/liveness-upvars.rs:143:9
+  --> $DIR/liveness-upvars.rs:144:9
    |
 LL |         s = 1;
    |         ^^^^^ this value is reassigned later and never used
@@ -191,7 +191,7 @@
    |               ------- `s` is overwritten here before the previous value is read
 
 warning: value assigned to `s` is never read
-  --> $DIR/liveness-upvars.rs:145:9
+  --> $DIR/liveness-upvars.rs:146:9
    |
 LL |         s = yield ();
    |         ^^^^^^^^^^^^ this value is reassigned later and never used
diff --git a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs
index 08cffa0..d1fb55d 100644
--- a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs
+++ b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+//@ ignore-parallel-frontend unstable liveness diagnostics
 #![allow(dead_code)]
 #![warn(unused_assignments)]
 
diff --git a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr
index 5afb336..4ec4a3d 100644
--- a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr
+++ b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr
@@ -1,18 +1,18 @@
 warning: value assigned to `x` is never read
-  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:10:9
+  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:11:9
    |
 LL |         x = 35;
    |         ^^^^^^
    |
    = help: maybe it is overwritten before being read?
 note: the lint level is defined here
-  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:3:9
+  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:4:9
    |
 LL | #![warn(unused_assignments)]
    |         ^^^^^^^^^^^^^^^^^^
 
 warning: value assigned to `x` is never read
-  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:21:13
+  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:22:13
    |
 LL |             x = 35;
    |             ^^^^^^
@@ -20,7 +20,7 @@
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `x` is never read
-  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:36:9
+  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:37:9
    |
 LL |         x = 42;
    |         ^^^^^^ this value is reassigned later and never used
@@ -29,7 +29,7 @@
    |     ------ `x` is overwritten here before the previous value is read
 
 warning: value assigned to `x` is never read
-  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:33:9
+  --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:34:9
    |
 LL |         x = 35;
    |         ^^^^^^ this value is reassigned later and never used
diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr
index d5dee81..a5ee463 100644
--- a/tests/ui/macros/cfg.stderr
+++ b/tests/ui/macros/cfg.stderr
@@ -4,7 +4,7 @@
 LL |     cfg!();
    |     ^^^^^^ cfg-pattern required
 
-error[E0539]: malformed `cfg` macro input
+error[E0565]: malformed `cfg` macro input
   --> $DIR/cfg.rs:3:5
    |
 LL |     cfg!(123);
@@ -53,4 +53,5 @@
 
 error: aborting due to 4 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0539`.
+Some errors have detailed explanations: E0539, E0565.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs
index 9fd92ad..99db268 100644
--- a/tests/ui/macros/cfg_select.rs
+++ b/tests/ui/macros/cfg_select.rs
@@ -178,12 +178,12 @@ fn b() {}
 
 cfg_select! {
     "str" => {}
-    //~^ ERROR malformed `cfg_select` macro input [E0539]
+    //~^ ERROR malformed `cfg_select` macro input [E0565]
 }
 
 cfg_select! {
     a::b => {}
-    //~^ ERROR malformed `cfg_select` macro input [E0539]
+    //~^ ERROR malformed `cfg_select` macro input [E0565]
 }
 
 cfg_select! {
diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr
index b8fbe10..e587161 100644
--- a/tests/ui/macros/cfg_select.stderr
+++ b/tests/ui/macros/cfg_select.stderr
@@ -25,13 +25,13 @@
 LL |     () => {}
    |     ^^ expressions are not allowed here
 
-error[E0539]: malformed `cfg_select` macro input
+error[E0565]: malformed `cfg_select` macro input
   --> $DIR/cfg_select.rs:180:5
    |
 LL |     "str" => {}
    |     ^^^^^ expected a valid identifier here
 
-error[E0539]: malformed `cfg_select` macro input
+error[E0565]: malformed `cfg_select` macro input
   --> $DIR/cfg_select.rs:185:5
    |
 LL |     a::b => {}
@@ -185,5 +185,5 @@
 
 error: aborting due to 17 previous errors; 7 warnings emitted
 
-Some errors have detailed explanations: E0537, E0539, E0753.
+Some errors have detailed explanations: E0537, E0565, E0753.
 For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/ui/macros/macro-comma-behavior.rs b/tests/ui/macros/macro-comma-behavior.rs
index f00d4d3..ea75fdd 100644
--- a/tests/ui/macros/macro-comma-behavior.rs
+++ b/tests/ui/macros/macro-comma-behavior.rs
@@ -10,7 +10,7 @@
 #[cfg(core)] use core::fmt;
 #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
 #[cfg(core)] #[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0;
-#[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
+#[cfg(core)] #[panic_handler] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
 
 // (see documentation of the similarly-named test in run-pass)
 fn to_format_or_not_to_format() {
diff --git a/tests/ui/issues/issue-17033.rs b/tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.rs
similarity index 73%
rename from tests/ui/issues/issue-17033.rs
rename to tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.rs
index b8eec3b..b7d20e7 100644
--- a/tests/ui/issues/issue-17033.rs
+++ b/tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.rs
@@ -1,3 +1,5 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/17033>.
+
 fn f<'r>(p: &'r mut fn(p: &mut ())) {
     (*p)(()) //~  ERROR mismatched types
              //~| NOTE expected `&mut ()`, found `()`
diff --git a/tests/ui/issues/issue-17033.stderr b/tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.stderr
similarity index 87%
rename from tests/ui/issues/issue-17033.stderr
rename to tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.stderr
index 0b42274..e7748e2 100644
--- a/tests/ui/issues/issue-17033.stderr
+++ b/tests/ui/mismatched_types/deref-fn-ptr-arg-type-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-17033.rs:2:10
+  --> $DIR/deref-fn-ptr-arg-type-mismatch.rs:4:10
    |
 LL |     (*p)(())
    |     ---- ^^ expected `&mut ()`, found `()`
diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 23bc9dc..ce63a69 100644
--- a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -4,7 +4,6 @@
 LL |     a.unwrap();
    |       ^^^^^^ the trait `Debug` is not implemented for `Foo`
    |
-   = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
 note: required by a bound in `Result::<T, E>::unwrap`
   --> $SRC_DIR/core/src/result.rs:LL:COL
 help: consider annotating `Foo` with `#[derive(Debug)]`
diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr
index 40dda93..d41fcce 100644
--- a/tests/ui/modules/issue-107649.stderr
+++ b/tests/ui/modules/issue-107649.stderr
@@ -4,7 +4,6 @@
 105 |     dbg!(lib::Dummy);
     |     ^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `Dummy`
     |
-    = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy`
 help: consider annotating `Dummy` with `#[derive(Debug)]`
    --> $DIR/auxiliary/dummy_lib.rs:2:1
     |
diff --git a/tests/ui/offset-of/inside-array-length.stderr b/tests/ui/offset-of/inside-array-length.stderr
index de11093..2d2ba87 100644
--- a/tests/ui/offset-of/inside-array-length.stderr
+++ b/tests/ui/offset-of/inside-array-length.stderr
@@ -53,7 +53,7 @@
    |
 LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {}
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}), args: ['^c_1, T/#1] }), bound_vars: [] }`...
+note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`...
   --> $DIR/inside-array-length.rs:9:27
    |
 LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {}
diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr
index 3c3b8d2..c078e0f 100644
--- a/tests/ui/on-unimplemented/no-debug.stderr
+++ b/tests/ui/on-unimplemented/no-debug.stderr
@@ -7,7 +7,6 @@
    |               required by this formatting parameter
    |
    = help: the trait `Debug` is not implemented for `Foo`
-   = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
 help: consider annotating `Foo` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
diff --git a/tests/ui/panic-handler/panic-handler-duplicate.rs b/tests/ui/panic-handler/panic-handler-duplicate.rs
index c0a7d6a..96a1115 100644
--- a/tests/ui/panic-handler/panic-handler-duplicate.rs
+++ b/tests/ui/panic-handler/panic-handler-duplicate.rs
@@ -11,7 +11,7 @@ fn panic(info: &PanicInfo) -> ! {
     loop {}
 }
 
-#[lang = "panic_impl"]
+#[panic_handler]
 fn panic2(info: &PanicInfo) -> ! { //~ ERROR found duplicate lang item `panic_impl`
     loop {}
 }
diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
index 938f6bc..44137b8 100644
--- a/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
+++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
@@ -7,7 +7,7 @@
 
 use core::panic::PanicInfo;
 
-#[lang = "panic_impl"]
+#[panic_handler]
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
diff --git a/tests/ui/parser/expr-as-stmt-2.stderr b/tests/ui/parser/expr-as-stmt-2.stderr
index f9838ee..3abb2b1 100644
--- a/tests/ui/parser/expr-as-stmt-2.stderr
+++ b/tests/ui/parser/expr-as-stmt-2.stderr
@@ -136,10 +136,6 @@
    |
 LL |     (if true { bar() } else { bar() }) && if true { bar() } else { bar() };
    |     +                                +
-help: consider using a semicolon here
-   |
-LL |     if true { bar() } else { bar() }; && if true { bar() } else { bar() };
-   |                                     +
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:24:30
@@ -154,46 +150,26 @@
    |
 LL |     (if true { bar() } else { bar() }) && if true { bar() } else { bar() };
    |     +                                +
-help: consider using a semicolon here
-   |
-LL |     if true { bar() } else { bar() }; && if true { bar() } else { bar() };
-   |                                     +
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:27:15
    |
 LL |     if true { bar() } else { bar() } if true { bar() } else { bar() };
    |     ----------^^^^^-----------------
-   |     |         |
+   |     |         |    |
+   |     |         |    help: consider using a semicolon here: `;`
    |     |         expected `()`, found `bool`
    |     expected this to be `()`
-   |
-help: consider using a semicolon here
-   |
-LL |     if true { bar(); } else { bar() } if true { bar() } else { bar() };
-   |                    +
-help: consider using a semicolon here
-   |
-LL |     if true { bar() } else { bar() }; if true { bar() } else { bar() };
-   |                                     +
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:27:30
    |
 LL |     if true { bar() } else { bar() } if true { bar() } else { bar() };
    |     -------------------------^^^^^--
-   |     |                        |
+   |     |                        |    |
+   |     |                        |    help: consider using a semicolon here: `;`
    |     |                        expected `()`, found `bool`
    |     expected this to be `()`
-   |
-help: consider using a semicolon here
-   |
-LL |     if true { bar() } else { bar(); } if true { bar() } else { bar() };
-   |                                   +
-help: consider using a semicolon here
-   |
-LL |     if true { bar() } else { bar() }; if true { bar() } else { bar() };
-   |                                     +
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
index 75a633c..d26ba93 100644
--- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:47:9
+  --> $DIR/empty-types.rs:48:9
    |
 LL |         _ => {}
    |         ^------
@@ -9,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:13:9
+  --> $DIR/empty-types.rs:14:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:50:9
+  --> $DIR/empty-types.rs:51:9
    |
 LL |         _x => {}
    |         ^^------
@@ -26,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:54:11
+  --> $DIR/empty-types.rs:55:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -41,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:68:9
+  --> $DIR/empty-types.rs:69:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -52,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:74:9
+  --> $DIR/empty-types.rs:75:9
    |
 LL |         _ => {}
    |         ^------
@@ -63,7 +63,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:77:9
+  --> $DIR/empty-types.rs:78:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -74,7 +74,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:81:9
+  --> $DIR/empty-types.rs:82:9
    |
 LL |         _ => {}
    |         ^------
@@ -85,7 +85,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:85:11
+  --> $DIR/empty-types.rs:86:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -104,7 +104,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:92:9
+  --> $DIR/empty-types.rs:93:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -115,7 +115,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:97:9
+  --> $DIR/empty-types.rs:98:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -126,7 +126,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:94:11
+  --> $DIR/empty-types.rs:95:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -144,7 +144,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:100:9
+  --> $DIR/empty-types.rs:101:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -158,7 +158,7 @@
    |                                         ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:110:9
+  --> $DIR/empty-types.rs:111:9
    |
 LL |         _ => {}
    |         ^------
@@ -169,18 +169,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:113:9
-   |
-LL |         Ok(_) => {}
-   |         ^^^^^------
-   |         |
-   |         matches no values because `Result<!, !>` is uninhabited
-   |         help: remove the match arm
-   |
-   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
-
-error: unreachable pattern
-  --> $DIR/empty-types.rs:116:9
+  --> $DIR/empty-types.rs:114:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -193,6 +182,17 @@
 error: unreachable pattern
   --> $DIR/empty-types.rs:117:9
    |
+LL |         Ok(_) => {}
+   |         ^^^^^------
+   |         |
+   |         matches no values because `Result<!, !>` is uninhabited
+   |         help: remove the match arm
+   |
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:118:9
+   |
 LL |         _ => {}
    |         ^------
    |         |
@@ -202,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:120:9
+  --> $DIR/empty-types.rs:121:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -213,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:121:9
+  --> $DIR/empty-types.rs:122:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -224,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:130:13
+  --> $DIR/empty-types.rs:131:13
    |
 LL |             _ => {}
    |             ^------
@@ -235,7 +235,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:133:13
+  --> $DIR/empty-types.rs:134:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -246,7 +246,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:141:13
+  --> $DIR/empty-types.rs:142:13
    |
 LL |             Some(_) => {}
    |             ^^^^^^^------
@@ -257,7 +257,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:145:13
+  --> $DIR/empty-types.rs:146:13
    |
 LL |             None => {}
    |             ---- matches all the relevant values
@@ -265,7 +265,7 @@
    |             ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:197:13
+  --> $DIR/empty-types.rs:198:13
    |
 LL |             _ => {}
    |             ^------
@@ -276,7 +276,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:202:13
+  --> $DIR/empty-types.rs:203:13
    |
 LL |             _ => {}
    |             ^------
@@ -287,7 +287,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:207:13
+  --> $DIR/empty-types.rs:208:13
    |
 LL |             _ => {}
    |             ^------
@@ -298,7 +298,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:212:13
+  --> $DIR/empty-types.rs:213:13
    |
 LL |             _ => {}
    |             ^------
@@ -309,7 +309,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:218:13
+  --> $DIR/empty-types.rs:219:13
    |
 LL |             _ => {}
    |             ^------
@@ -320,7 +320,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:279:9
+  --> $DIR/empty-types.rs:280:9
    |
 LL |         _ => {}
    |         ^------
@@ -331,7 +331,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:282:9
+  --> $DIR/empty-types.rs:283:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -342,7 +342,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:285:9
+  --> $DIR/empty-types.rs:286:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -353,7 +353,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:286:9
+  --> $DIR/empty-types.rs:287:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -364,7 +364,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:325:11
+  --> $DIR/empty-types.rs:326:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -378,7 +378,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:336:11
+  --> $DIR/empty-types.rs:337:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -391,7 +391,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:350:11
+  --> $DIR/empty-types.rs:351:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -405,7 +405,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:357:11
+  --> $DIR/empty-types.rs:358:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -419,7 +419,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:366:9
+  --> $DIR/empty-types.rs:367:9
    |
 LL |         _ => {}
    |         ^------
@@ -430,7 +430,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:369:9
+  --> $DIR/empty-types.rs:370:9
    |
 LL |         [_, _, _] => {}
    |         ^^^^^^^^^------
@@ -441,7 +441,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:372:9
+  --> $DIR/empty-types.rs:373:9
    |
 LL |         [_, ..] => {}
    |         ^^^^^^^------
@@ -452,7 +452,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:386:11
+  --> $DIR/empty-types.rs:387:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -466,7 +466,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:393:9
+  --> $DIR/empty-types.rs:394:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -474,7 +474,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:395:11
+  --> $DIR/empty-types.rs:396:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -488,7 +488,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:414:9
+  --> $DIR/empty-types.rs:415:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^------
@@ -499,7 +499,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:419:9
+  --> $DIR/empty-types.rs:420:9
    |
 LL |         Some(_a) => {}
    |         ^^^^^^^^------
@@ -510,7 +510,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:424:9
+  --> $DIR/empty-types.rs:425:9
    |
 LL |         None => {}
    |         ---- matches all the relevant values
@@ -519,7 +519,7 @@
    |         ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:429:9
+  --> $DIR/empty-types.rs:430:9
    |
 LL |         None => {}
    |         ---- matches all the relevant values
@@ -528,7 +528,7 @@
    |         ^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:601:9
+  --> $DIR/empty-types.rs:602:9
    |
 LL |         _ => {}
    |         ^------
@@ -539,7 +539,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:604:9
+  --> $DIR/empty-types.rs:605:9
    |
 LL |         _x => {}
    |         ^^------
@@ -550,7 +550,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:607:9
+  --> $DIR/empty-types.rs:608:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -561,7 +561,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:610:9
+  --> $DIR/empty-types.rs:611:9
    |
 LL |         _x if false => {}
    |         ^^---------------
diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
index 68a1beb..4dcbe6c 100644
--- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:47:9
+  --> $DIR/empty-types.rs:48:9
    |
 LL |         _ => {}
    |         ^------
@@ -9,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:13:9
+  --> $DIR/empty-types.rs:14:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:50:9
+  --> $DIR/empty-types.rs:51:9
    |
 LL |         _x => {}
    |         ^^------
@@ -26,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:54:11
+  --> $DIR/empty-types.rs:55:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -41,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:81:9
+  --> $DIR/empty-types.rs:82:9
    |
 LL |         _ => {}
    |         ^------
@@ -52,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:85:11
+  --> $DIR/empty-types.rs:86:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -71,7 +71,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:94:11
+  --> $DIR/empty-types.rs:95:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -89,7 +89,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:100:9
+  --> $DIR/empty-types.rs:101:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -103,7 +103,7 @@
    |                                         ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:104:9
+  --> $DIR/empty-types.rs:105:9
    |
 LL |     let Ok(_x) = &res_u32_never;
    |         ^^^^^^ pattern `&Err(!)` not covered
@@ -117,7 +117,7 @@
    |                                 ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:130:13
+  --> $DIR/empty-types.rs:131:13
    |
 LL |             _ => {}
    |             ^------
@@ -128,7 +128,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:133:13
+  --> $DIR/empty-types.rs:134:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -139,7 +139,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:154:15
+  --> $DIR/empty-types.rs:155:15
    |
 LL |         match *ref_opt_void {
    |               ^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -158,7 +158,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:197:13
+  --> $DIR/empty-types.rs:198:13
    |
 LL |             _ => {}
    |             ^------
@@ -169,7 +169,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:202:13
+  --> $DIR/empty-types.rs:203:13
    |
 LL |             _ => {}
    |             ^------
@@ -180,7 +180,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:207:13
+  --> $DIR/empty-types.rs:208:13
    |
 LL |             _ => {}
    |             ^------
@@ -191,7 +191,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:212:13
+  --> $DIR/empty-types.rs:213:13
    |
 LL |             _ => {}
    |             ^------
@@ -202,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:218:13
+  --> $DIR/empty-types.rs:219:13
    |
 LL |             _ => {}
    |             ^------
@@ -213,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:279:9
+  --> $DIR/empty-types.rs:280:9
    |
 LL |         _ => {}
    |         ^------
@@ -224,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:295:13
+  --> $DIR/empty-types.rs:296:13
    |
 LL |         let Ok(_) = *ptr_result_never_err;
    |             ^^^^^ pattern `Err(!)` not covered
@@ -238,7 +238,7 @@
    |         ++                                   +++++++++++
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:314:11
+  --> $DIR/empty-types.rs:315:11
    |
 LL |     match *x {}
    |           ^^
@@ -252,7 +252,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:316:11
+  --> $DIR/empty-types.rs:317:11
    |
 LL |     match *x {}
    |           ^^
@@ -266,7 +266,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered
-  --> $DIR/empty-types.rs:318:11
+  --> $DIR/empty-types.rs:319:11
    |
 LL |     match *x {}
    |           ^^ patterns `Ok(!)` and `Err(!)` not covered
@@ -288,7 +288,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:320:11
+  --> $DIR/empty-types.rs:321:11
    |
 LL |     match *x {}
    |           ^^
@@ -302,7 +302,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:325:11
+  --> $DIR/empty-types.rs:326:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -316,7 +316,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered
-  --> $DIR/empty-types.rs:327:11
+  --> $DIR/empty-types.rs:328:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[!, ..]` not covered
@@ -330,7 +330,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered
-  --> $DIR/empty-types.rs:336:11
+  --> $DIR/empty-types.rs:337:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered
@@ -343,7 +343,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered
-  --> $DIR/empty-types.rs:350:11
+  --> $DIR/empty-types.rs:351:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered
@@ -357,7 +357,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:357:11
+  --> $DIR/empty-types.rs:358:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -371,7 +371,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:386:11
+  --> $DIR/empty-types.rs:387:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -385,7 +385,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:393:9
+  --> $DIR/empty-types.rs:394:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -393,7 +393,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:395:11
+  --> $DIR/empty-types.rs:396:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -407,7 +407,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
-  --> $DIR/empty-types.rs:449:11
+  --> $DIR/empty-types.rs:450:11
    |
 LL |     match ref_opt_never {
    |           ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
@@ -426,7 +426,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:490:11
+  --> $DIR/empty-types.rs:491:11
    |
 LL |     match *ref_opt_never {
    |           ^^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -445,7 +445,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(!)` not covered
-  --> $DIR/empty-types.rs:538:11
+  --> $DIR/empty-types.rs:539:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -464,7 +464,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(!)` not covered
-  --> $DIR/empty-types.rs:549:11
+  --> $DIR/empty-types.rs:550:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -483,7 +483,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:568:11
+  --> $DIR/empty-types.rs:569:11
    |
 LL |     match *ref_tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -497,7 +497,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:601:9
+  --> $DIR/empty-types.rs:602:9
    |
 LL |         _ => {}
    |         ^------
@@ -508,7 +508,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:604:9
+  --> $DIR/empty-types.rs:605:9
    |
 LL |         _x => {}
    |         ^^------
@@ -519,7 +519,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:607:9
+  --> $DIR/empty-types.rs:608:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -530,7 +530,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:610:9
+  --> $DIR/empty-types.rs:611:9
    |
 LL |         _x if false => {}
    |         ^^---------------
@@ -541,7 +541,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&!` not covered
-  --> $DIR/empty-types.rs:635:11
+  --> $DIR/empty-types.rs:636:11
    |
 LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&!` not covered
@@ -557,7 +557,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(!)` not covered
-  --> $DIR/empty-types.rs:651:11
+  --> $DIR/empty-types.rs:652:11
    |
 LL |     match *ref_result_never {
    |           ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered
@@ -577,7 +577,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:671:11
+  --> $DIR/empty-types.rs:672:11
    |
 LL |     match *x {
    |           ^^ pattern `Some(!)` not covered
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
index 3209595..a49050c 100644
--- a/tests/ui/pattern/usefulness/empty-types.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:47:9
+  --> $DIR/empty-types.rs:48:9
    |
 LL |         _ => {}
    |         ^------
@@ -9,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:13:9
+  --> $DIR/empty-types.rs:14:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:50:9
+  --> $DIR/empty-types.rs:51:9
    |
 LL |         _x => {}
    |         ^^------
@@ -26,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:54:11
+  --> $DIR/empty-types.rs:55:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -41,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:81:9
+  --> $DIR/empty-types.rs:82:9
    |
 LL |         _ => {}
    |         ^------
@@ -52,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:85:11
+  --> $DIR/empty-types.rs:86:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -71,7 +71,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:94:11
+  --> $DIR/empty-types.rs:95:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -89,7 +89,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:100:9
+  --> $DIR/empty-types.rs:101:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -103,7 +103,7 @@
    |                                         ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:104:9
+  --> $DIR/empty-types.rs:105:9
    |
 LL |     let Ok(_x) = &res_u32_never;
    |         ^^^^^^ pattern `&Err(_)` not covered
@@ -117,7 +117,7 @@
    |                                 ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:130:13
+  --> $DIR/empty-types.rs:131:13
    |
 LL |             _ => {}
    |             ^------
@@ -128,7 +128,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:133:13
+  --> $DIR/empty-types.rs:134:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -139,7 +139,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:154:15
+  --> $DIR/empty-types.rs:155:15
    |
 LL |         match *ref_opt_void {
    |               ^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -158,7 +158,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:197:13
+  --> $DIR/empty-types.rs:198:13
    |
 LL |             _ => {}
    |             ^------
@@ -169,7 +169,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:202:13
+  --> $DIR/empty-types.rs:203:13
    |
 LL |             _ => {}
    |             ^------
@@ -180,7 +180,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:207:13
+  --> $DIR/empty-types.rs:208:13
    |
 LL |             _ => {}
    |             ^------
@@ -191,7 +191,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:212:13
+  --> $DIR/empty-types.rs:213:13
    |
 LL |             _ => {}
    |             ^------
@@ -202,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:218:13
+  --> $DIR/empty-types.rs:219:13
    |
 LL |             _ => {}
    |             ^------
@@ -213,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:279:9
+  --> $DIR/empty-types.rs:280:9
    |
 LL |         _ => {}
    |         ^------
@@ -224,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:295:13
+  --> $DIR/empty-types.rs:296:13
    |
 LL |         let Ok(_) = *ptr_result_never_err;
    |             ^^^^^ pattern `Err(_)` not covered
@@ -238,7 +238,7 @@
    |         ++                                   +++++++++++
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:314:11
+  --> $DIR/empty-types.rs:315:11
    |
 LL |     match *x {}
    |           ^^
@@ -252,7 +252,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:316:11
+  --> $DIR/empty-types.rs:317:11
    |
 LL |     match *x {}
    |           ^^
@@ -266,7 +266,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
-  --> $DIR/empty-types.rs:318:11
+  --> $DIR/empty-types.rs:319:11
    |
 LL |     match *x {}
    |           ^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -288,7 +288,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:320:11
+  --> $DIR/empty-types.rs:321:11
    |
 LL |     match *x {}
    |           ^^
@@ -302,7 +302,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:325:11
+  --> $DIR/empty-types.rs:326:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -316,7 +316,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:327:11
+  --> $DIR/empty-types.rs:328:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
@@ -330,7 +330,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
-  --> $DIR/empty-types.rs:336:11
+  --> $DIR/empty-types.rs:337:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@@ -343,7 +343,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:350:11
+  --> $DIR/empty-types.rs:351:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@@ -357,7 +357,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:357:11
+  --> $DIR/empty-types.rs:358:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -371,7 +371,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:386:11
+  --> $DIR/empty-types.rs:387:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -385,7 +385,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:393:9
+  --> $DIR/empty-types.rs:394:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -393,7 +393,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:395:11
+  --> $DIR/empty-types.rs:396:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -407,7 +407,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
-  --> $DIR/empty-types.rs:449:11
+  --> $DIR/empty-types.rs:450:11
    |
 LL |     match ref_opt_never {
    |           ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@@ -426,7 +426,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:490:11
+  --> $DIR/empty-types.rs:491:11
    |
 LL |     match *ref_opt_never {
    |           ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -445,7 +445,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:538:11
+  --> $DIR/empty-types.rs:539:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -464,7 +464,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:549:11
+  --> $DIR/empty-types.rs:550:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -483,7 +483,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:568:11
+  --> $DIR/empty-types.rs:569:11
    |
 LL |     match *ref_tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -497,7 +497,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:601:9
+  --> $DIR/empty-types.rs:602:9
    |
 LL |         _ => {}
    |         ^------
@@ -508,7 +508,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:604:9
+  --> $DIR/empty-types.rs:605:9
    |
 LL |         _x => {}
    |         ^^------
@@ -519,7 +519,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:607:9
+  --> $DIR/empty-types.rs:608:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -530,7 +530,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:610:9
+  --> $DIR/empty-types.rs:611:9
    |
 LL |         _x if false => {}
    |         ^^---------------
@@ -541,7 +541,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
-  --> $DIR/empty-types.rs:635:11
+  --> $DIR/empty-types.rs:636:11
    |
 LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&_` not covered
@@ -557,7 +557,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:651:11
+  --> $DIR/empty-types.rs:652:11
    |
 LL |     match *ref_result_never {
    |           ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -577,7 +577,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:671:11
+  --> $DIR/empty-types.rs:672:11
    |
 LL |     match *x {
    |           ^^ pattern `Some(_)` not covered
diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs
index d4fdb7c..cb0f181 100644
--- a/tests/ui/pattern/usefulness/empty-types.rs
+++ b/tests/ui/pattern/usefulness/empty-types.rs
@@ -1,5 +1,6 @@
 //@ revisions: normal exhaustive_patterns never_pats
 //@ edition: 2024
+//@ ignore-parallel-frontend pattern matching error message mismatch
 //
 // This tests correct handling of empty types in exhaustiveness checking.
 //
diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs
index ace0034..e6e8dd1 100644
--- a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs
+++ b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs
@@ -12,7 +12,6 @@ trait NeedsPinDrop {
 }
 
 impl NeedsPinDrop for S {
-    //~^ ERROR not all trait items implemented, missing: `pin_drop` [E0046]
     fn drop(&pin mut self) {}
     //~^ ERROR method `drop` with `&pin mut self` is only supported for the `Drop` trait
 }
@@ -53,7 +52,6 @@ trait Drop {
     }
 
     impl Drop for S {
-        //~^ ERROR not all trait items implemented, missing: `pin_drop` [E0046]
         fn drop(&pin mut self) {}
         //~^ ERROR method `drop` with `&pin mut self` is only supported for the `Drop` trait
     }
diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr
index 2238abe..2fba64f 100644
--- a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr
+++ b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr
@@ -1,5 +1,5 @@
 error[E0407]: method `drop` is not a member of trait `HasDrop`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:26:5
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:25:5
    |
 LL |     fn drop(&pin mut self) {}
    |     ^^^----^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@
    |     not a member of trait `HasDrop`
 
 error[E0407]: method `drop` is not a member of trait `HasPinnedDropReceiver`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:36:5
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:35:5
    |
 LL |     fn drop(&pin mut self) {}
    |     ^^^----^^^^^^^^^^^^^^^^^^
@@ -17,28 +17,19 @@
    |     not a member of trait `HasPinnedDropReceiver`
 
 error: method `drop` with `&pin mut self` is only supported for the `Drop` trait
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:16:5
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:15:5
    |
 LL |     fn drop(&pin mut self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ not a `Drop::pin_drop` implementation
 
 error: method `drop` with `&pin mut self` is only supported for the `Drop` trait
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:57:9
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:55:9
    |
 LL |         fn drop(&pin mut self) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ not a `Drop::pin_drop` implementation
 
-error[E0046]: not all trait items implemented, missing: `pin_drop`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:14:1
-   |
-LL |     fn pin_drop(self: Pin<&mut Self>);
-   |     ---------------------------------- `pin_drop` from trait
-...
-LL | impl NeedsPinDrop for S {
-   | ^^^^^^^^^^^^^^^^^^^^^^^ missing `pin_drop` in implementation
-
 error[E0046]: not all trait items implemented, missing: `drop`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:24:1
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:23:1
    |
 LL |     fn drop(self: Pin<&mut Self>);
    |     ------------------------------ `drop` from trait
@@ -47,7 +38,7 @@
    | ^^^^^^^^^^^^^^^^^^ missing `drop` in implementation
 
 error[E0046]: not all trait items implemented, missing: `drop`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:34:1
+  --> $DIR/pinned-drop-sugar-not-other-traits.rs:33:1
    |
 LL |     fn drop(self: &pin mut Self);
    |     ----------------------------- `drop` from trait
@@ -55,16 +46,7 @@
 LL | impl HasPinnedDropReceiver for S {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation
 
-error[E0046]: not all trait items implemented, missing: `pin_drop`
-  --> $DIR/pinned-drop-sugar-not-other-traits.rs:55:5
-   |
-LL |         fn pin_drop(self: Pin<&mut Self>);
-   |         ---------------------------------- `pin_drop` from trait
-...
-LL |     impl Drop for S {
-   |     ^^^^^^^^^^^^^^^ missing `pin_drop` in implementation
-
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0046, E0407.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/privacy/effective-visibilities-macro-2.rs b/tests/ui/privacy/effective-visibilities-macro-2.rs
new file mode 100644
index 0000000..0af3c92
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro-2.rs
@@ -0,0 +1,26 @@
+// Make sure that `Placeholder` will be marked as reachable without `use crate::ty` like in
+// `effective-visibility-macro.rs` test.
+
+#![feature(rustc_attrs, decl_macro)]
+
+pub mod ty {
+    pub mod print {
+        mod pretty {
+            #[rustc_effective_visibility]
+            pub macro with_no_queries() {}
+            //~^ ERROR  Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+        }
+
+        pub use self::pretty::with_no_queries;
+    }
+
+    #[rustc_effective_visibility]
+    mod sty {
+    //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+        #[rustc_effective_visibility]
+        pub type Placeholder = ();
+        //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/effective-visibilities-macro-2.stderr b/tests/ui/privacy/effective-visibilities-macro-2.stderr
new file mode 100644
index 0000000..bd643e2
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro-2.stderr
@@ -0,0 +1,20 @@
+error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro-2.rs:10:13
+   |
+LL |             pub macro with_no_queries() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+  --> $DIR/effective-visibilities-macro-2.rs:18:5
+   |
+LL |     mod sty {
+   |     ^^^^^^^
+
+error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro-2.rs:21:9
+   |
+LL |         pub type Placeholder = ();
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/privacy/effective-visibilities-macro.rs b/tests/ui/privacy/effective-visibilities-macro.rs
new file mode 100644
index 0000000..f5857fd
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro.rs
@@ -0,0 +1,25 @@
+#![feature(rustc_attrs, decl_macro)]
+
+pub mod ty {
+    pub mod print {
+        mod pretty {
+            #[rustc_effective_visibility]
+            pub macro with_no_queries() {}
+            //~^ ERROR  Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+        }
+
+        pub use self::pretty::with_no_queries;
+        // Start visiting outer modules during macro-reachable phase.
+        use crate::ty;
+    }
+
+    #[rustc_effective_visibility]
+    mod sty {
+    //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+        #[rustc_effective_visibility]
+        pub type Placeholder = ();
+        //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/effective-visibilities-macro.stderr b/tests/ui/privacy/effective-visibilities-macro.stderr
new file mode 100644
index 0000000..d08107e
--- /dev/null
+++ b/tests/ui/privacy/effective-visibilities-macro.stderr
@@ -0,0 +1,20 @@
+error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro.rs:7:13
+   |
+LL |             pub macro with_no_queries() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self)
+  --> $DIR/effective-visibilities-macro.rs:17:5
+   |
+LL |     mod sty {
+   |     ^^^^^^^
+
+error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective-visibilities-macro.rs:20:9
+   |
+LL |         pub type Placeholder = ();
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr
index 24962cf..cf80df7 100644
--- a/tests/ui/proc-macro/attribute.stderr
+++ b/tests/ui/proc-macro/attribute.stderr
@@ -102,7 +102,7 @@
 LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |
 
-error[E0539]: malformed `proc_macro_derive` attribute input
+error[E0565]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:45:1
    |
 LL | #[proc_macro_derive(m::d7)]
@@ -138,7 +138,7 @@
 LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |
 
-error[E0539]: malformed `proc_macro_derive` attribute input
+error[E0565]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:57:1
    |
 LL | #[proc_macro_derive(self)]
@@ -192,7 +192,7 @@
 LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |
 
-error[E0539]: malformed `proc_macro_derive` attribute input
+error[E0565]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:78:1
    |
 LL | #[proc_macro_derive(d13, attributes("a"))]
@@ -228,7 +228,7 @@
 LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |
 
-error[E0539]: malformed `proc_macro_derive` attribute input
+error[E0565]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:90:1
    |
 LL | #[proc_macro_derive(d15, attributes(m::a))]
@@ -264,7 +264,7 @@
 LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |
 
-error[E0539]: malformed `proc_macro_derive` attribute input
+error[E0565]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:102:1
    |
 LL | #[proc_macro_derive(d17, attributes(self))]
diff --git a/tests/ui/issues/issue-16596.rs b/tests/ui/regions/relate-bound-region-ref-type-param.rs
similarity index 80%
rename from tests/ui/issues/issue-16596.rs
rename to tests/ui/regions/relate-bound-region-ref-type-param.rs
index 51441e8..f6a637f 100644
--- a/tests/ui/issues/issue-16596.rs
+++ b/tests/ui/regions/relate-bound-region-ref-type-param.rs
@@ -1,3 +1,5 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16596>.
+
 //@ check-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/repr/invalid_repr_list_help.rs b/tests/ui/repr/invalid_repr_list_help.rs
index e8bf5fd..407514d 100644
--- a/tests/ui/repr/invalid_repr_list_help.rs
+++ b/tests/ui/repr/invalid_repr_list_help.rs
@@ -1,22 +1,22 @@
 #![deny(invalid_doc_attributes)]
 #![crate_type = "lib"]
 
-#[repr(uwu)] //~ERROR: unrecognized representation hint
+#[repr(uwu)] //~ERROR: malformed `repr` attribute input
 pub struct OwO;
 
-#[repr(uwu = "a")] //~ERROR: unrecognized representation hint
+#[repr(uwu = "a")] //~ERROR: malformed `repr` attribute input
 pub struct OwO2(i32);
 
-#[repr(uwu(4))] //~ERROR: unrecognized representation hint
+#[repr(uwu(4))] //~ERROR: malformed `repr` attribute input
 pub struct OwO3 {
     x: i32,
 }
 
-#[repr(uwu, u8)] //~ERROR: unrecognized representation hint
+#[repr(uwu, u8)] //~ERROR: malformed `repr` attribute input
 pub enum OwO4 {
     UwU = 1,
 }
 
-#[repr(uwu)] //~ERROR: unrecognized representation hint
+#[repr(uwu)] //~ERROR: malformed `repr` attribute input
 #[doc(owo)]  //~ERROR: unknown `doc` attribute
 pub struct Owo5;
diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr
index 3226508..82bf12f 100644
--- a/tests/ui/repr/invalid_repr_list_help.stderr
+++ b/tests/ui/repr/invalid_repr_list_help.stderr
@@ -1,47 +1,52 @@
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid_repr_list_help.rs:4:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid_repr_list_help.rs:4:1
    |
 LL | #[repr(uwu)]
-   |        ^^^
+   | ^^^^^^^---^^
+   |        |
+   |        valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid_repr_list_help.rs:7:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid_repr_list_help.rs:7:1
    |
 LL | #[repr(uwu = "a")]
-   |        ^^^^^^^^^
+   | ^^^^^^^---------^^
+   |        |
+   |        valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid_repr_list_help.rs:10:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid_repr_list_help.rs:10:1
    |
 LL | #[repr(uwu(4))]
-   |        ^^^^^^
+   | ^^^^^^^------^^
+   |        |
+   |        valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid_repr_list_help.rs:15:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid_repr_list_help.rs:15:1
    |
 LL | #[repr(uwu, u8)]
-   |        ^^^
+   | ^^^^^^^---^^^^^^
+   |        |
+   |        valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: unrecognized representation hint
-  --> $DIR/invalid_repr_list_help.rs:20:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/invalid_repr_list_help.rs:20:1
    |
 LL | #[repr(uwu)]
-   |        ^^^
+   | ^^^^^^^---^^
+   |        |
+   |        valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize`
    |
-   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: unknown `doc` attribute `owo`
   --> $DIR/invalid_repr_list_help.rs:21:7
@@ -57,4 +62,4 @@
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0552`.
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/repr/malformed-repr-hints.rs b/tests/ui/repr/malformed-repr-hints.rs
index 09c808a..de8ea89 100644
--- a/tests/ui/repr/malformed-repr-hints.rs
+++ b/tests/ui/repr/malformed-repr-hints.rs
@@ -4,40 +4,40 @@
 //@ compile-flags: -Zdeduplicate-diagnostics=yes
 
 #[repr(packed())]
-//~^ ERROR: incorrect `repr(packed)` attribute format
+//~^ ERROR: malformed `repr` attribute input
 struct S1;
 
 #[repr(align)]
-//~^ ERROR: invalid `repr(align)` attribute
+//~^ ERROR: malformed `repr` attribute input
 struct S2;
 
 #[repr(align(2, 4))]
-//~^ ERROR: incorrect `repr(align)` attribute format
+//~^ ERROR: malformed `repr` attribute input
 struct S3;
 
 #[repr(align())]
-//~^ ERROR: incorrect `repr(align)` attribute format
+//~^ ERROR: malformed `repr` attribute input
 struct S4;
 
 // Regression test for issue #118334:
 #[repr(Rust(u8))]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 #[repr(Rust(0))]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 #[repr(Rust = 0)]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 struct S5;
 
 #[repr(i8())]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 enum E1 { A, B }
 
 #[repr(u32(42))]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 enum E2 { A, B }
 
 #[repr(i64 = 2)]
-//~^ ERROR: invalid representation hint
+//~^ ERROR: malformed `repr` attribute input
 enum E3 { A, B }
 
 fn main() {}
diff --git a/tests/ui/repr/malformed-repr-hints.stderr b/tests/ui/repr/malformed-repr-hints.stderr
index 6fb9275..5911d11 100644
--- a/tests/ui/repr/malformed-repr-hints.stderr
+++ b/tests/ui/repr/malformed-repr-hints.stderr
@@ -1,64 +1,104 @@
-error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
-  --> $DIR/malformed-repr-hints.rs:6:8
+error[E0805]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:6:1
    |
 LL | #[repr(packed())]
-   |        ^^^^^^^^
+   | ^^^^^^^^^^^^^--^^
+   |              |
+   |              expected an argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
-  --> $DIR/malformed-repr-hints.rs:10:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:10:1
    |
 LL | #[repr(align)]
-   |        ^^^^^ help: supply an argument here: `align(...)`
+   | ^^^^^^^-----^^
+   |        |
+   |        expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
-  --> $DIR/malformed-repr-hints.rs:14:8
+error[E0805]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:14:1
    |
 LL | #[repr(align(2, 4))]
-   |        ^^^^^^^^^^^
+   | ^^^^^^^^^^^^------^^
+   |             |
+   |             expected a single argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
-  --> $DIR/malformed-repr-hints.rs:18:8
+error[E0805]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:18:1
    |
 LL | #[repr(align())]
-   |        ^^^^^^^
+   | ^^^^^^^^^^^^--^^
+   |             |
+   |             expected an argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list
-  --> $DIR/malformed-repr-hints.rs:23:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:23:1
    |
 LL | #[repr(Rust(u8))]
-   |        ^^^^^^^^
+   | ^^^^^^^^^^^----^^
+   |            |
+   |            didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list
-  --> $DIR/malformed-repr-hints.rs:25:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:25:1
    |
 LL | #[repr(Rust(0))]
-   |        ^^^^^^^
+   | ^^^^^^^^^^^---^^
+   |            |
+   |            didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `Rust` does not take a value
-  --> $DIR/malformed-repr-hints.rs:27:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:27:1
    |
 LL | #[repr(Rust = 0)]
-   |        ^^^^^^^^
+   | ^^^^^^^^^^^^---^^
+   |             |
+   |             didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
-  --> $DIR/malformed-repr-hints.rs:31:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:31:1
    |
 LL | #[repr(i8())]
-   |        ^^^^
+   | ^^^^^^^^^--^^
+   |          |
+   |          didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
-  --> $DIR/malformed-repr-hints.rs:35:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:35:1
    |
 LL | #[repr(u32(42))]
-   |        ^^^^^^^
+   | ^^^^^^^^^^----^^
+   |           |
+   |           didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0552]: invalid representation hint: `i64` does not take a value
-  --> $DIR/malformed-repr-hints.rs:39:8
+error[E0565]: malformed `repr` attribute input
+  --> $DIR/malformed-repr-hints.rs:39:1
    |
 LL | #[repr(i64 = 2)]
-   |        ^^^^^^^
+   | ^^^^^^^^^^^---^^
+   |            |
+   |            didn't expect any arguments here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0552, E0589, E0693.
-For more information about an error, try `rustc --explain E0552`.
+Some errors have detailed explanations: E0539, E0565, E0805.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/repr/repr-align-assign.fixed b/tests/ui/repr/repr-align-assign.fixed
deleted file mode 100644
index 96f9866..0000000
--- a/tests/ui/repr/repr-align-assign.fixed
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ run-rustfix
-
-#![allow(dead_code)]
-
-#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
-struct A(u64);
-
-#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
-struct B(u64);
-
-fn main() {}
diff --git a/tests/ui/repr/repr-align-assign.rs b/tests/ui/repr/repr-align-assign.rs
index 0b30ee6..a7fe2f2 100644
--- a/tests/ui/repr/repr-align-assign.rs
+++ b/tests/ui/repr/repr-align-assign.rs
@@ -1,11 +1,9 @@
-//@ run-rustfix
-
 #![allow(dead_code)]
 
-#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+#[repr(align=8)] //~ ERROR malformed `repr` attribute input
 struct A(u64);
 
-#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+#[repr(align="8")] //~ ERROR malformed `repr` attribute input
 struct B(u64);
 
 fn main() {}
diff --git a/tests/ui/repr/repr-align-assign.stderr b/tests/ui/repr/repr-align-assign.stderr
index cc046e0..f81cdf5 100644
--- a/tests/ui/repr/repr-align-assign.stderr
+++ b/tests/ui/repr/repr-align-assign.stderr
@@ -1,15 +1,23 @@
-error[E0693]: incorrect `repr(align)` attribute format
-  --> $DIR/repr-align-assign.rs:5:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/repr-align-assign.rs:3:1
    |
 LL | #[repr(align=8)]
-   |        ^^^^^^^ help: use parentheses instead: `align(8)`
+   | ^^^^^^^^^^^^--^^
+   |             |
+   |             expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0693]: incorrect `repr(align)` attribute format
-  --> $DIR/repr-align-assign.rs:8:8
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/repr-align-assign.rs:6:1
    |
 LL | #[repr(align="8")]
-   |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+   | ^^^^^^^^^^^^----^^
+   |             |
+   |             expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0693`.
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/repr/repr-align.rs b/tests/ui/repr/repr-align.rs
index 6b60a76..64c5311 100644
--- a/tests/ui/repr/repr-align.rs
+++ b/tests/ui/repr/repr-align.rs
@@ -1,33 +1,33 @@
 #![allow(dead_code)]
 
-#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+#[repr(align(16.0))] //~ ERROR: not an unsuffixed integer
 struct S0(i32);
 
-#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+#[repr(align(15))] //~ ERROR: not a power of two
 struct S1(i32);
 
-#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+#[repr(align(4294967296))] //~ ERROR: larger than 2^29
 struct S2(i32);
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
 struct S3(i32);
 
-#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+#[repr(align(0))] //~ ERROR: not a power of two
 struct S4(i32);
 
-#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+#[repr(align(16.0))] //~ ERROR: not an unsuffixed integer
 enum E0 { A, B }
 
-#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+#[repr(align(15))] //~ ERROR: not a power of two
 enum E1 { A, B }
 
-#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+#[repr(align(4294967296))] //~ ERROR: larger than 2^29
 enum E2 { A, B }
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
 enum E3 { A, B }
 
-#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+#[repr(align(0))] //~ ERROR: not a power of two
 enum E4 { A, B }
 
 fn main() {}
diff --git a/tests/ui/repr/repr-align.stderr b/tests/ui/repr/repr-align.stderr
index fe919e3..9c0185b 100644
--- a/tests/ui/repr/repr-align.stderr
+++ b/tests/ui/repr/repr-align.stderr
@@ -1,46 +1,46 @@
-error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+error[E0589]: invalid alignment value: not an unsuffixed integer
   --> $DIR/repr-align.rs:3:14
    |
 LL | #[repr(align(16.0))]
    |              ^^^^
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
+error[E0589]: invalid alignment value: not a power of two
   --> $DIR/repr-align.rs:6:14
    |
 LL | #[repr(align(15))]
    |              ^^
 
-error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+error[E0589]: invalid alignment value: larger than 2^29
   --> $DIR/repr-align.rs:9:14
    |
 LL | #[repr(align(4294967296))]
    |              ^^^^^^^^^^
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
+error[E0589]: invalid alignment value: not a power of two
   --> $DIR/repr-align.rs:15:14
    |
 LL | #[repr(align(0))]
    |              ^
 
-error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+error[E0589]: invalid alignment value: not an unsuffixed integer
   --> $DIR/repr-align.rs:18:14
    |
 LL | #[repr(align(16.0))]
    |              ^^^^
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
+error[E0589]: invalid alignment value: not a power of two
   --> $DIR/repr-align.rs:21:14
    |
 LL | #[repr(align(15))]
    |              ^^
 
-error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+error[E0589]: invalid alignment value: larger than 2^29
   --> $DIR/repr-align.rs:24:14
    |
 LL | #[repr(align(4294967296))]
    |              ^^^^^^^^^^
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
+error[E0589]: invalid alignment value: not a power of two
   --> $DIR/repr-align.rs:30:14
    |
 LL | #[repr(align(0))]
diff --git a/tests/ui/repr/repr_align_greater_usize.msp430.stderr b/tests/ui/repr/repr_align_greater_usize.msp430.stderr
index 4fcd33d..1045e6e 100644
--- a/tests/ui/repr/repr_align_greater_usize.msp430.stderr
+++ b/tests/ui/repr/repr_align_greater_usize.msp430.stderr
@@ -1,10 +1,10 @@
-error[E0589]: invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target)
+error[E0589]: invalid alignment value: alignment larger than `isize::MAX` bytes (32767 for the current target)
   --> $DIR/repr_align_greater_usize.rs:23:14
    |
 LL | #[repr(align(32768))]
    |              ^^^^^
 
-error[E0589]: invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target)
+error[E0589]: invalid alignment value: alignment larger than `isize::MAX` bytes (32767 for the current target)
   --> $DIR/repr_align_greater_usize.rs:26:14
    |
 LL | #[repr(align(65536))]
diff --git a/tests/ui/repr/repr_align_greater_usize.rs b/tests/ui/repr/repr_align_greater_usize.rs
index 7df1fbe..9f4eb8e 100644
--- a/tests/ui/repr/repr_align_greater_usize.rs
+++ b/tests/ui/repr/repr_align_greater_usize.rs
@@ -20,8 +20,8 @@
 #[repr(align(16384))]
 struct Kitten;
 
-#[repr(align(32768))] //[msp430]~ ERROR invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589]
+#[repr(align(32768))] //[msp430]~ ERROR alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589]
 struct Cat;
 
-#[repr(align(65536))] //[msp430]~ ERROR invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589]
+#[repr(align(65536))] //[msp430]~ ERROR alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589]
 struct BigCat;
diff --git a/tests/ui/return/issue-82612-return-mutable-reference.stderr b/tests/ui/return/issue-82612-return-mutable-reference.stderr
index 632f366..c7f86f9 100644
--- a/tests/ui/return/issue-82612-return-mutable-reference.stderr
+++ b/tests/ui/return/issue-82612-return-mutable-reference.stderr
@@ -14,10 +14,6 @@
    |
 LL |             value.get_or_insert_with(func);
    |                                           +
-help: consider using a semicolon here
-   |
-LL |         };
-   |          +
 help: you might have meant to return this value
    |
 LL |             return value.get_or_insert_with(func);
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
index 4cdeb18..f8699f9 100644
--- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
@@ -4,7 +4,6 @@
 LL |     let _: NotDebug = dbg!(NotDebug);
    |                       ^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `NotDebug`
    |
-   = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug`
 help: consider annotating `NotDebug` with `#[derive(Debug)]`
    |
 LL + #[derive(Debug)]
diff --git a/tests/ui/rustc-env/def-path-hash-ice-157238.rs b/tests/ui/rustc-env/def-path-hash-ice-157238.rs
new file mode 100644
index 0000000..42bf830
--- /dev/null
+++ b/tests/ui/rustc-env/def-path-hash-ice-157238.rs
@@ -0,0 +1,9 @@
+//@ run-pass
+//
+// Ensure that `trace` level instrumentation in `def_path_hash` works,
+// see #157238.
+//
+//@ dont-check-compiler-stdout
+//@ dont-check-compiler-stderr
+//@ rustc-env:RUSTC_LOG=trace
+fn main() {}
diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout
index 3aca86a..6dbc1dd 100644
--- a/tests/ui/rustc_public-ir-print/async-closure.stdout
+++ b/tests/ui/rustc_public-ir-print/async-closure.stdout
@@ -48,9 +48,15 @@
     bb0: {
         _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
         _6 = discriminant((*_7));
-        switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
+        switchInt(move _6) -> [0: bb3, 1: bb1, otherwise: bb2];
     }
     bb1: {
+        assert(false, `async fn` resumed after completion) -> [success: bb1, unwind unreachable];
+    }
+    bb2: {
+        unreachable;
+    }
+    bb3: {
         StorageLive(_3);
         _4 = no_retag ((*_7).0: &i32);
         _3 = (*_4);
@@ -60,12 +66,6 @@
         discriminant((*_7)) = 1;
         return;
     }
-    bb2: {
-        assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable];
-    }
-    bb3: {
-        unreachable;
-    }
 }
 fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
     let mut _0: Poll<()>;
@@ -80,9 +80,15 @@
     bb0: {
         _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
         _6 = discriminant((*_7));
-        switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
+        switchInt(move _6) -> [0: bb3, 1: bb1, otherwise: bb2];
     }
     bb1: {
+        assert(false, `async fn` resumed after completion) -> [success: bb1, unwind unreachable];
+    }
+    bb2: {
+        unreachable;
+    }
+    bb3: {
         StorageLive(_3);
         _4 = no_retag ((*_7).0: &i32);
         _3 = (*_4);
@@ -92,10 +98,4 @@
         discriminant((*_7)) = 1;
         return;
     }
-    bb2: {
-        assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable];
-    }
-    bb3: {
-        unreachable;
-    }
 }
diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr
index d2f780b..96c45d2 100644
--- a/tests/ui/span/issue-71363.stderr
+++ b/tests/ui/span/issue-71363.stderr
@@ -18,7 +18,6 @@
 4 | impl std::error::Error for MyError {}
   |                            ^^^^^^^ the trait `Debug` is not implemented for `MyError`
   |
-  = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
 note: required by a bound in `std::error::Error`
  --> $SRC_DIR/core/src/error.rs:LL:COL
 help: consider annotating `MyError` with `#[derive(Debug)]`
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
index b28f39c..0d05bd9 100644
--- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -6,7 +6,6 @@
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ the trait `Debug` is not implemented for `a::Inner<T>`
    |
-   = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>`
 help: consider annotating `a::Inner<T>` with `#[derive(Debug)]`
    |
 LL +     #[derive(Debug)]
diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs
index fdd5dfc..349862a 100644
--- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs
+++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs
@@ -18,7 +18,6 @@ fn main() -> Result<(), ()> {
         //~| NOTE: expected `()`, found integer
         //~| HELP: consider using a semicolon here
     }
-    //~^ HELP: consider using a semicolon here
 
     Ok(())
 }
diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
index 25cd274..78852b8 100644
--- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
+++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
@@ -12,19 +12,12 @@
 LL | /     if true {
 LL | |
 LL | |         x?
-   | |         ^^ expected `()`, found integer
+   | |         ^^- help: consider using a semicolon here: `;`
+   | |         |
+   | |         expected `()`, found integer
 ...  |
 LL | |     }
    | |_____- `if` expressions without `else` arms expect their inner expression to be `()`
-   |
-help: consider using a semicolon here
-   |
-LL |         x?;
-   |           +
-help: consider using a semicolon here
-   |
-LL |     };
-   |      +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/target-feature/implied-features-nvptx.rs b/tests/ui/target-feature/implied-features-nvptx.rs
index 1550c99..a51c22a 100644
--- a/tests/ui/target-feature/implied-features-nvptx.rs
+++ b/tests/ui/target-feature/implied-features-nvptx.rs
@@ -1,5 +1,5 @@
-//@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 -Z unstable-options -Clinker-flavor=llbc
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80
 //@ only-nvptx64
 //@ build-pass
 #![no_std]
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index cb19bdc..702ea3b 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -174,7 +174,7 @@
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^ `foo` is not valid for this target
    |
-   = help: valid names are: `fma`, `xop`, `adx`, `aes`, and `avx` and 75 more
+   = help: valid names are: `fma`, `xop`, `adx`, `aes`, and `avx` and 76 more
 
 error[E0046]: not all trait items implemented, missing: `foo`
   --> $DIR/invalid-attribute.rs:80:1
@@ -226,7 +226,7 @@
 LL | #[target_feature(enable = "sse5")]
    |                  ^^^^^^^^^^^^^^^ `sse5` is not valid for this target
    |
-   = help: valid names are: `sse`, `sse2`, `sse3`, `sse4a`, and `ssse3` and 75 more
+   = help: valid names are: `sse`, `sse2`, `sse3`, `sse4a`, and `ssse3` and 76 more
 
 error: the feature named `avx512` is not valid for this target
   --> $DIR/invalid-attribute.rs:126:18
@@ -234,7 +234,7 @@
 LL | #[target_feature(enable = "avx512")]
    |                  ^^^^^^^^^^^^^^^^^ `avx512` is not valid for this target
    |
-   = help: valid names are: `avx512f`, `avx2`, `avx512bw`, `avx512cd`, and `avx512dq` and 75 more
+   = help: valid names are: `avx512f`, `avx2`, `avx512bw`, `avx512cd`, and `avx512dq` and 76 more
 
 error: aborting due to 26 previous errors
 
diff --git a/tests/ui/tool-attributes/invalid-tool.stderr b/tests/ui/tool-attributes/invalid-tool.stderr
index 0e06af5..499894a 100644
--- a/tests/ui/tool-attributes/invalid-tool.stderr
+++ b/tests/ui/tool-attributes/invalid-tool.stderr
@@ -1,4 +1,4 @@
-error[E0539]: malformed `register_tool` attribute input
+error[E0565]: malformed `register_tool` attribute input
   --> $DIR/invalid-tool.rs:3:1
    |
 LL | #![register_tool(1)]
@@ -14,4 +14,4 @@
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/tool-attributes/nested-disallowed.stderr b/tests/ui/tool-attributes/nested-disallowed.stderr
index 5e03697..3cc9c68 100644
--- a/tests/ui/tool-attributes/nested-disallowed.stderr
+++ b/tests/ui/tool-attributes/nested-disallowed.stderr
@@ -1,4 +1,4 @@
-error[E0539]: malformed `register_tool` attribute input
+error[E0565]: malformed `register_tool` attribute input
   --> $DIR/nested-disallowed.rs:2:1
    |
 LL | #![register_tool(foo::bar)]
@@ -14,4 +14,4 @@
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
index cc5a4af..3f5511d 100644
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
+++ b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
@@ -12,10 +12,6 @@
    |
    = note: expected unit type `()`
                    found enum `Result<(), std::fmt::Error>`
-help: consider using a semicolon here
-   |
-LL |     };
-   |      +
 help: you might have meant to return this value
    |
 LL |         return writeln!(w, "but not here");
@@ -42,10 +38,6 @@
    = note: expected unit type `()`
                    found enum `Result<(), std::fmt::Error>`
    = note: this error originates in the macro `writeln` which comes from the expansion of the macro `baz` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider using a semicolon here
-   |
-LL |     };
-   |      +
 help: you might have meant to return this value
    |
 LL |         return baz!(w);
diff --git a/tests/ui/typeck/question-mark-operator-suggestion-span.stderr b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
index f567e55..e447646 100644
--- a/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
+++ b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
@@ -12,10 +12,6 @@
    |
    = note: expected unit type `()`
                    found enum `Result<(), std::fmt::Error>`
-help: consider using a semicolon here
-   |
-LL |     };
-   |      +
 help: you might have meant to return this value
    |
 LL |         return writeln!(w, "but not here");
diff --git a/tests/ui/issues/issue-16562.rs b/tests/ui/typeck/unconstrained-impl-extra-parameter.rs
similarity index 79%
rename from tests/ui/issues/issue-16562.rs
rename to tests/ui/typeck/unconstrained-impl-extra-parameter.rs
index e16a351..abc62d4 100644
--- a/tests/ui/issues/issue-16562.rs
+++ b/tests/ui/typeck/unconstrained-impl-extra-parameter.rs
@@ -1,3 +1,5 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16562>.
+
 trait MatrixShape {}
 
 struct Col<D, C> {
diff --git a/tests/ui/issues/issue-16562.stderr b/tests/ui/typeck/unconstrained-impl-extra-parameter.stderr
similarity index 87%
rename from tests/ui/issues/issue-16562.stderr
rename to tests/ui/typeck/unconstrained-impl-extra-parameter.stderr
index ac957fd..bafdae9 100644
--- a/tests/ui/issues/issue-16562.stderr
+++ b/tests/ui/typeck/unconstrained-impl-extra-parameter.stderr
@@ -1,5 +1,5 @@
 error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-16562.rs:10:6
+  --> $DIR/unconstrained-impl-extra-parameter.rs:12:6
    |
 LL | impl<T, M: MatrixShape> Collection for Col<M, usize> {
    |      ^--
diff --git a/tests/ui/issues/issue-16739.rs b/tests/ui/unboxed-closures/rust-call-shim-through-trait-box.rs
similarity index 85%
rename from tests/ui/issues/issue-16739.rs
rename to tests/ui/unboxed-closures/rust-call-shim-through-trait-box.rs
index 39cc1b7..0c2a9ce 100644
--- a/tests/ui/issues/issue-16739.rs
+++ b/tests/ui/unboxed-closures/rust-call-shim-through-trait-box.rs
@@ -1,9 +1,10 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/16739>.
+//! Test that unboxing shim for calling rust-call ABI methods through a
+//! trait box works and does not cause an ICE.
+
 //@ run-pass
 #![feature(unboxed_closures, fn_traits)]
 
-// Test that unboxing shim for calling rust-call ABI methods through a
-// trait box works and does not cause an ICE.
-
 struct Foo { foo: u32 }
 
 impl FnMut<()> for Foo {
diff --git a/triagebot.toml b/triagebot.toml
index 8c9702c..57a6119 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -777,6 +777,10 @@
 PR #{number} "{title}" fixes a regression and has been nominated for backport.
 {recipients}, what do you think about it?
 This topic will help T-compiler getting context about it.
+
+Tip: to approve or decline from this Zulip thread, use:
+@_**triagebot** backport approve beta #{number}
+@_**triagebot** backport decline beta #{number}
 """,
     """\
 /poll Should #{number} be beta backported?
@@ -802,6 +806,11 @@
     """\
 PR #{number} "{title}" fixes a regression and has been nominated for backport.
 {recipients}, what do you think about it?
+This topic will help T-compiler getting context about it.
+
+Tip: to approve or decline from this Zulip thread, use:
+@_**triagebot** backport approve stable #{number}
+@_**triagebot** backport decline stable #{number}
 """,
     """\
 /poll Approve stable backport of #{number}?