diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 7bffeaf4cc9e..f5555488a2e1 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -215,7 +215,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
     >(
         &self,
         local_layouts: &IndexSlice<LocalIdx, F>,
-        prefix_layouts: IndexVec<FieldIdx, F>,
+        relocated_upvars: &IndexSlice<LocalIdx, Option<LocalIdx>>,
         variant_fields: &IndexSlice<VariantIdx, IndexVec<FieldIdx, LocalIdx>>,
         storage_conflicts: &BitMatrix<LocalIdx, LocalIdx>,
         tag_to_layout: impl Fn(Scalar) -> F,
@@ -223,7 +223,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         coroutine::layout(
             self,
             local_layouts,
-            prefix_layouts,
+            relocated_upvars,
             variant_fields,
             storage_conflicts,
             tag_to_layout,
diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs
index 27e704d538c8..352b3a91d2dd 100644
--- a/compiler/rustc_abi/src/layout/coroutine.rs
+++ b/compiler/rustc_abi/src/layout/coroutine.rs
@@ -145,7 +145,7 @@ pub(super) fn layout<
 >(
     calc: &super::LayoutCalculator<impl HasDataLayout>,
     local_layouts: &IndexSlice<LocalIdx, F>,
-    mut prefix_layouts: IndexVec<FieldIdx, F>,
+    relocated_upvars: &IndexSlice<LocalIdx, Option<LocalIdx>>,
     variant_fields: &IndexSlice<VariantIdx, IndexVec<FieldIdx, LocalIdx>>,
     storage_conflicts: &BitMatrix<LocalIdx, LocalIdx>,
     tag_to_layout: impl Fn(Scalar) -> F,
@@ -155,10 +155,8 @@ pub(super) fn layout<
     let (ineligible_locals, assignments) =
         coroutine_saved_local_eligibility(local_layouts.len(), variant_fields, storage_conflicts);
 
-    // Build a prefix layout, including "promoting" all ineligible
-    // locals as part of the prefix. We compute the layout of all of
-    // these fields at once to get optimal packing.
-    let tag_index = prefix_layouts.len();
+    // Build a prefix layout, consisting of only the state tag.
+    let tag_index = 0;
 
     // `variant_fields` already accounts for the reserved variants, so no need to add them.
     let max_discr = (variant_fields.len() - 1) as u128;
@@ -169,17 +167,17 @@ pub(super) fn layout<
     };
 
     let promoted_layouts = ineligible_locals.iter().map(|local| local_layouts[local]);
-    prefix_layouts.push(tag_to_layout(tag));
-    prefix_layouts.extend(promoted_layouts);
+    let prefix_layouts: IndexVec<_, _> =
+        [tag_to_layout(tag)].into_iter().chain(promoted_layouts).collect();
     let prefix =
         calc.univariant(&prefix_layouts, &ReprOptions::default(), StructKind::AlwaysSized)?;
 
     let (prefix_size, prefix_align) = (prefix.size, prefix.align);
 
-    // Split the prefix layout into the "outer" fields (upvars and
-    // discriminant) and the "promoted" fields. Promoted fields will
-    // get included in each variant that requested them in
-    // CoroutineLayout.
+    // Split the prefix layout into the discriminant and
+    // the "promoted" fields.
+    // Promoted fields will get included in each variant
+    // that requested them in CoroutineLayout.
     debug!("prefix = {:#?}", prefix);
     let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
         FieldsShape::Arbitrary { mut offsets, memory_index } => {
@@ -218,19 +216,45 @@ pub(super) fn layout<
     let variants = variant_fields
         .iter_enumerated()
         .map(|(index, variant_fields)| {
+            let is_unresumed = index == VariantIdx::new(0);
+            let mut is_ineligible = IndexVec::from_elem_n(None, variant_fields.len());
+            for (field, &local) in variant_fields.iter_enumerated() {
+                if is_unresumed {
+                    // NOTE(@dingxiangfei2009): rewrite this when let-chain #53667
+                    // is stabilized
+                    if let Some(inner_local) = relocated_upvars[local] {
+                        if let Ineligible(Some(promoted_field)) = assignments[inner_local] {
+                            is_ineligible.insert(field, promoted_field);
+                            continue;
+                        }
+                    }
+                }
+                match assignments[local] {
+                    Assigned(v) if v == index => {}
+                    Ineligible(Some(promoted_field)) => {
+                        is_ineligible.insert(field, promoted_field);
+                    }
+                    Ineligible(None) => {
+                        panic!("an ineligible local should have been promoted into the prefix")
+                    }
+                    Assigned(_) => {
+                        panic!("an eligible local should have been assigned to exactly one variant")
+                    }
+                    Unassigned => {
+                        panic!("each saved local should have been inspected at least once")
+                    }
+                }
+            }
             // Only include overlap-eligible fields when we compute our variant layout.
-            let variant_only_tys = variant_fields
-                .iter()
-                .filter(|local| match assignments[**local] {
-                    Unassigned => unreachable!(),
-                    Assigned(v) if v == index => true,
-                    Assigned(_) => unreachable!("assignment does not match variant"),
-                    Ineligible(_) => false,
+            let fields: IndexVec<_, _> = variant_fields
+                .iter_enumerated()
+                .filter_map(|(field, &local)| {
+                    if is_ineligible.contains(field) { None } else { Some(local_layouts[local]) }
                 })
-                .map(|local| local_layouts[*local]);
+                .collect();
 
             let mut variant = calc.univariant(
-                &variant_only_tys.collect::<IndexVec<_, _>>(),
+                &fields,
                 &ReprOptions::default(),
                 StructKind::Prefixed(prefix_size, prefix_align.abi),
             )?;
@@ -254,19 +278,14 @@ pub(super) fn layout<
                 IndexVec::from_elem_n(FieldIdx::new(invalid_field_idx), invalid_field_idx);
 
             let mut offsets_and_memory_index = iter::zip(offsets, memory_index);
-            let combined_offsets = variant_fields
+            let combined_offsets = is_ineligible
                 .iter_enumerated()
-                .map(|(i, local)| {
-                    let (offset, memory_index) = match assignments[*local] {
-                        Unassigned => unreachable!(),
-                        Assigned(_) => {
-                            let (offset, memory_index) = offsets_and_memory_index.next().unwrap();
-                            (offset, promoted_memory_index.len() as u32 + memory_index)
-                        }
-                        Ineligible(field_idx) => {
-                            let field_idx = field_idx.unwrap();
-                            (promoted_offsets[field_idx], promoted_memory_index[field_idx])
-                        }
+                .map(|(i, &is_ineligible)| {
+                    let (offset, memory_index) = if let Some(field_idx) = is_ineligible {
+                        (promoted_offsets[field_idx], promoted_memory_index[field_idx])
+                    } else {
+                        let (offset, memory_index) = offsets_and_memory_index.next().unwrap();
+                        (offset, promoted_memory_index.len() as u32 + memory_index)
                     };
                     combined_inverse_memory_index[memory_index] = i;
                     offset
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 3951b467961a..90edf53f1305 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -393,49 +393,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
                 ));
 
-                let captured_place = self.upvars[upvar_index.index()];
-
-                err.span_label(span, format!("cannot {act}"));
-
-                let upvar_hir_id = captured_place.get_root_variable();
-
-                if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id)
-                    && let hir::PatKind::Binding(hir::BindingMode::NONE, _, upvar_ident, _) =
-                        pat.kind
-                {
-                    if upvar_ident.name == kw::SelfLower {
-                        for (_, node) in self.infcx.tcx.hir_parent_iter(upvar_hir_id) {
-                            if let Some(fn_decl) = node.fn_decl() {
-                                if !matches!(
-                                    fn_decl.implicit_self,
-                                    hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut
-                                ) {
-                                    err.span_suggestion_verbose(
-                                        upvar_ident.span.shrink_to_lo(),
-                                        "consider changing this to be mutable",
-                                        "mut ",
-                                        Applicability::MachineApplicable,
-                                    );
-                                    break;
-                                }
-                            }
-                        }
-                    } else {
-                        err.span_suggestion_verbose(
-                            upvar_ident.span.shrink_to_lo(),
-                            "consider changing this to be mutable",
-                            "mut ",
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                }
+                self.suggest_mutable_upvar(*upvar_index, the_place_err, &mut err, span, act);
+            }
 
-                let tcx = self.infcx.tcx;
-                if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind()
-                    && let ty::Closure(id, _) = *ty.kind()
-                {
-                    self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
-                }
+            PlaceRef { local, projection: [] }
+                if let Some(upvar_index) = self
+                    .body
+                    .local_upvar_map
+                    .iter_enumerated()
+                    .filter_map(|(field, &local)| local.map(|local| (field, local)))
+                    .find_map(|(field, relocated)| (relocated == local).then_some(field)) =>
+            {
+                self.suggest_mutable_upvar(upvar_index, the_place_err, &mut err, span, act);
             }
 
             // complete hack to approximate old AST-borrowck
@@ -542,6 +511,58 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
     }
 
+    fn suggest_mutable_upvar(
+        &self,
+        upvar_index: FieldIdx,
+        the_place_err: PlaceRef<'tcx>,
+        err: &mut Diag<'infcx>,
+        span: Span,
+        act: &str,
+    ) {
+        let captured_place = self.upvars[upvar_index.index()];
+
+        err.span_label(span, format!("cannot {act}"));
+
+        let upvar_hir_id = captured_place.get_root_variable();
+
+        if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id)
+            && let hir::PatKind::Binding(hir::BindingMode::NONE, _, upvar_ident, _) = pat.kind
+        {
+            if upvar_ident.name == kw::SelfLower {
+                for (_, node) in self.infcx.tcx.hir_parent_iter(upvar_hir_id) {
+                    if let Some(fn_decl) = node.fn_decl() {
+                        if !matches!(
+                            fn_decl.implicit_self,
+                            hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut
+                        ) {
+                            err.span_suggestion_verbose(
+                                upvar_ident.span.shrink_to_lo(),
+                                "consider changing this to be mutable",
+                                "mut ",
+                                Applicability::MachineApplicable,
+                            );
+                            break;
+                        }
+                    }
+                }
+            } else {
+                err.span_suggestion_verbose(
+                    upvar_ident.span.shrink_to_lo(),
+                    "consider changing this to be mutable",
+                    "mut ",
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+
+        let tcx = self.infcx.tcx;
+        if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind()
+            && let ty::Closure(id, _) = *ty.kind()
+        {
+            self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, err);
+        }
+    }
+
     /// Suggest `map[k] = v` => `map.insert(k, v)` and the like.
     fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'infcx>, span: Span) {
         let Some(adt) = ty.ty_adt_def() else { return };
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 07b3f3477a84..c27bb6b6b595 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
+use rustc_data_structures::unord::UnordMap;
 use rustc_errors::LintDiagnostic;
 use rustc_hir as hir;
 use rustc_hir::CRATE_HIR_ID;
@@ -261,6 +262,7 @@ fn do_mir_borrowck<'tcx>(
             regioncx: &regioncx,
             used_mut: Default::default(),
             used_mut_upvars: SmallVec::new(),
+            local_from_upvars: UnordMap::default(),
             borrow_set: &borrow_set,
             upvars: &[],
             local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
@@ -286,6 +288,11 @@ fn do_mir_borrowck<'tcx>(
         promoted_mbcx.report_move_errors();
     }
 
+    let mut local_from_upvars = UnordMap::default();
+    for (field, &local) in body.local_upvar_map.iter_enumerated() {
+        let Some(local) = local else { continue };
+        local_from_upvars.insert(local, field);
+    }
     let mut mbcx = MirBorrowckCtxt {
         infcx: &infcx,
         body,
@@ -300,6 +307,7 @@ fn do_mir_borrowck<'tcx>(
         regioncx: &regioncx,
         used_mut: Default::default(),
         used_mut_upvars: SmallVec::new(),
+        local_from_upvars,
         borrow_set: &borrow_set,
         upvars: tcx.closure_captures(def),
         local_names,
@@ -555,6 +563,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
     /// If the function we're checking is a closure, then we'll need to report back the list of
     /// mutable upvars that have been used. This field keeps track of them.
     used_mut_upvars: SmallVec<[FieldIdx; 8]>,
+    /// Since upvars are moved to real locals, we need to map mutations to the locals back to
+    /// the upvars, so that used_mut_upvars is up-to-date.
+    local_from_upvars: UnordMap<Local, FieldIdx>,
     /// Region inference context. This contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
     regioncx: &'a RegionInferenceContext<'tcx>,
@@ -2265,7 +2276,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
 
         // at this point, we have set up the error reporting state.
         if let Some(init_index) = previously_initialized {
-            if let (AccessKind::Mutate, Some(_)) = (error_access, place.as_local()) {
+            if let (AccessKind::Mutate, Some(local)) = (error_access, place.as_local())
+                && self.body.local_upvar_map.iter().flatten().all(|upvar| upvar != &local)
+            {
                 // If this is a mutate access to an immutable local variable with no projections
                 // report the error as an illegal reassignment
                 let init = &self.move_data.inits[init_index];
@@ -2293,10 +2306,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                 // If the local may have been initialized, and it is now currently being
                 // mutated, then it is justified to be annotated with the `mut`
                 // keyword, since the mutation may be a possible reassignment.
-                if is_local_mutation_allowed != LocalMutationIsAllowed::Yes
-                    && self.is_local_ever_initialized(local, state).is_some()
-                {
-                    self.used_mut.insert(local);
+                if !matches!(is_local_mutation_allowed, LocalMutationIsAllowed::Yes) {
+                    if self.is_local_ever_initialized(local, state).is_some() {
+                        self.used_mut.insert(local);
+                    } else if let Some(&field) = self.local_from_upvars.get(&local) {
+                        self.used_mut_upvars.push(field);
+                    }
                 }
             }
             RootPlace {
@@ -2314,6 +2329,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                     projection: place_projection,
                 }) {
                     self.used_mut_upvars.push(field);
+                } else if let Some(&field) = self.local_from_upvars.get(&place_local) {
+                    self.used_mut_upvars.push(field);
                 }
             }
         }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0fda3e31690d..ea317519cf78 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -25,9 +25,9 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::{
-    self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
-    Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt,
-    TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
+    self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
+    GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
+    UserArgs, UserTypeAnnotationIndex, fold_regions,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::ResultsCursor;
@@ -2188,14 +2188,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
             AggregateKind::Coroutine(_, args) => {
-                // It doesn't make sense to look at a field beyond the prefix;
-                // these require a variant index, and are not initialized in
-                // aggregate rvalues.
-                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_coroutine().prefix_tys().len(),
-                    }),
+                // It doesn't make sense to look at a field beyond the captured
+                // upvars.
+                // Otherwise it require a variant index, and are not initialized
+                // in aggregate rvalues.
+                let upvar_tys = &args.as_coroutine().upvar_tys();
+                if let Some(ty) = upvar_tys.get(field_index.as_usize()) {
+                    Ok(*ty)
+                } else {
+                    Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() })
                 }
             }
             AggregateKind::CoroutineClosure(_, args) => {
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 125a9201831c..2da493516cf3 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -915,6 +915,9 @@ fn codegen_stmt<'tcx>(
                             let variant_dest = lval.downcast_variant(fx, variant_index);
                             (variant_index, variant_dest, active_field_index)
                         }
+                        mir::AggregateKind::Coroutine(_def_id, _args) => {
+                            (FIRST_VARIANT, lval.downcast_variant(fx, FIRST_VARIANT), None)
+                        }
                         _ => (FIRST_VARIANT, lval, None),
                     };
                     if active_field_index.is_some() {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 98d59f5a8ae0..c3c0769b3242 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -14,9 +14,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::layout::{
     HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
 };
-use rustc_middle::ty::{
-    self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
-};
+use rustc_middle::ty::{self, AdtKind, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility};
 use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene};
 use rustc_symbol_mangling::typeid_for_trait_ref;
@@ -1101,7 +1099,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
     closure_or_coroutine_di_node: &'ll DIType,
 ) -> SmallVec<&'ll DIType> {
     let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() {
-        ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()),
+        ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().upvar_tys()),
         ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
         ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()),
         _ => {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index a72e205c9b24..5d82a2b00670 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -724,7 +724,6 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
     let coroutine_layout =
         cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
 
-    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
     let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
     let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
 
@@ -764,7 +763,6 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
                 coroutine_type_and_layout,
                 coroutine_type_di_node,
                 coroutine_layout,
-                common_upvar_names,
             );
 
             let span = coroutine_layout.variant_source_info[variant_index].span;
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 9f6a5cc89e02..ed3561faaf2f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -5,12 +5,10 @@ use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
 use rustc_codegen_ssa::traits::MiscCodegenMethods;
 use rustc_hir::def::CtorKind;
-use rustc_index::IndexSlice;
 use rustc_middle::bug;
 use rustc_middle::mir::CoroutineLayout;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef};
-use rustc_span::Symbol;
 
 use super::type_map::{DINodeCreationResult, UniqueTypeId};
 use super::{SmallVec, size_and_align_of};
@@ -286,7 +284,6 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
     coroutine_type_and_layout: TyAndLayout<'tcx>,
     coroutine_type_di_node: &'ll DIType,
     coroutine_layout: &CoroutineLayout<'tcx>,
-    common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
 ) -> &'ll DIType {
     let variant_name = CoroutineArgs::variant_name(variant_index);
     let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
@@ -297,11 +294,6 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
 
     let variant_layout = coroutine_type_and_layout.for_variant(cx, variant_index);
 
-    let coroutine_args = match coroutine_type_and_layout.ty.kind() {
-        ty::Coroutine(_, args) => args.as_coroutine(),
-        _ => unreachable!(),
-    };
-
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -316,7 +308,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
         ),
         |cx, variant_struct_type_di_node| {
             // Fields that just belong to this variant/state
-            let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count())
+            (0..variant_layout.fields.count())
                 .map(|field_index| {
                     let coroutine_saved_local = coroutine_layout.variant_fields[variant_index]
                         [FieldIdx::from_usize(field_index)];
@@ -339,29 +331,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
                         None,
                     )
                 })
-                .collect();
-
-            // Fields that are common to all states
-            let common_fields: SmallVec<_> = coroutine_args
-                .prefix_tys()
-                .iter()
-                .zip(common_upvar_names)
-                .enumerate()
-                .map(|(index, (upvar_ty, upvar_name))| {
-                    build_field_di_node(
-                        cx,
-                        variant_struct_type_di_node,
-                        upvar_name.as_str(),
-                        cx.size_and_align_of(upvar_ty),
-                        coroutine_type_and_layout.fields.offset(index),
-                        DIFlags::FlagZero,
-                        type_di_node(cx, upvar_ty),
-                        None,
-                    )
-                })
-                .collect();
-
-            state_specific_fields.into_iter().chain(common_fields).collect()
+                .collect()
         },
         |cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
     )
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 187d97c54c87..69489480ced3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -188,9 +188,6 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
                 )
             };
 
-            let common_upvar_names =
-                cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
-
             // Build variant struct types
             let variant_struct_type_di_nodes: SmallVec<_> = variants
                 .indices()
@@ -218,7 +215,6 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
                                 coroutine_type_and_layout,
                                 coroutine_type_di_node,
                                 coroutine_layout,
-                                common_upvar_names,
                             ),
                         source_info,
                     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 7e355b6406ae..beb7fcc689c2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -701,13 +701,12 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
 }
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
+    #[instrument(level = "debug", skip(self, bx), ret)]
     fn maybe_codegen_consume_direct(
         &mut self,
         bx: &mut Bx,
         place_ref: mir::PlaceRef<'tcx>,
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
-        debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
-
         match self.locals[place_ref.local] {
             LocalRef::Operand(mut o) => {
                 // Moves out of scalar and scalar pair fields are trivial.
@@ -750,13 +749,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self, bx), ret)]
     pub fn codegen_consume(
         &mut self,
         bx: &mut Bx,
         place_ref: mir::PlaceRef<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
-        debug!("codegen_consume(place_ref={:?})", place_ref);
-
         let ty = self.monomorphized_place_ty(place_ref);
         let layout = bx.cx().layout_of(ty);
 
@@ -775,13 +773,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         bx.load_operand(place)
     }
 
+    #[instrument(level = "debug", skip(self, bx), ret)]
     pub fn codegen_operand(
         &mut self,
         bx: &mut Bx,
         operand: &mir::Operand<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
-        debug!("codegen_operand(operand={:?})", operand);
-
         match *operand {
             mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => {
                 self.codegen_consume(bx, place.as_ref())
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 96be44ee09ff..aacf17629e78 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -144,6 +144,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let variant_dest = dest.project_downcast(bx, variant_index);
                         (variant_index, variant_dest, active_field_index)
                     }
+                    mir::AggregateKind::Coroutine(_, _) => {
+                        (FIRST_VARIANT, dest.project_downcast(bx, FIRST_VARIANT), None)
+                    }
                     _ => (FIRST_VARIANT, dest, None),
                 };
                 if active_field_index.is_some() {
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index ddf2d65914f6..e917c353e330 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -305,6 +305,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let variant_dest = self.project_downcast(dest, variant_index)?;
                 (variant_index, variant_dest, active_field_index)
             }
+            mir::AggregateKind::Coroutine(_def_id, _args) => {
+                (FIRST_VARIANT, self.project_downcast(dest, FIRST_VARIANT)?, None)
+            }
             mir::AggregateKind::RawPtr(..) => {
                 // Pointers don't have "fields" in the normal sense, so the
                 // projection-based code below would either fail in projection
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 13f0dda180be..90eb212e69bf 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -197,6 +197,11 @@ impl<I: Idx, T> IndexVec<I, T> {
     pub fn append(&mut self, other: &mut Self) {
         self.raw.append(&mut other.raw);
     }
+
+    #[inline]
+    pub fn debug_map_view(&self) -> IndexSliceMapView<'_, I, T> {
+        IndexSliceMapView(self.as_slice())
+    }
 }
 
 /// `IndexVec` is often used as a map, so it provides some map-like APIs.
@@ -220,14 +225,44 @@ impl<I: Idx, T> IndexVec<I, Option<T>> {
     pub fn contains(&self, index: I) -> bool {
         self.get(index).and_then(Option::as_ref).is_some()
     }
+
+    #[inline]
+    pub fn debug_map_view_compact(&self) -> IndexSliceMapViewCompact<'_, I, T> {
+        IndexSliceMapViewCompact(self.as_slice())
+    }
 }
 
+pub struct IndexSliceMapView<'a, I: Idx, T>(&'a IndexSlice<I, T>);
+pub struct IndexSliceMapViewCompact<'a, I: Idx, T>(&'a IndexSlice<I, Option<T>>);
+
 impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.raw, fmt)
     }
 }
 
+impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapView<'a, I, T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut entries = fmt.debug_map();
+        for (idx, val) in self.0.iter_enumerated() {
+            entries.entry(&idx, val);
+        }
+        entries.finish()
+    }
+}
+
+impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapViewCompact<'a, I, T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut entries = fmt.debug_map();
+        for (idx, val) in self.0.iter_enumerated() {
+            if let Some(val) = val {
+                entries.entry(&idx, val);
+            }
+        }
+        entries.finish()
+    }
+}
+
 impl<I: Idx, T> Deref for IndexVec<I, T> {
     type Target = IndexSlice<I, T>;
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7090e93549e6..31e13d68a917 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -367,6 +367,9 @@ pub struct Body<'tcx> {
     #[type_foldable(identity)]
     #[type_visitable(ignore)]
     pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
+
+    /// Coroutine local-upvar map
+    pub local_upvar_map: IndexVec<FieldIdx, Option<Local>>,
 }
 
 impl<'tcx> Body<'tcx> {
@@ -410,6 +413,7 @@ impl<'tcx> Body<'tcx> {
             tainted_by_errors,
             coverage_info_hi: None,
             function_coverage_info: None,
+            local_upvar_map: IndexVec::new(),
         };
         body.is_polymorphic = body.has_non_region_param();
         body
@@ -441,6 +445,7 @@ impl<'tcx> Body<'tcx> {
             tainted_by_errors: None,
             coverage_info_hi: None,
             function_coverage_info: None,
+            local_upvar_map: IndexVec::new(),
         };
         body.is_polymorphic = body.has_non_region_param();
         body
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 5a9fe10938ae..3b1ec30e455e 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -10,6 +10,7 @@ use rustc_index::bit_set::BitMatrix;
 use rustc_index::{Idx, IndexVec};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_span::{Span, Symbol};
+use rustc_type_ir::data_structures::IndexMap;
 use smallvec::SmallVec;
 
 use super::{ConstValue, SourceInfo};
@@ -18,7 +19,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regio
 rustc_index::newtype_index! {
     #[derive(HashStable)]
     #[encodable]
-    #[debug_format = "_{}"]
+    #[debug_format = "corsl_{}"]
     pub struct CoroutineSavedLocal {}
 }
 
@@ -56,6 +57,13 @@ pub struct CoroutineLayout<'tcx> {
     #[type_foldable(identity)]
     #[type_visitable(ignore)]
     pub storage_conflicts: BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
+
+    /// This map `A -> B` allows later MIR passes, error reporters
+    /// and layout calculator to relate saved locals `A` sourced from upvars
+    /// and locals `B` that upvars are moved into.
+    #[type_foldable(identity)]
+    #[type_visitable(ignore)]
+    pub relocated_upvars: IndexMap<CoroutineSavedLocal, CoroutineSavedLocal>,
 }
 
 impl Debug for CoroutineLayout<'_> {
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index f05a798949b7..57355febcd04 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -123,11 +123,10 @@ impl<'tcx> PlaceTy<'tcx> {
                     .get(f.index())
                     .copied()
                     .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                // Only prefix fields (upvars and current state) are
-                // accessible without a variant index.
+                // Only upvars are accessible without a variant index.
                 ty::Coroutine(_, args) => args
                     .as_coroutine()
-                    .prefix_tys()
+                    .upvar_tys()
                     .get(f.index())
                     .copied()
                     .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index ebb6a8c08a54..48e6efc0c0ca 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -935,9 +935,10 @@ where
                     ),
                     Variants::Multiple { tag, tag_field, .. } => {
                         if i == tag_field {
-                            return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
+                            TyMaybeWithLayout::TyAndLayout(tag_layout(tag))
+                        } else {
+                            TyMaybeWithLayout::Ty(args.as_coroutine().upvar_tys()[i])
                         }
-                        TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
                     }
                 },
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 74a94d827845..9a86cb114b31 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -145,13 +145,6 @@ impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
             })
         })
     }
-
-    /// This is the types of the fields of a coroutine which are not stored in a
-    /// variant.
-    #[inline]
-    fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
-        self.upvar_tys()
-    }
 }
 
 #[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs
index bfc16816e2e5..2b29434efe54 100644
--- a/compiler/rustc_mir_build/src/builder/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs
@@ -61,6 +61,7 @@ pub(super) fn build_custom_mir<'tcx>(
         pass_count: 0,
         coverage_info_hi: None,
         function_coverage_info: None,
+        local_upvar_map: IndexVec::new(),
     };
 
     body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 04d96f117072..5927256c22d7 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -51,11 +51,15 @@
 //! Otherwise it drops all the values in scope at the last suspension point.
 
 mod by_move_body;
-use std::{iter, ops};
+mod relocate_upvars;
+
+use std::ops::Deref;
 
 pub(super) use by_move_body::coroutine_by_move_body_def_id;
+pub(super) use relocate_upvars::RelocateUpvars;
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::unord::UnordMap;
 use rustc_errors::pluralize;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
@@ -65,7 +69,8 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{
-    self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
+    self, CapturedPlace, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt,
+    TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
@@ -92,6 +97,8 @@ struct RenameLocalVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
 }
 
+const VARIANT_UNRESUMED: VariantIdx = VariantIdx::from_usize(CoroutineArgs::UNRESUMED);
+
 impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
@@ -187,8 +194,11 @@ struct TransformVisitor<'tcx> {
     // A map from a suspension point in a block to the locals which have live storage at that point
     storage_liveness: IndexVec<BasicBlock, Option<DenseBitSet<Local>>>,
 
+    // A rev-lookup from basic blocks with yielding terminator to the suspension point index,
+    suspension_point_at_block: UnordMap<BasicBlock, SuspensionPointIdx>,
+
     // A list of suspension points, generated during the transform
-    suspension_points: Vec<SuspensionPoint<'tcx>>,
+    suspension_points: IndexVec<SuspensionPointIdx, Option<SuspensionPoint<'tcx>>>,
 
     // The set of locals that have no `StorageLive`/`StorageDead` annotations.
     always_live_locals: DenseBitSet<Local>,
@@ -388,6 +398,16 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
         // Replace an Local in the remap with a coroutine struct access
         if let Some(&Some((ty, variant_index, idx))) = self.remap.get(place.local) {
             replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
+        } else if let Place { local: ty::CAPTURE_STRUCT_LOCAL, projection } = *place
+            && let [first @ ProjectionElem::Field(..), rest @ ..] = &**projection
+        {
+            let projections: Vec<_> = [ProjectionElem::Downcast(None, VARIANT_UNRESUMED), *first]
+                .into_iter()
+                .chain(rest.iter().copied())
+                .collect();
+            let new_place =
+                Place::from(ty::CAPTURE_STRUCT_LOCAL).project_deeper(&projections, self.tcx);
+            *place = new_place;
         }
     }
 
@@ -416,8 +436,9 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
             // We must assign the value first in case it gets declared dead below
             self.make_state(v, source_info, is_return, &mut data.statements);
             let state = if let Some((resume, mut resume_arg)) = resume {
-                // Yield
-                let state = CoroutineArgs::RESERVED_VARIANTS + self.suspension_points.len();
+                // This is a `yield`
+                let suspension_point_idx = *self.suspension_point_at_block.get(&block).unwrap();
+                let state = CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx.as_usize();
 
                 // The resume arg target location might itself be remapped if its base local is
                 // live across a yield.
@@ -439,12 +460,8 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
                     }
                 }
 
-                self.suspension_points.push(SuspensionPoint {
-                    state,
-                    resume,
-                    resume_arg,
-                    drop,
-                    storage_liveness,
+                self.suspension_points.get_or_insert_with(suspension_point_idx, || {
+                    SuspensionPoint { state, resume, resume_arg, drop, storage_liveness }
                 });
 
                 VariantIdx::new(state)
@@ -470,19 +487,19 @@ fn make_aggregate_adt<'tcx>(
 }
 
 fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let coroutine_ty = body.local_decls.raw[1].ty;
+    let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
     let ref_coroutine_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty);
 
     // Replace the by value coroutine argument
-    body.local_decls.raw[1].ty = ref_coroutine_ty;
+    body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = ref_coroutine_ty;
 
     // Add a deref to accesses of the coroutine state
     SelfArgVisitor::new(tcx, ProjectionElem::Deref).visit_body(body);
 }
 
 fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let ref_coroutine_ty = body.local_decls.raw[1].ty;
+    let ref_coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
     let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span));
     let pin_adt_ref = tcx.adt_def(pin_did);
@@ -490,7 +507,7 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
     let pin_ref_coroutine_ty = Ty::new_adt(tcx, pin_adt_ref, args);
 
     // Replace the by ref coroutine argument
-    body.local_decls.raw[1].ty = pin_ref_coroutine_ty;
+    body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = pin_ref_coroutine_ty;
 
     // Add the Pin field access to accesses of the coroutine state
     SelfArgVisitor::new(tcx, ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty))
@@ -629,15 +646,20 @@ fn transform_gen_context<'tcx>(body: &mut Body<'tcx>) {
     body.arg_count = 1;
 }
 
+#[derive(Debug)]
 struct LivenessInfo {
     /// Which locals are live across any suspension point.
     saved_locals: CoroutineSavedLocals,
 
+    /// Always live locals
+    always_live_locals: DenseBitSet<Local>,
+
     /// The set of saved locals live at each suspension point.
-    live_locals_at_suspension_points: Vec<DenseBitSet<CoroutineSavedLocal>>,
+    live_locals_at_suspension_points:
+        IndexVec<SuspensionPointIdx, DenseBitSet<CoroutineSavedLocal>>,
 
     /// Parallel vec to the above with SourceInfo for each yield terminator.
-    source_info_at_suspension_points: Vec<SourceInfo>,
+    source_info_at_suspension_points: IndexVec<SuspensionPointIdx, SourceInfo>,
 
     /// For every saved local, the set of other saved locals that are
     /// storage-live at the same time as this local. We cannot overlap locals in
@@ -647,6 +669,14 @@ struct LivenessInfo {
     /// For every suspending block, the locals which are storage-live across
     /// that suspension point.
     storage_liveness: IndexVec<BasicBlock, Option<DenseBitSet<Local>>>,
+
+    /// A rev-lookup of basic blocks to the suspension point index
+    suspension_point_at_block: UnordMap<BasicBlock, SuspensionPointIdx>,
+}
+
+rustc_index::newtype_index! {
+    #[debug_format = "suspend_{}"]
+    struct SuspensionPointIdx {}
 }
 
 /// Computes which locals have to be stored in the state-machine for the
@@ -660,12 +690,12 @@ struct LivenessInfo {
 fn locals_live_across_suspend_points<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
-    always_live_locals: &DenseBitSet<Local>,
+    always_live_locals: DenseBitSet<Local>,
     movable: bool,
 ) -> LivenessInfo {
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
-    let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
+    let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(&always_live_locals))
         .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
@@ -687,11 +717,13 @@ fn locals_live_across_suspend_points<'tcx>(
         MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body);
 
     let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
-    let mut live_locals_at_suspension_points = Vec::new();
-    let mut source_info_at_suspension_points = Vec::new();
+    let mut live_locals_at_suspension_points = IndexVec::<SuspensionPointIdx, _>::default();
+    let mut source_info_at_suspension_points = IndexVec::default();
     let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len());
+    let mut suspension_point_at_block = UnordMap::default();
 
-    for (block, data) in body.basic_blocks.iter_enumerated() {
+    for &block in body.basic_blocks.reverse_postorder() {
+        let data = &body.basic_blocks[block];
         if let TerminatorKind::Yield { .. } = data.terminator().kind {
             let loc = Location { block, statement_index: data.statements.len() };
 
@@ -725,7 +757,7 @@ fn locals_live_across_suspend_points<'tcx>(
             live_locals.intersect(requires_storage_cursor.get());
 
             // The coroutine argument is ignored.
-            live_locals.remove(SELF_ARG);
+            live_locals.remove(ty::CAPTURE_STRUCT_LOCAL);
 
             debug!("loc = {:?}, live_locals = {:?}", loc, live_locals);
 
@@ -733,8 +765,9 @@ fn locals_live_across_suspend_points<'tcx>(
             // any suspension points
             live_locals_at_any_suspension_point.union(&live_locals);
 
-            live_locals_at_suspension_points.push(live_locals);
+            let idx = live_locals_at_suspension_points.push(live_locals);
             source_info_at_suspension_points.push(data.terminator().source_info);
+            suspension_point_at_block.insert(block, idx);
         }
     }
 
@@ -757,10 +790,12 @@ fn locals_live_across_suspend_points<'tcx>(
 
     LivenessInfo {
         saved_locals,
+        always_live_locals,
         live_locals_at_suspension_points,
         source_info_at_suspension_points,
         storage_conflicts,
         storage_liveness: storage_liveness_map,
+        suspension_point_at_block,
     }
 }
 
@@ -769,6 +804,7 @@ fn locals_live_across_suspend_points<'tcx>(
 /// `CoroutineSavedLocal` is indexed in terms of the elements in this set;
 /// i.e. `CoroutineSavedLocal::new(1)` corresponds to the second local
 /// included in this set.
+#[derive(Debug)]
 struct CoroutineSavedLocals(DenseBitSet<Local>);
 
 impl CoroutineSavedLocals {
@@ -801,7 +837,7 @@ impl CoroutineSavedLocals {
     }
 }
 
-impl ops::Deref for CoroutineSavedLocals {
+impl Deref for CoroutineSavedLocals {
     type Target = DenseBitSet<Local>;
 
     fn deref(&self) -> &Self::Target {
@@ -919,25 +955,39 @@ impl StorageConflictVisitor<'_, '_> {
     }
 }
 
+#[instrument[level = "debug", skip(body), fields(body = ?body.source)]]
 fn compute_layout<'tcx>(
     liveness: LivenessInfo,
     body: &Body<'tcx>,
+    upvar_tys: &[Ty<'tcx>],
+    upvar_infos: &[&CapturedPlace<'tcx>],
 ) -> (
     IndexVec<Local, Option<(Ty<'tcx>, VariantIdx, FieldIdx)>>,
     CoroutineLayout<'tcx>,
     IndexVec<BasicBlock, Option<DenseBitSet<Local>>>,
+    UnordMap<BasicBlock, SuspensionPointIdx>,
 ) {
     let LivenessInfo {
         saved_locals,
+        always_live_locals,
         live_locals_at_suspension_points,
         source_info_at_suspension_points,
         storage_conflicts,
         storage_liveness,
+        suspension_point_at_block,
     } = liveness;
 
+    // We need to later establish the map between upvars in UNRESUMED and locals in other states.
+    let local_upvar_map: UnordMap<_, _> = body
+        .local_upvar_map
+        .iter_enumerated()
+        .filter_map(|(field, local)| local.map(|local| (local, field)))
+        .collect();
+
     // Gather live local types and their indices.
     let mut locals = IndexVec::<CoroutineSavedLocal, _>::new();
     let mut tys = IndexVec::<CoroutineSavedLocal, _>::new();
+    let mut saved_local_upvar_map = UnordMap::default();
     for (saved_local, local) in saved_locals.iter_enumerated() {
         debug!("coroutine saved local {:?} => {:?}", saved_local, local);
 
@@ -965,7 +1015,52 @@ fn compute_layout<'tcx>(
         debug!(?decl);
 
         tys.push(decl);
+
+        if let Some(&field) = local_upvar_map.get(&local) {
+            saved_local_upvar_map.insert(field, saved_local);
+        }
     }
+    // These are the "saved locals" sourced from the UNRESUMED state.
+    let upvar_saved_locals: IndexVec<FieldIdx, CoroutineSavedLocal> = upvar_tys
+        .iter()
+        .zip(upvar_infos)
+        .map(|(&ty, info)| {
+            tys.push(CoroutineSavedTy {
+                ty,
+                source_info: SourceInfo::outermost(info.var_ident.span),
+                ignore_for_traits: false,
+            })
+        })
+        .collect();
+    debug!(?upvar_saved_locals);
+    let storage_conflicts = if let Some(&first) = upvar_saved_locals.raw.first()
+        && let Some(&last) = upvar_saved_locals.raw.last()
+    {
+        let mut enlarged_storage_conflicts = BitMatrix::new(tys.len(), tys.len());
+        let mut upvars = DenseBitSet::new_empty(tys.len());
+        let mut ineligibles = upvars.clone();
+        upvars.insert_range(first..=last);
+        for (saved_local, local) in saved_locals.iter_enumerated() {
+            if always_live_locals.contains(local) {
+                ineligibles.insert(saved_local);
+            }
+        }
+        upvars.union(&ineligibles);
+        for row in storage_conflicts.rows() {
+            for column in storage_conflicts.iter(row) {
+                enlarged_storage_conflicts.insert(row, column);
+            }
+        }
+        for &upvar in &upvar_saved_locals {
+            enlarged_storage_conflicts.union_row_with(&upvars, upvar);
+        }
+        for ineligible in ineligibles.iter() {
+            enlarged_storage_conflicts.union_row_with(&upvars, ineligible);
+        }
+        enlarged_storage_conflicts
+    } else {
+        storage_conflicts
+    };
 
     // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states.
     // In debuginfo, these will correspond to the beginning (UNRESUMED) or end
@@ -982,12 +1077,14 @@ fn compute_layout<'tcx>(
 
     // Build the coroutine variant field list.
     // Create a map from local indices to coroutine struct indices.
+    let variant_fields: [_; CoroutineArgs::RESERVED_VARIANTS] =
+        [upvar_saved_locals.clone(), IndexVec::new(), IndexVec::new()];
     let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
-        iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect();
+        variant_fields.into_iter().collect();
     let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size());
-    for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() {
+    for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter_enumerated() {
         let variant_index =
-            VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx);
+            VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx.as_usize());
         let mut fields = IndexVec::new();
         for (idx, saved_local) in live_locals.iter().enumerate() {
             fields.push(saved_local);
@@ -1003,29 +1100,42 @@ fn compute_layout<'tcx>(
     }
     debug!("coroutine variant_fields = {:?}", variant_fields);
     debug!("coroutine storage_conflicts = {:#?}", storage_conflicts);
+    debug!(remap = ?remap.debug_map_view_compact());
+    debug!(locals = ?locals.debug_map_view());
 
     let mut field_names = IndexVec::from_elem(None, &tys);
     for var in &body.var_debug_info {
-        let VarDebugInfoContents::Place(place) = &var.value else { continue };
-        let Some(local) = place.as_local() else { continue };
-        let Some(&Some((_, variant, field))) = remap.get(local) else {
-            continue;
-        };
-
-        let saved_local = variant_fields[variant][field];
-        field_names.get_or_insert_with(saved_local, || var.name);
+        debug!(?var);
+        if let VarDebugInfoContents::Place(place) = &var.value
+            && let Some(local) = place.local_or_deref_local()
+            && let Some(&Some((_, variant, field))) = remap.get(local)
+        {
+            let saved_local = variant_fields[variant][field];
+            field_names.get_or_insert_with(saved_local, || var.name);
+        }
     }
+    for (capture, &saved_local) in upvar_infos.iter().zip(&upvar_saved_locals) {
+        field_names.get_or_insert_with(saved_local, || capture.var_ident.name);
+    }
+    debug!(field_names = ?field_names.debug_map_view());
 
+    let relocated_upvars = upvar_saved_locals
+        .iter_enumerated()
+        .filter_map(|(field, &source)| {
+            saved_local_upvar_map.get(&field).map(|&dest| (source, dest))
+        })
+        .collect();
     let layout = CoroutineLayout {
         field_tys: tys,
         field_names,
         variant_fields,
         variant_source_info,
         storage_conflicts,
+        relocated_upvars,
     };
     debug!(?layout);
 
-    (remap, layout, storage_liveness)
+    (remap, layout, storage_liveness, suspension_point_at_block)
 }
 
 /// Replaces the entry point of `body` with a block that switches on the coroutine discriminant and
@@ -1102,7 +1212,8 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         elaborate_drop(
             &mut elaborator,
             *source_info,
-            Place::from(SELF_ARG),
+            Place::from(SELF_ARG)
+                .project_deeper(&[ProjectionElem::Downcast(None, VARIANT_UNRESUMED)], tcx),
             (),
             *target,
             unwind,
@@ -1166,7 +1277,7 @@ fn create_coroutine_drop_shim<'tcx>(
     // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible
     // filename.
     body.source.instance = coroutine_instance;
-    dump_mir(tcx, false, "coroutine_drop", &0, &body, |_, _| Ok(()));
+    dump_mir(tcx, false, "coroutine_drop", &0 as _, &body, |_, _| Ok(()));
     body.source.instance = drop_instance;
 
     body
@@ -1354,7 +1465,7 @@ fn create_coroutine_resume_function<'tcx>(
 
     pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);
 
-    dump_mir(tcx, false, "coroutine_resume", &0, body, |_, _| Ok(()));
+    dump_mir(tcx, false, "coroutine_resume", &0 as _, body, |_, _| Ok(()));
 }
 
 fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
@@ -1403,6 +1514,7 @@ fn create_cases<'tcx>(
         .suspension_points
         .iter()
         .filter_map(|point| {
+            let Some(point) = point else { bug!("all suspension points must be resolved now") };
             // Find the target for this suspension point, if applicable
             operation.target_block(point).map(|target| {
                 let mut statements = Vec::new();
@@ -1459,8 +1571,12 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>(
     // The first argument is the coroutine type passed by value
     let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
-    let movable = match *coroutine_ty.kind() {
-        ty::Coroutine(def_id, _) => tcx.coroutine_movability(def_id) == hir::Movability::Movable,
+    let (movable, upvar_tys, upvar_infos) = match *coroutine_ty.kind() {
+        ty::Coroutine(def_id, args) => (
+            matches!(tcx.coroutine_movability(def_id), hir::Movability::Movable),
+            args.as_coroutine().upvar_tys(),
+            tcx.closure_captures(def_id.expect_local()),
+        ),
         ty::Error(_) => return None,
         _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty),
     };
@@ -1468,12 +1584,13 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>(
     // The witness simply contains all locals live across suspend points.
 
     let always_live_locals = always_storage_live_locals(body);
-    let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
+    debug!(?always_live_locals);
+    let liveness_info = locals_live_across_suspend_points(tcx, body, always_live_locals, movable);
 
     // Extract locals which are live across suspension point into `layout`
     // `remap` gives a mapping from local indices onto coroutine struct indices
     // `storage_liveness` tells us which locals have live storage at suspension points
-    let (_, coroutine_layout, _) = compute_layout(liveness_info, body);
+    let (_, coroutine_layout, _, _) = compute_layout(liveness_info, body, upvar_tys, upvar_infos);
 
     check_suspend_tys(tcx, &coroutine_layout, body);
     check_field_tys_sized(tcx, &coroutine_layout, def_id);
@@ -1531,14 +1648,19 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         assert!(body.coroutine_drop().is_none());
 
         // The first argument is the coroutine type passed by value
-        let coroutine_ty = body.local_decls.raw[1].ty;
+        let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
         let coroutine_kind = body.coroutine_kind().unwrap();
 
         // Get the discriminant type and args which typeck computed
-        let (discr_ty, movable) = match *coroutine_ty.kind() {
-            ty::Coroutine(_, args) => {
+        let (discr_ty, movable, upvar_tys, upvar_infos) = match *coroutine_ty.kind() {
+            ty::Coroutine(def_id, args) => {
                 let args = args.as_coroutine();
-                (args.discr_ty(tcx), coroutine_kind.movability() == hir::Movability::Movable)
+                (
+                    args.discr_ty(tcx),
+                    matches!(coroutine_kind.movability(), hir::Movability::Movable),
+                    args.upvar_tys(),
+                    tcx.closure_captures(def_id.expect_local()),
+                )
             }
             _ => {
                 tcx.dcx().span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}"));
@@ -1611,7 +1733,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         let always_live_locals = always_storage_live_locals(body);
 
         let liveness_info =
-            locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
+            locals_live_across_suspend_points(tcx, body, always_live_locals.clone(), movable);
 
         if tcx.sess.opts.unstable_opts.validate_mir {
             let mut vis = EnsureCoroutineFieldAssignmentsNeverAlias {
@@ -1626,7 +1748,8 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         // Extract locals which are live across suspension point into `layout`
         // `remap` gives a mapping from local indices onto coroutine struct indices
         // `storage_liveness` tells us which locals have live storage at suspension points
-        let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
+        let (remap, layout, storage_liveness, suspension_point_at_block) =
+            compute_layout(liveness_info, body, upvar_tys, upvar_infos);
 
         let can_return = can_return(tcx, body, body.typing_env(tcx));
 
@@ -1641,11 +1764,12 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
             remap,
             storage_liveness,
             always_live_locals,
-            suspension_points: Vec::new(),
+            suspension_points: IndexVec::default(),
             old_ret_local,
             discr_ty,
             old_ret_ty,
             old_yield_ty,
+            suspension_point_at_block,
         };
         transform.visit_body(body);
 
@@ -1674,14 +1798,14 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         // This is expanded to a drop ladder in `elaborate_coroutine_drops`.
         let drop_clean = insert_clean_drop(body);
 
-        dump_mir(tcx, false, "coroutine_pre-elab", &0, body, |_, _| Ok(()));
+        dump_mir(tcx, false, "coroutine_pre-elab", &0 as _, body, |_, _| Ok(()));
 
         // Expand `drop(coroutine_struct)` to a drop ladder which destroys upvars.
         // If any upvars are moved out of, drop elaboration will handle upvar destruction.
         // However we need to also elaborate the code generated by `insert_clean_drop`.
         elaborate_coroutine_drops(tcx, body);
 
-        dump_mir(tcx, false, "coroutine_post-transform", &0, body, |_, _| Ok(()));
+        dump_mir(tcx, false, "coroutine_post-transform", &0 as _, body, |_, _| Ok(()));
 
         // Create a copy of our MIR and use it to create the drop shim for the coroutine
         let drop_shim = create_coroutine_drop_shim(tcx, &transform, coroutine_ty, body, drop_clean);
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 89a306c61047..3104ccca03b9 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -69,7 +69,6 @@
 
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::unord::UnordMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -77,8 +76,18 @@ use rustc_middle::bug;
 use rustc_middle::hir::place::{Projection, ProjectionKind};
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::{self, dump_mir};
+use rustc_middle::ty::data_structures::IndexMap;
 use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt};
 
+struct CaptureInfo<'tcx> {
+    /// Field index of the capture in the parent coroutine structure
+    remapped_idx: FieldIdx,
+    /// Type of the capture in the parent coroutine structure
+    remapped_ty: Ty<'tcx>,
+    peel_deref: bool,
+    bridging_projections: Vec<Projection<'tcx>>,
+}
+
 pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
     tcx: TyCtxt<'tcx>,
     coroutine_def_id: LocalDefId,
@@ -125,23 +134,27 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
         .tuple_fields()
         .len();
 
-    let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures(
+    let field_remapping: IndexMap<_, _> = ty::analyze_coroutine_closure_captures(
         tcx.closure_captures(parent_def_id).iter().copied(),
         tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(),
         |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| {
             // Store this set of additional projections (fields and derefs).
             // We need to re-apply them later.
-            let mut child_precise_captures =
-                child_capture.place.projections[parent_capture.place.projections.len()..].to_vec();
+            let child_precise_captures = child_capture.place.projections
+                [parent_capture.place.projections.len()..]
+                .iter()
+                .copied();
 
             // If the parent capture is by-ref, then we need to apply an additional
             // deref before applying any further projections to this place.
-            if parent_capture.is_by_ref() {
-                child_precise_captures.insert(
-                    0,
-                    Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref },
-                );
-            }
+            let bridging_projections = if parent_capture.is_by_ref() {
+                [Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref }]
+                    .into_iter()
+                    .chain(child_precise_captures)
+                    .collect()
+            } else {
+                child_precise_captures.collect()
+            };
             // If the child capture is by-ref, then we need to apply a "ref"
             // projection (i.e. `&`) at the end. But wait! We don't have that
             // as a projection kind. So instead, we can apply its dual and
@@ -167,8 +180,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
 
             // Finally, store the type of the parent's captured place. We need
             // this when building the field projection in the MIR body later on.
-            let mut parent_capture_ty = parent_capture.place.ty();
-            parent_capture_ty = match parent_capture.info.capture_kind {
+            let parent_capture_ty = parent_capture.place.ty();
+            let remapped_ty = match parent_capture.info.capture_kind {
                 ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => parent_capture_ty,
                 ty::UpvarCapture::ByRef(kind) => Ty::new_ref(
                     tcx,
@@ -180,19 +193,19 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
 
             Some((
                 FieldIdx::from_usize(child_field_idx + num_args),
-                (
-                    FieldIdx::from_usize(parent_field_idx + num_args),
-                    parent_capture_ty,
+                CaptureInfo {
+                    remapped_idx: FieldIdx::from_usize(parent_field_idx + num_args),
+                    remapped_ty,
                     peel_deref,
-                    child_precise_captures,
-                ),
+                    bridging_projections,
+                },
             ))
         },
     )
     .flatten()
     .collect();
 
-    if coroutine_kind == ty::ClosureKind::FnOnce {
+    if matches!(coroutine_kind, ty::ClosureKind::FnOnce) {
         assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len());
         // The by-move body is just the body :)
         return coroutine_def_id.to_def_id();
@@ -211,6 +224,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
         );
 
     let mut by_move_body = body.clone();
+    dump_mir(tcx, false, "built", &"before", &by_move_body, |_, _| Ok(()));
     MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
 
     // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
@@ -241,7 +255,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
 
 struct MakeByMoveBody<'tcx> {
     tcx: TyCtxt<'tcx>,
-    field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, Vec<Projection<'tcx>>)>,
+    field_remapping: IndexMap<FieldIdx, CaptureInfo<'tcx>>,
     by_move_coroutine_ty: Ty<'tcx>,
 }
 
@@ -262,8 +276,12 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
         if place.local == ty::CAPTURE_STRUCT_LOCAL
             && let Some((&mir::ProjectionElem::Field(idx, _), projection)) =
                 place.projection.split_first()
-            && let Some(&(remapped_idx, remapped_ty, peel_deref, ref bridging_projections)) =
-                self.field_remapping.get(&idx)
+            && let Some(&CaptureInfo {
+                remapped_idx,
+                remapped_ty,
+                peel_deref,
+                ref bridging_projections,
+            }) = self.field_remapping.get(&idx)
         {
             // As noted before, if the parent closure captures a field by value, and
             // the child captures a field by ref, then for the by-move body we're
@@ -340,7 +358,7 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
                 local: ty::CAPTURE_STRUCT_LOCAL,
                 projection: [mir::ProjectionElem::Field(idx, _)],
             } = place.as_ref()
-            && let Some(&(_, _, true, _)) = self.field_remapping.get(&idx)
+            && let Some(CaptureInfo { peel_deref: true, .. }) = self.field_remapping.get(idx)
         {
             statement.kind = mir::StatementKind::Nop;
         }
diff --git a/compiler/rustc_mir_transform/src/coroutine/relocate_upvars.rs b/compiler/rustc_mir_transform/src/coroutine/relocate_upvars.rs
new file mode 100644
index 000000000000..495c966a06f5
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/coroutine/relocate_upvars.rs
@@ -0,0 +1,314 @@
+//! MIR rewrite pass to promote upvars into native locals in the coroutine body
+//!
+//! # Summary
+//! This pass performs the following transformations.
+//! 1. It generates a fresh batch of locals for each captured upvars.
+//!
+//! For each upvar, whether used or not, a fresh local is created with the same type.
+//!
+//! 2. It replaces the places pointing into those upvars with places pointing into those locals instead
+//!
+//! Each place that starts with access into the coroutine structure `_1` is replaced with the fresh local as
+//! the base. For instance, `(_1.4 as Some).0` is rewritten into `(_34 as Some).0` when `_34` is the fresh local
+//! corresponding to the captured upvar stored in `_1.4`.
+//!
+//! 3. It assembles an prologue to replace the current entry block.
+//!
+//! This prologue block transfers every captured upvar into its corresponding fresh local, *via scratch locals*.
+//! The upvars are first completely moved into the scratch locals in batch, and then moved into the destination
+//! locals in batch.
+//! The reason is that it is possible that coroutine layout may change and the source memory location of
+//! an upvar may not necessarily be mapped exactly to the same place as in the `Unresumed` state.
+//! While coroutine layout ensures that the same saved local has stable offsets throughout its lifetime,
+//! technically the upvar in `Unresumed` state and their fresh locals are different saved locals.
+//! This scratch locals re-estabilish safety so that the correct data permutation can take place.
+
+use rustc_abi::FieldIdx;
+use rustc_index::{IndexSlice, IndexVec};
+use rustc_middle::bug;
+use rustc_middle::mir::visit::MutVisitor;
+use rustc_middle::mir::{
+    self, BasicBlock, BasicBlockData, Body, Local, Place, ProjectionElem, START_BLOCK, SourceInfo,
+    Statement, StatementKind, Terminator, TerminatorKind, UnwindAction,
+};
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::Span;
+
+use crate::pass_manager::MirPass;
+use crate::patch::MirPatch;
+
+pub(crate) struct RelocateUpvars;
+
+struct UpvarSubstitution<'tcx> {
+    /// Newly minted local into which the upvar is moved
+    local: Local,
+    reloc: Local,
+    /// Place into the capture structure where this upvar is found
+    upvar_place: Place<'tcx>,
+    span: Span,
+}
+
+struct SubstituteUpvarVisitor<'tcx, 'a> {
+    tcx: TyCtxt<'tcx>,
+    mappings: &'a IndexSlice<FieldIdx, UpvarSubstitution<'tcx>>,
+}
+
+impl<'tcx, 'a> MutVisitor<'tcx> for SubstituteUpvarVisitor<'tcx, 'a> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_place(
+        &mut self,
+        place: &mut Place<'tcx>,
+        _context: mir::visit::PlaceContext,
+        location: mir::Location,
+    ) {
+        if let Place { local: ty::CAPTURE_STRUCT_LOCAL, projection } = place
+            && let [ProjectionElem::Field(field_idx, _ty), rest @ ..] = &***projection
+        {
+            let Some(&UpvarSubstitution { local, .. }) = self.mappings.get(*field_idx) else {
+                bug!(
+                    "SubstituteUpvar: found {field_idx:?} @ {location:?} but there is no upvar for it"
+                )
+            };
+            let new_place = Place::from(local);
+            let new_place = new_place.project_deeper(rest, self.tcx);
+            *place = new_place;
+        }
+    }
+
+    fn visit_terminator(
+        &mut self,
+        terminator: &mut mir::Terminator<'tcx>,
+        location: mir::Location,
+    ) {
+        if let TerminatorKind::Drop { place, .. } = &terminator.kind
+            && let Some(ty::CAPTURE_STRUCT_LOCAL) = place.as_local()
+        {
+            // This is a drop on the whole coroutine state, which we will processed later
+            return;
+        }
+        self.super_terminator(terminator, location)
+    }
+}
+
+impl<'tcx> MirPass<'tcx> for RelocateUpvars {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let Some(coroutine_def_id) = body.source.def_id().as_local() else {
+            return;
+        };
+        if tcx.coroutine_kind(coroutine_def_id).is_none() {
+            return;
+        }
+
+        // The first argument is the coroutine type passed by value
+        let coroutine_ty = if let Some(decl) = body.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) {
+            decl.ty
+        } else {
+            return;
+        };
+
+        // We only care when there is at least one upvar
+        let (def_id, upvar_tys) = if let ty::Coroutine(def_id, args) = *coroutine_ty.kind() {
+            let args = args.as_coroutine();
+            (def_id, args.upvar_tys())
+        } else {
+            return;
+        };
+        if upvar_tys.is_empty() {
+            return;
+        }
+
+        let upvar_infos = tcx.closure_captures(def_id.expect_local()).iter();
+
+        let mut substitution_mapping = IndexVec::new();
+        let mut patch = MirPatch::new(body);
+        for (field_idx, (upvar_ty, &captured)) in upvar_tys.iter().zip(upvar_infos).enumerate() {
+            let span = captured.var_ident.span;
+
+            let local = patch.new_local_with_info(
+                upvar_ty,
+                span,
+                mir::LocalInfo::Boring,
+                matches!(captured.mutability, ty::Mutability::Not),
+            );
+            let reloc = patch.new_local_with_info(upvar_ty, span, mir::LocalInfo::Boring, true);
+
+            let field_idx = FieldIdx::from_usize(field_idx);
+            let upvar_place = Place::from(ty::CAPTURE_STRUCT_LOCAL)
+                .project_deeper(&[ProjectionElem::Field(field_idx, upvar_ty)], tcx);
+
+            substitution_mapping.push(UpvarSubstitution { local, reloc, upvar_place, span });
+        }
+        patch.apply(body);
+        body.local_upvar_map = substitution_mapping.iter().map(|sub| Some(sub.local)).collect();
+        SubstituteUpvarVisitor { tcx, mappings: &substitution_mapping }.visit_body(body);
+
+        rewrite_drop_coroutine_struct(body, &substitution_mapping);
+        insert_substitution_prologue(body, &substitution_mapping);
+    }
+
+    fn is_required(&self) -> bool {
+        true
+    }
+}
+
+fn rewrite_one_drop_coroutine_struct<'tcx>(
+    patch: &mut MirPatch<'tcx>,
+    body: &Body<'tcx>,
+    block: BasicBlock,
+    substitution_mapping: &IndexSlice<FieldIdx, UpvarSubstitution<'tcx>>,
+) {
+    let data = &body.basic_blocks[block];
+    let source_info = data.terminator().source_info;
+    let TerminatorKind::Drop { place: _, mut target, mut unwind, replace } = data.terminator().kind
+    else {
+        unreachable!()
+    };
+    let mut cleanup = match unwind {
+        UnwindAction::Cleanup(tgt) => tgt,
+        UnwindAction::Continue => patch.resume_block(),
+        UnwindAction::Unreachable => patch.unreachable_cleanup_block(),
+        UnwindAction::Terminate(reason) => patch.terminate_block(reason),
+    };
+    for &UpvarSubstitution { local, .. } in substitution_mapping {
+        let place = local.into();
+        let mut unwind_one = patch.new_block(BasicBlockData {
+            statements: vec![Statement { source_info, kind: StatementKind::StorageDead(local) }],
+            terminator: Some(Terminator {
+                source_info,
+                kind: TerminatorKind::Goto {
+                    target: if data.is_cleanup { target } else { cleanup },
+                },
+            }),
+            is_cleanup: true,
+        });
+        unwind_one = patch.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info,
+                kind: TerminatorKind::Drop {
+                    place,
+                    target: unwind_one,
+                    unwind: UnwindAction::Terminate(mir::UnwindTerminateReason::InCleanup),
+                    replace,
+                },
+            }),
+            is_cleanup: true,
+        });
+        if data.is_cleanup {
+            unwind = UnwindAction::Cleanup(unwind_one);
+            cleanup = unwind_one;
+            target = unwind_one;
+        } else {
+            let mut drop_one = patch.new_block(BasicBlockData {
+                statements: vec![Statement {
+                    source_info,
+                    kind: StatementKind::StorageDead(local),
+                }],
+                terminator: Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }),
+                is_cleanup: false,
+            });
+            drop_one = patch.new_block(BasicBlockData {
+                terminator: Some(Terminator {
+                    source_info,
+                    kind: TerminatorKind::Drop { place, target: drop_one, unwind, replace },
+                }),
+                statements: vec![],
+                is_cleanup: false,
+            });
+            target = drop_one;
+            unwind = UnwindAction::Cleanup(unwind_one);
+            cleanup = unwind_one;
+        }
+    }
+    patch.patch_terminator(block, TerminatorKind::Goto { target });
+}
+
+fn rewrite_drop_coroutine_struct<'tcx>(
+    body: &mut Body<'tcx>,
+    substitution_mapping: &IndexSlice<FieldIdx, UpvarSubstitution<'tcx>>,
+) {
+    let mut blocks = vec![];
+    for (block, block_data) in body.basic_blocks.iter_enumerated() {
+        let Terminator { source_info: _, kind: TerminatorKind::Drop { place, .. } } =
+            block_data.terminator()
+        else {
+            continue;
+        };
+        let Some(local) = place.as_local() else { continue };
+        if local == ty::CAPTURE_STRUCT_LOCAL {
+            blocks.push(block)
+        }
+    }
+    let mut patch = MirPatch::new(body);
+    for block in blocks {
+        rewrite_one_drop_coroutine_struct(&mut patch, body, block, substitution_mapping);
+    }
+    patch.apply(body);
+}
+
+fn insert_substitution_prologue<'tcx>(
+    body: &mut Body<'tcx>,
+    substitution_mapping: &IndexSlice<FieldIdx, UpvarSubstitution<'tcx>>,
+) {
+    let mut patch = MirPatch::new(body);
+    let mut stmts = Vec::with_capacity(2 * substitution_mapping.len());
+    for &UpvarSubstitution { local, reloc, upvar_place, span } in substitution_mapping {
+        // For each upvar-local _$i
+        let source_info = SourceInfo::outermost(span);
+        // StorageLive(_$i)
+        stmts.push(Statement { source_info, kind: StatementKind::StorageLive(local) });
+        // Use a fresh local _$i' here, so as to avoid potential field permutation
+        // StorageLive(_$i')
+        stmts.push(Statement { source_info, kind: StatementKind::StorageLive(reloc) });
+        // _$i' = move $<path>
+        stmts.push(Statement {
+            source_info,
+            kind: StatementKind::Assign(Box::new((
+                reloc.into(),
+                mir::Rvalue::Use(mir::Operand::Move(upvar_place)),
+            ))),
+        });
+    }
+    for &UpvarSubstitution { local, reloc, upvar_place: _, span } in substitution_mapping {
+        let source_info = SourceInfo::outermost(span);
+        // _$i = move $i'
+        stmts.push(Statement {
+            source_info,
+            kind: StatementKind::Assign(Box::new((
+                local.into(),
+                mir::Rvalue::Use(mir::Operand::Move(reloc.into())),
+            ))),
+        });
+        stmts.push(Statement { source_info, kind: StatementKind::StorageDead(reloc) });
+    }
+    let source_info = SourceInfo::outermost(body.span);
+    let prologue = patch.new_block(BasicBlockData {
+        statements: stmts,
+        terminator: Some(Terminator {
+            source_info,
+            kind: TerminatorKind::Drop {
+                place: Place::from(ty::CAPTURE_STRUCT_LOCAL),
+                target: START_BLOCK,
+                unwind: UnwindAction::Continue,
+                replace: false,
+            },
+        }),
+        is_cleanup: false,
+    });
+    patch.apply(body);
+
+    // Manually patch so that prologue is the new entry
+    let preds = body.basic_blocks.predecessors()[START_BLOCK].clone();
+    let basic_blocks = body.basic_blocks.as_mut();
+    for pred in preds {
+        for target in &mut basic_blocks[pred].terminator_mut().successors_mut() {
+            if *target == START_BLOCK {
+                *target = prologue;
+            }
+        }
+    }
+    basic_blocks.swap(START_BLOCK, prologue);
+}
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index bc914ea65641..00d81cc3b3cc 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -40,6 +40,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
                         ty,
                         self.local_decls[p_ref.local].source_info.span,
                         LocalInfo::DerefTemp,
+                        false,
                     );
 
                     // We are adding current p_ref's projections to our
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 205d388f4fb5..5a8b16554cec 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -129,7 +129,7 @@ declare_passes! {
     pub mod cleanup_post_borrowck : CleanupPostBorrowck;
 
     mod copy_prop : CopyProp;
-    mod coroutine : StateTransform;
+    mod coroutine : RelocateUpvars, StateTransform;
     mod coverage : InstrumentCoverage;
     mod ctfe_limit : CtfeLimit;
     mod dataflow_const_prop : DataflowConstProp;
@@ -447,7 +447,12 @@ fn mir_promoted(
     pm::run_passes(
         tcx,
         &mut body,
-        &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
+        &[
+            &coroutine::RelocateUpvars,
+            &promote_pass,
+            &simplify::SimplifyCfg::PromoteConsts,
+            &coverage::InstrumentCoverage,
+        ],
         Some(MirPhase::Analysis(AnalysisPhase::Initial)),
         pm::Optimizations::Allowed,
     );
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 7a8d3ba1ff1f..e5da2c36b240 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -294,11 +294,20 @@ fn run_passes_inner<'tcx>(
             if dump_enabled {
                 dump_mir_for_pass(tcx, body, name, true);
             }
+            let (dialect, phase_num) = body.phase.index();
             if validate {
-                validate_body(tcx, body, format!("after pass {name}"));
+                validate_body(
+                    tcx,
+                    body,
+                    format!("after pass {name} {dialect}-{phase_num}-{:03}", body.pass_count),
+                );
             }
             if lint {
-                lint_body(tcx, body, format!("after pass {name}"));
+                lint_body(
+                    tcx,
+                    body,
+                    format!("after pass {name} {dialect}-{phase_num}-{:03}", body.pass_count),
+                );
             }
 
             body.pass_count += 1;
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index 6a177faeac81..e3a9883dbeff 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -154,10 +154,14 @@ impl<'tcx> MirPatch<'tcx> {
         ty: Ty<'tcx>,
         span: Span,
         local_info: LocalInfo<'tcx>,
+        immutable: bool,
     ) -> Local {
         let index = self.next_local;
         self.next_local += 1;
         let mut new_decl = LocalDecl::new(ty, span);
+        if immutable {
+            new_decl = new_decl.immutable();
+        }
         **new_decl.local_info.as_mut().unwrap_crate_local() = local_info;
         self.new_locals.push(new_decl);
         Local::new(index)
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 84905f4a400f..01256c71cd6d 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -403,9 +403,16 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
         // Only bother running the `LocalUpdater` if we actually found locals to remove.
         if map.iter().any(Option::is_none) {
             // Update references to all vars and tmps now
-            let mut updater = LocalUpdater { map, tcx };
+            let mut updater = LocalUpdater { map: &map, tcx };
             updater.visit_body_preserves_cfg(body);
 
+            // Update mapping for local to upvar
+            for local in &mut body.local_upvar_map {
+                if let Some(idx) = local {
+                    *local = *map.get(*idx).unwrap_or(&None);
+                }
+            }
+
             body.local_decls.shrink_to_fit();
         }
     }
@@ -587,12 +594,12 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
     }
 }
 
-struct LocalUpdater<'tcx> {
-    map: IndexVec<Local, Option<Local>>,
+struct LocalUpdater<'tcx, 'a> {
+    map: &'a IndexSlice<Local, Option<Local>>,
     tcx: TyCtxt<'tcx>,
 }
 
-impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
+impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx, '_> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 231d7c2ef022..e48abcd9db53 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{
-    self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
+    self, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -779,14 +779,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             };
 
                             ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
-                        } else {
-                            let Some(&f_ty) = args.as_coroutine().prefix_tys().get(f.index())
-                            else {
-                                fail_out_of_bounds(self, location);
-                                return;
-                            };
-
+                        } else if let Some(&f_ty) = args.as_coroutine().upvar_tys().get(f.index()) {
                             f_ty
+                        } else {
+                            fail_out_of_bounds(self, location);
+                            return;
                         };
 
                         check_equal(self, location, f_ty);
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 9383b82ff3cd..4374c1347cf5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -5,7 +5,7 @@ use std::borrow::Cow;
 use std::iter;
 
 use itertools::{EitherOrBoth, Itertools};
-use rustc_abi::ExternAbi;
+use rustc_abi::{ExternAbi, FIRST_VARIANT};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::codes::*;
@@ -2361,18 +2361,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             && let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
         {
             debug!(?coroutine_info);
-            'find_source: for (variant, source_info) in
-                coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
+            // Variants are scanned "in reverse" because suspension points
+            // tend to contain more diagnostic information than the unresumed state.
+            'find_source: for ((variant_idx, variant), source_info) in coroutine_info
+                .variant_fields
+                .iter_enumerated()
+                .zip(&coroutine_info.variant_source_info)
+                .rev()
             {
                 debug!(?variant);
                 for &local in variant {
                     let decl = &coroutine_info.field_tys[local];
                     debug!(?decl);
                     if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
-                        interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
-                            decl.source_info.span,
-                            Some((source_info.span, from_awaited_ty)),
-                        ));
+                        let span = decl.source_info.span;
+                        if variant_idx == FIRST_VARIANT {
+                            interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Upvar(span));
+                        } else {
+                            interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
+                                span,
+                                Some((source_info.span, from_awaited_ty)),
+                            ));
+                        }
                         break 'find_source;
                     }
                 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 7334beb52c9d..e2885f056b8d 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -9,6 +9,7 @@ use rustc_abi::{
 use rustc_hashes::Hash64;
 use rustc_index::IndexVec;
 use rustc_middle::bug;
+use rustc_middle::mir::CoroutineSavedLocal;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout,
@@ -410,7 +411,7 @@ fn layout_of_uncached<'tcx>(
                 return Err(error(cx, LayoutError::Unknown(ty)));
             };
 
-            let local_layouts = info
+            let local_layouts: IndexVec<_, _> = info
                 .field_tys
                 .iter()
                 .map(|local| {
@@ -418,20 +419,17 @@ fn layout_of_uncached<'tcx>(
                     let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty.instantiate(tcx, args));
                     cx.spanned_layout_of(uninit_ty, local.source_info.span)
                 })
-                .try_collect::<IndexVec<_, _>>()?;
-
-            let prefix_layouts = args
-                .as_coroutine()
-                .prefix_tys()
-                .iter()
-                .map(|ty| cx.layout_of(ty))
-                .try_collect::<IndexVec<_, _>>()?;
+                .try_collect()?;
 
+            let relocated_upvars = IndexVec::from_fn_n(
+                |local: CoroutineSavedLocal| info.relocated_upvars.get(&local).copied(),
+                info.field_tys.len(),
+            );
             let layout = cx
                 .calc
                 .coroutine(
                     &local_layouts,
-                    prefix_layouts,
+                    &relocated_upvars,
                     &info.variant_fields,
                     &info.storage_conflicts,
                     |tag| TyAndLayout {
@@ -826,7 +824,11 @@ fn variant_info_for_coroutine<'tcx>(
                             .then(|| Symbol::intern(&field_layout.ty.to_string())),
                     }
                 })
-                .chain(upvar_fields.iter().copied())
+                .chain(
+                    if variant_idx == FIRST_VARIANT { &upvar_fields[..] } else { &[] }
+                        .iter()
+                        .copied(),
+                )
                 .collect();
 
             // If the variant has no state-specific fields, then it's the size of the upvars.
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index e366dc2d2195..326a78954620 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -13,11 +13,14 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 LL |     async { true }.await
    |                    ^^^^^ await occurs here, with `rc` maybe used later
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
-note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> tests/ui/future_not_send.rs:8:39
+note: future is not `Send` as this value is used across an await
+  --> tests/ui/future_not_send.rs:11:20
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   |                                       ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
+   |                                       ---- has type `&std::cell::Cell<usize>` which is not `Send`
+...
+LL |     async { true }.await
+   |                    ^^^^^ await occurs here, with `cell` maybe used later
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
    = note: `-D clippy::future-not-send` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
@@ -92,11 +95,14 @@ error: future cannot be sent between threads safely
 LL |     pub async fn public_future(&self) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
    |
-note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> tests/ui/future_not_send.rs:49:32
+note: future is not `Send` as this value is used across an await
+  --> tests/ui/future_not_send.rs:52:31
    |
 LL |     pub async fn public_future(&self) {
-   |                                ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync`
+   |                                 ---- has type `&Dummy` which is not `Send`
+...
+LL |         self.private_future().await;
+   |                               ^^^^^ await occurs here, with `self` maybe used later
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
index fd6ba4e3563d..9c39f73ef6d7 100644
--- a/src/tools/clippy/tests/ui/large_futures.stderr
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -31,7 +31,7 @@ error: large future with a size of 65540 bytes
 LL |     foo().await;
    |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
 
-error: large future with a size of 49159 bytes
+error: large future with a size of 32774 bytes
   --> tests/ui/large_futures.rs:35:5
    |
 LL |     calls_fut(fut).await;
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
index d59393fb3f3c..96caf2917345 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -3,6 +3,7 @@
 #![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
 #![allow(
     unused,
+    clippy::await_holding_lock,
     clippy::boxed_local,
     clippy::extra_unused_type_parameters,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index e24907ab5fcd..b087a1288362 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -3,6 +3,7 @@
 #![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
 #![allow(
     unused,
+    clippy::await_holding_lock,
     clippy::boxed_local,
     clippy::extra_unused_type_parameters,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 138d0498c43e..c7669e4d175b 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -1,5 +1,5 @@
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> tests/ui/needless_lifetimes.rs:19:23
+  --> tests/ui/needless_lifetimes.rs:20:23
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    |                       ^^  ^^       ^^          ^^
@@ -13,7 +13,7 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> tests/ui/needless_lifetimes.rs:22:24
+  --> tests/ui/needless_lifetimes.rs:23:24
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
    |                        ^^  ^^       ^^          ^^
@@ -25,7 +25,7 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:33:15
+  --> tests/ui/needless_lifetimes.rs:34:15
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    |               ^^      ^^                 ^^
@@ -37,7 +37,7 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> tests/ui/needless_lifetimes.rs:46:31
+  --> tests/ui/needless_lifetimes.rs:47:31
    |
 LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
    |                               ^^                  ^^
@@ -49,7 +49,7 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:54:27
+  --> tests/ui/needless_lifetimes.rs:55:27
    |
 LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
    |                           ^^           ^^
@@ -61,7 +61,7 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> tests/ui/needless_lifetimes.rs:72:26
+  --> tests/ui/needless_lifetimes.rs:73:26
    |
 LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
    |                          ^^                  ^^
@@ -73,7 +73,7 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:80:22
+  --> tests/ui/needless_lifetimes.rs:81:22
    |
 LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
    |                      ^^           ^^
@@ -85,7 +85,7 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:90:21
+  --> tests/ui/needless_lifetimes.rs:91:21
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    |                     ^^      ^^                        ^^
@@ -97,7 +97,7 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:96:28
+  --> tests/ui/needless_lifetimes.rs:97:28
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    |                            ^^         ^^                        ^^
@@ -109,7 +109,7 @@ LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> tests/ui/needless_lifetimes.rs:127:21
+  --> tests/ui/needless_lifetimes.rs:128:21
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |                     ^^   ^^           ^^
@@ -121,7 +121,7 @@ LL +     fn self_and_out(&self) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 't
-  --> tests/ui/needless_lifetimes.rs:135:30
+  --> tests/ui/needless_lifetimes.rs:136:30
    |
 LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
    |                              ^^                 ^^
@@ -133,7 +133,7 @@ LL +     fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> tests/ui/needless_lifetimes.rs:143:26
+  --> tests/ui/needless_lifetimes.rs:144:26
    |
 LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
    |                          ^^       ^^
@@ -145,7 +145,7 @@ LL +     fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's, 't
-  --> tests/ui/needless_lifetimes.rs:148:29
+  --> tests/ui/needless_lifetimes.rs:149:29
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |                             ^^  ^^   ^^            ^^
@@ -157,7 +157,7 @@ LL +     fn distinct_self_and_in(&self, _x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:172:21
+  --> tests/ui/needless_lifetimes.rs:173:21
    |
 LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
    |                     ^^             ^^
@@ -169,7 +169,7 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:188:22
+  --> tests/ui/needless_lifetimes.rs:189:22
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    |                      ^^         ^^               ^^
@@ -181,7 +181,7 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:199:20
+  --> tests/ui/needless_lifetimes.rs:200:20
    |
 LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
    |                    ^^             ^^
@@ -193,7 +193,7 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:204:30
+  --> tests/ui/needless_lifetimes.rs:205:30
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    |                              ^^         ^^          ^
@@ -205,7 +205,7 @@ LL + fn named_input_elided_output(_arg: &str) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:213:19
+  --> tests/ui/needless_lifetimes.rs:214:19
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    |                   ^^                                ^^
@@ -217,7 +217,7 @@ LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:249:24
+  --> tests/ui/needless_lifetimes.rs:250:24
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |                        ^^      ^^
@@ -229,7 +229,7 @@ LL +         fn needless_lt(x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:254:24
+  --> tests/ui/needless_lifetimes.rs:255:24
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |                        ^^       ^^
@@ -241,7 +241,7 @@ LL +         fn needless_lt(_x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:285:55
+  --> tests/ui/needless_lifetimes.rs:286:55
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |                                                       ^^      ^^                                    ^^
@@ -253,7 +253,7 @@ LL +     fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:295:26
+  --> tests/ui/needless_lifetimes.rs:296:26
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |                          ^^                           ^^                ^^
@@ -265,7 +265,7 @@ LL +     fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:308:30
+  --> tests/ui/needless_lifetimes.rs:309:30
    |
 LL |     fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |                              ^^         ^^                ^^
@@ -277,7 +277,7 @@ LL +     fn where_clause_elidable<T>(i: &i32, f: T) -> &i32
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:324:28
+  --> tests/ui/needless_lifetimes.rs:325:28
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |                            ^^      ^^                               ^^
@@ -289,7 +289,7 @@ LL +     fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:338:28
+  --> tests/ui/needless_lifetimes.rs:339:28
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |                            ^^      ^^
@@ -301,7 +301,7 @@ LL +     fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:342:28
+  --> tests/ui/needless_lifetimes.rs:343:28
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |                            ^^      ^^
@@ -313,7 +313,7 @@ LL +     fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:365:21
+  --> tests/ui/needless_lifetimes.rs:366:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
    |                     ^^   ^^           ^^
@@ -325,7 +325,7 @@ LL +         fn implicit(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:369:25
+  --> tests/ui/needless_lifetimes.rs:370:25
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
    |                         ^^   ^^               ^^
@@ -337,7 +337,7 @@ LL +         fn implicit_mut(&mut self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:374:21
+  --> tests/ui/needless_lifetimes.rs:375:21
    |
 LL |         fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
    |                     ^^         ^^                ^^
@@ -349,7 +349,7 @@ LL +         fn explicit(self: &Arc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:379:25
+  --> tests/ui/needless_lifetimes.rs:380:25
    |
 LL |         fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
    |                         ^^         ^^                   ^^
@@ -361,7 +361,7 @@ LL +         fn explicit_mut(self: &mut Rc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:392:31
+  --> tests/ui/needless_lifetimes.rs:393:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |                               ^^                          ^^         ^^
@@ -373,7 +373,7 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:399:21
+  --> tests/ui/needless_lifetimes.rs:400:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
    |                     ^^   ^^           ^^
@@ -385,7 +385,7 @@ LL +         fn implicit(&self) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:401:30
+  --> tests/ui/needless_lifetimes.rs:402:30
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
    |                              ^^   ^^           ^^
@@ -397,7 +397,7 @@ LL +         fn implicit_provided(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:407:21
+  --> tests/ui/needless_lifetimes.rs:408:21
    |
 LL |         fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
    |                     ^^         ^^                ^^
@@ -409,7 +409,7 @@ LL +         fn explicit(self: &Arc<Self>) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:410:30
+  --> tests/ui/needless_lifetimes.rs:411:30
    |
 LL |         fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
    |                              ^^         ^^                ^^
@@ -421,7 +421,7 @@ LL +         fn explicit_provided(self: &Arc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:421:31
+  --> tests/ui/needless_lifetimes.rs:422:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
    |                               ^^                          ^^         ^^
@@ -433,7 +433,7 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:423:40
+  --> tests/ui/needless_lifetimes.rs:424:40
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |                                        ^^                          ^^         ^^
@@ -445,7 +445,7 @@ LL +         fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:433:12
+  --> tests/ui/needless_lifetimes.rs:434:12
    |
 LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
    |            ^^      ^^
@@ -457,7 +457,7 @@ LL +     fn foo(x: &u8, y: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:436:12
+  --> tests/ui/needless_lifetimes.rs:437:12
    |
 LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
    |            ^^      ^^
@@ -469,7 +469,7 @@ LL +     fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:444:18
+  --> tests/ui/needless_lifetimes.rs:445:18
    |
 LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
    |                  ^^      ^^         ^^
@@ -481,7 +481,7 @@ LL +     fn one_input(x: &u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:450:42
+  --> tests/ui/needless_lifetimes.rs:451:42
    |
 LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
    |                                          ^^          ^^
@@ -493,7 +493,7 @@ LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:467:22
+  --> tests/ui/needless_lifetimes.rs:468:22
    |
 LL |         fn one_input<'a>(x: &'a u8) -> &'a u8 {
    |                      ^^      ^^         ^^
diff --git a/tests/codegen/async-fn-debug.rs b/tests/codegen/async-fn-debug.rs
index 7be4ad456657..2b7d9eb30ecc 100644
--- a/tests/codegen/async-fn-debug.rs
+++ b/tests/codegen/async-fn-debug.rs
@@ -37,17 +37,17 @@ async fn async_fn_test() {
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 12,
+// CHECK-SAME: file: [[FILE]], line: 14,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 14,
+// CHECK:      [[S0:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S0]]
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
+// CHECK-SAME: file: [[FILE]], line: 12,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
 // CHECK:      [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[GEN]],
diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs
index 242c76c2989e..2142e8f4b859 100644
--- a/tests/debuginfo/coroutine-objects.rs
+++ b/tests/debuginfo/coroutine-objects.rs
@@ -10,22 +10,22 @@
 
 // gdb-command:run
 // gdb-command:print b
-// gdb-check:$1 = coroutine_objects::main::{coroutine_env#0}::Unresumed{_ref__a: 0x[...]}
+// gdb-check:$1 = coroutine_objects::main::{coroutine_env#0}::Unresumed{a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$2 = coroutine_objects::main::{coroutine_env#0}::Suspend0{c: 6, d: 7, _ref__a: 0x[...]}
+// gdb-check:$2 = coroutine_objects::main::{coroutine_env#0}::Suspend0{c: 6, d: 7, a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$3 = coroutine_objects::main::{coroutine_env#0}::Suspend1{c: 7, d: 8, _ref__a: 0x[...]}
+// gdb-check:$3 = coroutine_objects::main::{coroutine_env#0}::Suspend1{c: 7, d: 8, a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$4 = coroutine_objects::main::{coroutine_env#0}::Returned{_ref__a: 0x[...]}
+// gdb-check:$4 = coroutine_objects::main::{coroutine_env#0}::Returned
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 // lldb-command:v b
-// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { _ref__a = 0x[...] } $discr$ = [...] }
+// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { a = 0x[...] } $discr$ = [...] }
 
 // === CDB TESTS ===================================================================================
 
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index 109a41d1ef90..fc73c7ba1545 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -1,7 +1,7 @@
 // MIR for `b::{closure#0}` 0 coroutine_resume
 /* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: CoroutineSavedTy {
+        corsl_0: CoroutineSavedTy {
             ty: Coroutine(
                 DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
                 [
@@ -22,7 +22,7 @@
             },
             ignore_for_traits: false,
         },
-        _1: CoroutineSavedTy {
+        corsl_1: CoroutineSavedTy {
             ty: Coroutine(
                 DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
                 [
@@ -48,12 +48,12 @@
         Unresumed(0): [],
         Returned (1): [],
         Panicked (2): [],
-        Suspend0 (3): [_0],
-        Suspend1 (4): [_1],
+        Suspend0 (3): [corsl_1],
+        Suspend1 (4): [corsl_0],
     },
     storage_conflicts: BitMatrix(2x2) {
-        (_0, _0),
-        (_1, _1),
+        (corsl_0, corsl_0),
+        (corsl_1, corsl_1),
     },
 } */
 
@@ -96,14 +96,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
     let mut _38: &mut std::task::Context<'_>;
     let mut _39: u32;
     scope 1 {
-        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
+        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
         let _17: ();
         scope 2 {
             debug result => _17;
         }
     }
     scope 3 {
-        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
+        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
         let _33: ();
         scope 4 {
             debug result => _33;
@@ -131,7 +131,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_5);
         PlaceMention(_4);
         nop;
-        (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _4;
+        (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _4;
         goto -> bb4;
     }
 
@@ -141,7 +141,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageLive(_10);
         StorageLive(_11);
         StorageLive(_12);
-        _12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
+        _12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).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];
     }
@@ -188,7 +188,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_4);
         StorageDead(_19);
         StorageDead(_20);
-        discriminant((*(_1.0: &mut {async fn body of b()}))) = 3;
+        discriminant((*(_1.0: &mut {async fn body of b()}))) = 4;
         return;
     }
 
@@ -201,7 +201,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_12);
         StorageDead(_9);
         StorageDead(_8);
-        drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable];
+        drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb12, unwind unreachable];
     }
 
     bb11: {
@@ -233,7 +233,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_22);
         PlaceMention(_21);
         nop;
-        (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _21;
+        (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _21;
         goto -> bb16;
     }
 
@@ -243,7 +243,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageLive(_26);
         StorageLive(_27);
         StorageLive(_28);
-        _28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
+        _28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).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];
     }
@@ -285,7 +285,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_21);
         StorageDead(_35);
         StorageDead(_36);
-        discriminant((*(_1.0: &mut {async fn body of b()}))) = 4;
+        discriminant((*(_1.0: &mut {async fn body of b()}))) = 3;
         return;
     }
 
@@ -298,7 +298,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         StorageDead(_28);
         StorageDead(_25);
         StorageDead(_24);
-        drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable];
+        drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb23, unwind unreachable];
     }
 
     bb22: {
@@ -330,6 +330,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
     }
 
     bb27: {
+        StorageLive(_21);
+        StorageLive(_35);
+        StorageLive(_36);
+        _35 = move _2;
+        goto -> bb22;
+    }
+
+    bb28: {
         StorageLive(_3);
         StorageLive(_4);
         StorageLive(_19);
@@ -338,14 +346,6 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
         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/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
index f8b3f68d21e6..fe01ea115cd2 100644
--- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
@@ -1,7 +1,7 @@
 // MIR for `main::{closure#0}` 0 coroutine_resume
 /* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: CoroutineSavedTy {
+        corsl_0: CoroutineSavedTy {
             ty: HasDrop,
             source_info: SourceInfo {
                 span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
@@ -14,10 +14,10 @@
         Unresumed(0): [],
         Returned (1): [],
         Panicked (2): [],
-        Suspend0 (3): [_0],
+        Suspend0 (3): [corsl_0],
     },
     storage_conflicts: BitMatrix(1x1) {
-        (_0, _0),
+        (corsl_0, corsl_0),
     },
 } */
 
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
index eb97af1e2845..3beda282fc91 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
@@ -38,17 +38,19 @@
 +                 let mut _27: !;
 +                 let mut _28: &mut std::task::Context<'_>;
 +                 let mut _29: ();
-+                 let mut _30: ();
-+                 let mut _31: &mut std::task::Context<'_>;
-+                 let mut _32: u32;
-+                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
-+                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let _30: ActionPermit<'_, T>;
++                 let _31: ActionPermit<'_, T>;
++                 let mut _32: ();
++                 let mut _33: &mut std::task::Context<'_>;
++                 let mut _34: u32;
 +                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 7 {
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 8 {
@@ -58,15 +60,15 @@
 +                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
 +                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _42: ();
-+                             let mut _43: std::option::Option<()>;
-+                             let mut _44: &mut std::option::Option<()>;
-+                             let mut _45: &mut std::future::Ready<()>;
-+                             let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             let mut _44: ();
++                             let mut _45: std::option::Option<()>;
++                             let mut _46: &mut std::option::Option<()>;
++                             let mut _47: &mut std::future::Ready<()>;
++                             let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
 +                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
-+                                 let mut _47: std::pin::Pin<&mut std::future::Ready<()>>;
++                                 let mut _49: std::pin::Pin<&mut std::future::Ready<()>>;
 +                                 scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
-+                                     let mut _48: &mut &mut std::future::Ready<()>;
++                                     let mut _50: &mut &mut std::future::Ready<()>;
 +                                     scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                                     }
 +                                     scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@@ -76,22 +78,22 @@
 +                                 }
 +                             }
 +                             scope 19 (inlined Option::<()>::take) {
-+                                 let mut _49: std::option::Option<()>;
++                                 let mut _51: std::option::Option<()>;
 +                                 scope 20 (inlined std::mem::replace::<Option<()>>) {
 +                                     scope 21 {
 +                                     }
 +                                 }
 +                             }
 +                             scope 22 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _50: isize;
-+                                 let mut _51: !;
++                                 let mut _52: isize;
++                                 let mut _53: !;
 +                                 scope 23 {
 +                                 }
 +                             }
 +                         }
 +                     }
 +                     scope 10 (inlined ready::<()>) {
-+                         let mut _41: std::option::Option<()>;
++                         let mut _43: std::option::Option<()>;
 +                     }
 +                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
@@ -136,8 +138,6 @@
 +         StorageLive(_16);
 +         StorageLive(_25);
 +         StorageLive(_27);
-+         StorageLive(_30);
-+         StorageLive(_31);
 +         StorageLive(_32);
 +         StorageLive(_33);
 +         StorageLive(_34);
@@ -147,9 +147,11 @@
 +         StorageLive(_38);
 +         StorageLive(_39);
 +         StorageLive(_40);
-+         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _32 = discriminant((*_33));
-+         switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
++         StorageLive(_41);
++         StorageLive(_42);
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _34 = discriminant((*_35));
++         switchInt(move _34) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
       }
   
 -     bb3: {
@@ -159,6 +161,8 @@
 +     }
 + 
 +     bb2: {
++         StorageDead(_42);
++         StorageDead(_41);
 +         StorageDead(_40);
 +         StorageDead(_39);
 +         StorageDead(_38);
@@ -168,8 +172,6 @@
 +         StorageDead(_34);
 +         StorageDead(_33);
 +         StorageDead(_32);
-+         StorageDead(_31);
-+         StorageDead(_30);
 +         StorageDead(_27);
 +         StorageDead(_25);
 +         StorageDead(_16);
@@ -187,23 +189,28 @@
       }
   
 +     bb3: {
-+         _31 = move _9;
-+         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         _33 = move _9;
++         StorageLive(_30);
++         StorageLive(_31);
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _31 = move (((*_36) as variant#0).0: ActionPermit<'_, T>);
++         _30 = move _31;
++         StorageDead(_31);
++         _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_42) as variant#3).0: ActionPermit<'_, T>) = move _30;
 +         StorageLive(_12);
 +         StorageLive(_13);
 +         StorageLive(_14);
 +         _14 = ();
-+         StorageLive(_41);
-+         _41 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _41);
-+         StorageDead(_41);
++         StorageLive(_43);
++         _43 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _43);
++         StorageDead(_43);
 +         StorageDead(_14);
 +         _12 = move _13;
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_37) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb4;
 +     }
 + 
@@ -215,41 +222,41 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _21 = &mut (((*_38) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
 +         StorageDead(_20);
 +         StorageLive(_22);
 +         StorageLive(_23);
 +         StorageLive(_24);
-+         _24 = copy _31;
++         _24 = copy _33;
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
++         StorageLive(_47);
++         StorageLive(_48);
++         StorageLive(_51);
++         StorageLive(_53);
++         StorageLive(_44);
 +         StorageLive(_45);
 +         StorageLive(_46);
++         _48 = &mut _19;
 +         StorageLive(_49);
-+         StorageLive(_51);
-+         StorageLive(_42);
-+         StorageLive(_43);
-+         StorageLive(_44);
-+         _46 = &mut _19;
-+         StorageLive(_47);
-+         StorageLive(_48);
-+         _48 = &mut (_19.0: &mut std::future::Ready<()>);
-+         _45 = copy (_19.0: &mut std::future::Ready<()>);
-+         StorageDead(_48);
-+         _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 };
-+         StorageDead(_47);
-+         _44 = &mut ((*_45).0: std::option::Option<()>);
-+         _49 = Option::<()>::None;
-+         _43 = copy ((*_45).0: std::option::Option<()>);
-+         ((*_45).0: std::option::Option<()>) = copy _49;
-+         StorageDead(_44);
 +         StorageLive(_50);
-+         _50 = discriminant(_43);
-+         switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5];
++         _50 = &mut (_19.0: &mut std::future::Ready<()>);
++         _47 = copy (_19.0: &mut std::future::Ready<()>);
++         StorageDead(_50);
++         _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 };
++         StorageDead(_49);
++         _46 = &mut ((*_47).0: std::option::Option<()>);
++         _51 = Option::<()>::None;
++         _45 = copy ((*_47).0: std::option::Option<()>);
++         ((*_47).0: std::option::Option<()>) = copy _51;
++         StorageDead(_46);
++         StorageLive(_52);
++         _52 = discriminant(_45);
++         switchInt(move _52) -> [0: bb11, 1: bb12, otherwise: bb5];
 +     }
 + 
 +     bb5: {
@@ -269,29 +276,31 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_38)) = 3;
++         StorageDead(_30);
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_39)) = 3;
 +         goto -> bb2;
 +     }
 + 
 +     bb7: {
 +         StorageLive(_26);
 +         _26 = copy ((_18 as Ready).0: ());
-+         _30 = copy _26;
++         _32 = copy _26;
 +         StorageDead(_26);
 +         StorageDead(_23);
 +         StorageDead(_21);
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
++         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
 +     }
 + 
 +     bb8: {
-+         _7 = Poll::<()>::Ready(move _30);
-+         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_40)) = 1;
++         StorageDead(_30);
++         _7 = Poll::<()>::Ready(move _32);
++         _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_41)) = 1;
 +         goto -> bb2;
 +     }
 + 
@@ -299,9 +308,10 @@
 +         StorageLive(_12);
 +         StorageLive(_28);
 +         StorageLive(_29);
++         StorageLive(_30);
 +         _28 = move _9;
 +         StorageDead(_29);
-+         _31 = move _28;
++         _33 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
 +         goto -> bb4;
@@ -312,19 +322,19 @@
 +     }
 + 
 +     bb11: {
-+         _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
++         _53 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
 +     }
 + 
 +     bb12: {
-+         _42 = move ((_43 as Some).0: ());
-+         StorageDead(_50);
-+         StorageDead(_43);
-+         _18 = Poll::<()>::Ready(move _42);
-+         StorageDead(_42);
-+         StorageDead(_51);
-+         StorageDead(_49);
-+         StorageDead(_46);
++         _44 = move ((_45 as Some).0: ());
++         StorageDead(_52);
 +         StorageDead(_45);
++         _18 = Poll::<()>::Ready(move _44);
++         StorageDead(_44);
++         StorageDead(_53);
++         StorageDead(_51);
++         StorageDead(_48);
++         StorageDead(_47);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
index eb757e091145..a6da1fcd9d62 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
@@ -38,11 +38,11 @@
 +                 let mut _27: !;
 +                 let mut _28: &mut std::task::Context<'_>;
 +                 let mut _29: ();
-+                 let mut _30: ();
-+                 let mut _31: &mut std::task::Context<'_>;
-+                 let mut _32: u32;
-+                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
-+                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let _30: ActionPermit<'_, T>;
++                 let _31: ActionPermit<'_, T>;
++                 let mut _32: ();
++                 let mut _33: &mut std::task::Context<'_>;
++                 let mut _34: u32;
 +                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
@@ -51,6 +51,8 @@
 +                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _43: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _44: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 7 {
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 8 {
@@ -60,15 +62,15 @@
 +                         scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                         }
 +                         scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
-+                             let mut _44: ();
-+                             let mut _45: std::option::Option<()>;
-+                             let mut _46: &mut std::option::Option<()>;
-+                             let mut _47: &mut std::future::Ready<()>;
-+                             let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
++                             let mut _46: ();
++                             let mut _47: std::option::Option<()>;
++                             let mut _48: &mut std::option::Option<()>;
++                             let mut _49: &mut std::future::Ready<()>;
++                             let mut _50: &mut std::pin::Pin<&mut std::future::Ready<()>>;
 +                             scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
-+                                 let mut _49: std::pin::Pin<&mut std::future::Ready<()>>;
++                                 let mut _51: std::pin::Pin<&mut std::future::Ready<()>>;
 +                                 scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
-+                                     let mut _50: &mut &mut std::future::Ready<()>;
++                                     let mut _52: &mut &mut std::future::Ready<()>;
 +                                     scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
 +                                     }
 +                                     scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@@ -78,22 +80,22 @@
 +                                 }
 +                             }
 +                             scope 19 (inlined Option::<()>::take) {
-+                                 let mut _51: std::option::Option<()>;
++                                 let mut _53: std::option::Option<()>;
 +                                 scope 20 (inlined std::mem::replace::<Option<()>>) {
 +                                     scope 21 {
 +                                     }
 +                                 }
 +                             }
 +                             scope 22 (inlined #[track_caller] Option::<()>::expect) {
-+                                 let mut _52: isize;
-+                                 let mut _53: !;
++                                 let mut _54: isize;
++                                 let mut _55: !;
 +                                 scope 23 {
 +                                 }
 +                             }
 +                         }
 +                     }
 +                     scope 10 (inlined ready::<()>) {
-+                         let mut _43: std::option::Option<()>;
++                         let mut _45: std::option::Option<()>;
 +                     }
 +                     scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
 +                     }
@@ -138,8 +140,6 @@
 +         StorageLive(_16);
 +         StorageLive(_25);
 +         StorageLive(_27);
-+         StorageLive(_30);
-+         StorageLive(_31);
 +         StorageLive(_32);
 +         StorageLive(_33);
 +         StorageLive(_34);
@@ -151,9 +151,11 @@
 +         StorageLive(_40);
 +         StorageLive(_41);
 +         StorageLive(_42);
-+         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _32 = discriminant((*_33));
-+         switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
++         StorageLive(_43);
++         StorageLive(_44);
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _34 = discriminant((*_35));
++         switchInt(move _34) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
       }
   
 -     bb3: {
@@ -171,6 +173,8 @@
 +     }
 + 
 +     bb4: {
++         StorageDead(_44);
++         StorageDead(_43);
 +         StorageDead(_42);
 +         StorageDead(_41);
 +         StorageDead(_40);
@@ -182,8 +186,6 @@
 +         StorageDead(_34);
 +         StorageDead(_33);
 +         StorageDead(_32);
-+         StorageDead(_31);
-+         StorageDead(_30);
 +         StorageDead(_27);
 +         StorageDead(_25);
 +         StorageDead(_16);
@@ -204,23 +206,28 @@
 -         StorageDead(_2);
 -         return;
 +     bb5: {
-+         _31 = move _9;
-+         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         _33 = move _9;
++         StorageLive(_30);
++         StorageLive(_31);
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _31 = move (((*_36) as variant#0).0: ActionPermit<'_, T>);
++         _30 = move _31;
++         StorageDead(_31);
++         _43 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_43) as variant#3).0: ActionPermit<'_, T>) = move _30;
 +         StorageLive(_12);
 +         StorageLive(_13);
 +         StorageLive(_14);
 +         _14 = ();
-+         StorageLive(_43);
-+         _43 = Option::<()>::Some(copy _14);
-+         _13 = std::future::Ready::<()>(move _43);
-+         StorageDead(_43);
++         StorageLive(_45);
++         _45 = Option::<()>::Some(copy _14);
++         _13 = std::future::Ready::<()>(move _45);
++         StorageDead(_45);
 +         StorageDead(_14);
 +         _12 = move _13;
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         (((*_37) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb6;
       }
   
@@ -232,41 +239,41 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _21 = &mut (((*_38) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
 +         StorageDead(_20);
 +         StorageLive(_22);
 +         StorageLive(_23);
 +         StorageLive(_24);
-+         _24 = copy _31;
++         _24 = copy _33;
 +         _23 = move _24;
 +         _22 = &mut (*_23);
 +         StorageDead(_24);
++         StorageLive(_49);
++         StorageLive(_50);
++         StorageLive(_53);
++         StorageLive(_55);
++         StorageLive(_46);
 +         StorageLive(_47);
 +         StorageLive(_48);
++         _50 = &mut _19;
 +         StorageLive(_51);
-+         StorageLive(_53);
-+         StorageLive(_44);
-+         StorageLive(_45);
-+         StorageLive(_46);
-+         _48 = &mut _19;
-+         StorageLive(_49);
-+         StorageLive(_50);
-+         _50 = &mut (_19.0: &mut std::future::Ready<()>);
-+         _47 = copy (_19.0: &mut std::future::Ready<()>);
-+         StorageDead(_50);
-+         _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 };
-+         StorageDead(_49);
-+         _46 = &mut ((*_47).0: std::option::Option<()>);
-+         _51 = Option::<()>::None;
-+         _45 = copy ((*_47).0: std::option::Option<()>);
-+         ((*_47).0: std::option::Option<()>) = copy _51;
-+         StorageDead(_46);
 +         StorageLive(_52);
-+         _52 = discriminant(_45);
-+         switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7];
++         _52 = &mut (_19.0: &mut std::future::Ready<()>);
++         _49 = copy (_19.0: &mut std::future::Ready<()>);
++         StorageDead(_52);
++         _51 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _49 };
++         StorageDead(_51);
++         _48 = &mut ((*_49).0: std::option::Option<()>);
++         _53 = Option::<()>::None;
++         _47 = copy ((*_49).0: std::option::Option<()>);
++         ((*_49).0: std::option::Option<()>) = copy _53;
++         StorageDead(_48);
++         StorageLive(_54);
++         _54 = discriminant(_47);
++         switchInt(move _54) -> [0: bb16, 1: bb17, otherwise: bb7];
       }
   
 -     bb6 (cleanup): {
@@ -288,33 +295,27 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_38)) = 3;
++         StorageDead(_30);
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_39)) = 3;
 +         goto -> bb4;
 +     }
 + 
 +     bb9: {
 +         StorageLive(_26);
 +         _26 = copy ((_18 as Ready).0: ());
-+         _30 = copy _26;
++         _32 = copy _26;
 +         StorageDead(_26);
 +         StorageDead(_23);
 +         StorageDead(_21);
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
-+     }
-+ 
-+     bb10: {
-+         _7 = Poll::<()>::Ready(move _30);
 +         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_40)) = 1;
-+         goto -> bb4;
++         drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind: bb12];
 +     }
 + 
-+     bb11 (cleanup): {
++     bb10 (cleanup): {
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         StorageDead(_23);
@@ -326,9 +327,17 @@
 +         drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
 +     }
 + 
-+     bb12 (cleanup): {
++     bb11: {
++         StorageDead(_30);
++         _7 = Poll::<()>::Ready(move _32);
 +         _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
-+         discriminant((*_42)) = 2;
++         discriminant((*_42)) = 1;
++         goto -> bb4;
++     }
++ 
++     bb12 (cleanup): {
++         _44 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         discriminant((*_44)) = 2;
 +         goto -> bb2;
 +     }
 + 
@@ -336,9 +345,10 @@
 +         StorageLive(_12);
 +         StorageLive(_28);
 +         StorageLive(_29);
++         StorageLive(_30);
 +         _28 = move _9;
 +         StorageDead(_29);
-+         _31 = move _28;
++         _33 = move _28;
 +         StorageDead(_28);
 +         _16 = const ();
 +         goto -> bb6;
@@ -353,19 +363,19 @@
 +     }
 + 
 +     bb16: {
-+         _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
++         _55 = option::expect_failed(const "`Ready` polled after completion") -> bb10;
 +     }
 + 
 +     bb17: {
-+         _44 = move ((_45 as Some).0: ());
-+         StorageDead(_52);
-+         StorageDead(_45);
-+         _18 = Poll::<()>::Ready(move _44);
-+         StorageDead(_44);
-+         StorageDead(_53);
-+         StorageDead(_51);
-+         StorageDead(_48);
++         _46 = move ((_47 as Some).0: ());
++         StorageDead(_54);
 +         StorageDead(_47);
++         _18 = Poll::<()>::Ready(move _46);
++         StorageDead(_46);
++         StorageDead(_55);
++         StorageDead(_53);
++         StorageDead(_50);
++         StorageDead(_49);
 +         StorageDead(_22);
 +         StorageDead(_19);
 +         _25 = discriminant(_18);
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs
index b1af81423cea..6047ac2167a3 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop.rs
@@ -11,10 +11,10 @@
 //@ edition: 2021
 
 // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests
-use core::future::{async_drop_in_place, AsyncDrop, Future};
+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::pin::{Pin, pin};
 use core::task::{Context, Poll, Waker};
 
 async fn test_async_drop<T>(x: T, _size: usize) {
@@ -26,8 +26,8 @@ async fn test_async_drop<T>(x: T, _size: usize) {
     // async functions.
     #[cfg(target_pointer_width = "64")]
     assert_eq!(
-        mem::size_of_val(&*dtor),
         _size,
+        mem::size_of_val(&*dtor),
         "sizes did not match for async destructor of type {}",
         core::any::type_name::<T>(),
     );
@@ -53,20 +53,18 @@ fn main() {
     let i = 13;
     let fut = pin!(async {
         test_async_drop(Int(0), 0).await;
-        // FIXME(#63818): niches in coroutines are disabled.
-        // Some of these sizes should be smaller, as indicated in comments.
-        test_async_drop(AsyncInt(0), /*104*/ 112).await;
-        test_async_drop([AsyncInt(1), AsyncInt(2)], /*152*/ 168).await;
-        test_async_drop((AsyncInt(3), AsyncInt(4)), /*488*/ 528).await;
+        test_async_drop(AsyncInt(0), 56).await;
+        test_async_drop([AsyncInt(1), AsyncInt(2)], 96).await;
+        test_async_drop((AsyncInt(3), AsyncInt(4)), 144).await;
         test_async_drop(5, 0).await;
         let j = 42;
         test_async_drop(&i, 0).await;
         test_async_drop(&j, 0).await;
-        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, /*1688*/ 1792).await;
+        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 200).await;
         test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await;
 
         let foo = AsyncInt(10);
-        test_async_drop(AsyncReference { foo: &foo }, /*104*/ 112).await;
+        test_async_drop(AsyncReference { foo: &foo }, 56).await;
 
         let foo = AsyncInt(11);
         test_async_drop(
@@ -75,17 +73,17 @@ fn main() {
                 let foo = AsyncInt(10);
                 foo
             },
-            /*120*/ 136,
+            72,
         )
         .await;
 
-        test_async_drop(AsyncEnum::A(AsyncInt(12)), /*680*/ 736).await;
-        test_async_drop(AsyncEnum::B(SyncInt(13)), /*680*/ 736).await;
+        test_async_drop(AsyncEnum::A(AsyncInt(12)), 168).await;
+        test_async_drop(AsyncEnum::B(SyncInt(13)), 168).await;
 
         test_async_drop(SyncInt(14), /*16*/ 24).await;
         test_async_drop(
             SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) },
-            /*3064*/ 3296,
+            232,
         )
         .await;
 
@@ -101,11 +99,11 @@ fn main() {
                 black_box(core::future::ready(())).await;
                 foo
             },
-            /*120*/ 136,
+            72,
         )
         .await;
 
-        test_async_drop(AsyncUnion { signed: 21 }, /*32*/ 40).await;
+        test_async_drop(AsyncUnion { signed: 21 }, 32).await;
     });
     let res = fut.poll(&mut cx);
     assert_eq!(res, Poll::Ready(()));
@@ -149,7 +147,10 @@ struct AsyncReference<'a> {
 }
 
 impl AsyncDrop for AsyncReference<'_> {
-    type Dropper<'a> = impl Future<Output = ()> where Self: 'a;
+    type Dropper<'a>
+        = impl Future<Output = ()>
+    where
+        Self: 'a;
 
     fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
         async move {
@@ -212,11 +213,9 @@ impl AsyncDrop for AsyncUnion {
 
     fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
         async move {
-            println!(
-                "AsyncUnion::Dropper::poll: {}, {}",
-                unsafe { self.signed },
-                unsafe { self.unsigned },
-            );
+            println!("AsyncUnion::Dropper::poll: {}, {}", unsafe { self.signed }, unsafe {
+                self.unsigned
+            },);
         }
     }
 }
diff --git a/tests/ui/async-await/awaiting-unsized-param.rs b/tests/ui/async-await/awaiting-unsized-param.rs
index 45611eae41f5..b00b23c1139e 100644
--- a/tests/ui/async-await/awaiting-unsized-param.rs
+++ b/tests/ui/async-await/awaiting-unsized-param.rs
@@ -7,6 +7,7 @@ use std::future::Future;
 
 async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
     //~^ ERROR the size for values of type `(dyn Future<Output = T> + Unpin + 'static)` cannot be known at compilation time
+    //~| ERROR the size for values of type `dyn Future<Output = T> + Unpin` cannot be known at compilation time
     (&mut f).await
 }
 
diff --git a/tests/ui/async-await/awaiting-unsized-param.stderr b/tests/ui/async-await/awaiting-unsized-param.stderr
index 0104736976d5..4095ca21007b 100644
--- a/tests/ui/async-await/awaiting-unsized-param.stderr
+++ b/tests/ui/async-await/awaiting-unsized-param.stderr
@@ -16,6 +16,15 @@ LL | async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
    = help: the trait `Sized` is not implemented for `(dyn Future<Output = T> + Unpin + 'static)`
    = note: all values captured by value by a closure must have a statically known size
 
-error: aborting due to 1 previous error; 1 warning emitted
+error[E0277]: the size for values of type `dyn Future<Output = T> + Unpin` cannot be known at compilation time
+  --> $DIR/awaiting-unsized-param.rs:8:21
+   |
+LL | async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
+   |                     ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `dyn Future<Output = T> + Unpin`
+   = note: all values live across `await` must have a statically known size
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
index 642e27b2a57d..c7342b38cc50 100644
--- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -1,39 +1,36 @@
-print-type-size type: `{async fn body of test()}`: 3078 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 2053 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
-print-type-size     variant `Suspend0`: 3077 bytes
-print-type-size         local `.__awaitee`: 3077 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
+print-type-size     variant `Suspend0`: 2052 bytes
+print-type-size         local `.__awaitee`: 2052 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
-print-type-size     field `.value`: 3077 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
-print-type-size     variant `MaybeUninit`: 3077 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 2052 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 2052 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 2052 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 2052 bytes
 print-type-size         field `.uninit`: 0 bytes
-print-type-size         field `.value`: 3077 bytes
-print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes
+print-type-size         field `.value`: 2052 bytes
+print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 2052 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
-print-type-size     variant `Unresumed`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes
-print-type-size     variant `Suspend0`: 2052 bytes
-print-type-size         upvar `.fut`: 1025 bytes
+print-type-size     variant `Unresumed`: 2051 bytes
+print-type-size         upvar `.fut`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         padding: 1026 bytes
+print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size     variant `Suspend0`: 1027 bytes
 print-type-size         local `.fut`: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
-print-type-size     variant `Suspend1`: 3076 bytes
-print-type-size         upvar `.fut`: 1025 bytes
+print-type-size     variant `Suspend1`: 2051 bytes
 print-type-size         padding: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
-print-type-size     variant `Suspend2`: 2052 bytes
-print-type-size         upvar `.fut`: 1025 bytes
+print-type-size     variant `Suspend2`: 1027 bytes
 print-type-size         local `.fut`: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
-print-type-size     variant `Returned`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes
-print-type-size     variant `Panicked`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
 print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1025 bytes
 print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
@@ -43,11 +40,16 @@ print-type-size         field `.value`: 1025 bytes
 print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
-print-type-size         upvar `.arg`: 1024 bytes
-print-type-size     variant `Returned`: 1024 bytes
-print-type-size         upvar `.arg`: 1024 bytes
-print-type-size     variant `Panicked`: 1024 bytes
-print-type-size         upvar `.arg`: 1024 bytes
+print-type-size         upvar `.arg`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.arg`: 1024 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1024 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1024 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1024 bytes
 print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
 print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs
index 317c17b9b3e5..3bbbadc2099d 100644
--- a/tests/ui/async-await/future-sizes/future-as-arg.rs
+++ b/tests/ui/async-await/future-sizes/future-as-arg.rs
@@ -8,9 +8,10 @@ async fn use_future(fut: impl std::future::Future<Output = ()>) {
 }
 
 fn main() {
-    let actual = std::mem::size_of_val(
-        &use_future(use_future(use_future(use_future(use_future(test([0; 16])))))));
+    let actual = std::mem::size_of_val(&use_future(use_future(use_future(use_future(
+        use_future(test([0; 16])),
+    )))));
     // Not using an exact number in case it slightly changes over different commits
-    let expected = 550;
-    assert!(actual > expected, "expected: >{expected}, actual: {actual}");
+    let expected = 21;
+    assert!(actual >= expected, "expected: >{expected}, actual: {actual}");
 }
diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout
index 67168a3d6ef7..8e62f7f1775b 100644
--- a/tests/ui/async-await/future-sizes/large-arg.stdout
+++ b/tests/ui/async-await/future-sizes/large-arg.stdout
@@ -1,44 +1,40 @@
-print-type-size type: `{async fn body of test()}`: 3076 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 1028 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
-print-type-size     variant `Suspend0`: 3075 bytes
-print-type-size         local `.__awaitee`: 3075 bytes, type: {async fn body of a<[u8; 1024]>()}
+print-type-size     variant `Suspend0`: 1027 bytes
+print-type-size         local `.__awaitee`: 1027 bytes, type: {async fn body of a<[u8; 1024]>()}
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
-print-type-size     field `.value`: 3075 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
-print-type-size     variant `MaybeUninit`: 3075 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 1027 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1027 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 1027 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1027 bytes
 print-type-size         field `.uninit`: 0 bytes
-print-type-size         field `.value`: 3075 bytes
-print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 3075 bytes, alignment: 1 bytes
+print-type-size         field `.value`: 1027 bytes
+print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 1027 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Suspend0`: 3074 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size         local `.__awaitee`: 2050 bytes, type: {async fn body of b<[u8; 1024]>()}
-print-type-size     variant `Returned`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Panicked`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
-print-type-size     field `.value`: 2050 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
-print-type-size     variant `MaybeUninit`: 2050 bytes
+print-type-size         upvar `.t`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.t`: 1024 bytes
+print-type-size     variant `Suspend0`: 1026 bytes
+print-type-size         local `.__awaitee`: 1026 bytes, type: {async fn body of b<[u8; 1024]>()}
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 1026 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1026 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 1026 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1026 bytes
 print-type-size         field `.uninit`: 0 bytes
-print-type-size         field `.value`: 2050 bytes
-print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 2050 bytes, alignment: 1 bytes
+print-type-size         field `.value`: 1026 bytes
+print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 1026 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Suspend0`: 2049 bytes
-print-type-size         upvar `.t`: 1024 bytes
+print-type-size         upvar `.t`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.t`: 1024 bytes
+print-type-size     variant `Suspend0`: 1025 bytes
 print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of c<[u8; 1024]>()}
-print-type-size     variant `Returned`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Panicked`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
 print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1025 bytes
 print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
@@ -53,8 +49,13 @@ print-type-size     variant `Pending`: 0 bytes
 print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Returned`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
-print-type-size     variant `Panicked`: 1024 bytes
-print-type-size         upvar `.t`: 1024 bytes
+print-type-size         upvar `.t`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.t`: 1024 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1024 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1024 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1024 bytes
diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs
index 36295a84e7ad..837d532e067d 100644
--- a/tests/ui/async-await/issue-70818.rs
+++ b/tests/ui/async-await/issue-70818.rs
@@ -3,6 +3,7 @@
 use std::future::Future;
 fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
     //~^ Error future cannot be sent between threads safely
+    //~| Error future cannot be sent between threads safely
     async { (ty, ty1) }
 }
 
diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr
index 8de6a825042b..d4fe930ce18b 100644
--- a/tests/ui/async-await/issue-70818.stderr
+++ b/tests/ui/async-await/issue-70818.stderr
@@ -5,7 +5,7 @@ LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
 note: captured value is not `Send`
-  --> $DIR/issue-70818.rs:6:18
+  --> $DIR/issue-70818.rs:7:18
    |
 LL |     async { (ty, ty1) }
    |                  ^^^ has type `U` which is not `Send`
@@ -14,5 +14,21 @@ help: consider restricting type parameter `U` with trait `Send`
 LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
    |                  +++++++++++++++++++
 
-error: aborting due to 1 previous error
+error: future cannot be sent between threads safely
+  --> $DIR/issue-70818.rs:4:38
+   |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+   |
+note: captured value is not `Send`
+  --> $DIR/issue-70818.rs:4:27
+   |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+   |                           ^^^ has type `U` which is not `Send`
+help: consider restricting type parameter `U` with trait `Send`
+   |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+   |                  +++++++++++++++++++
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
index f6c9fdd6d680..75d303751bc7 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
@@ -9,27 +9,27 @@ pub async fn async_fn(x: &mut i32) -> &i32 {
     y
 }
 
-pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
+pub fn async_closure(x: &mut i32) -> impl Future<Output = &i32> {
     (async move || {
         //~^ ERROR lifetime may not live long enough
         //~| ERROR temporary value dropped while borrowed
         let y = &*x;
-        *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+        *x += 1; //~ ERROR cannot assign to value because it is borrowed
         y
     })()
 }
 
-pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
+pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output = &i32> {
     (async move || -> &i32 {
         //~^ ERROR lifetime may not live long enough
         //~| ERROR temporary value dropped while borrowed
         let y = &*x;
-        *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
+        *x += 1; //~ ERROR cannot assign to value because it is borrowed
         y
     })()
 }
 
-pub fn async_block(x: &mut i32) -> impl Future<Output=&i32> {
+pub fn async_block(x: &mut i32) -> impl Future<Output = &i32> {
     async move {
         let y = &*x;
         *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
index e1f268116fc5..52d549d0b206 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -10,18 +10,18 @@ LL |     *x += 1;
 LL |     y
    |     - returning this value requires that `*x` is borrowed for `'1`
 
-error[E0506]: cannot assign to `*x` because it is borrowed
+error[E0506]: cannot assign to value because it is borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
    |
 LL |     (async move || {
    |                  - return type of async closure is &'1 i32
 ...
 LL |         let y = &*x;
-   |                 --- `*x` is borrowed here
+   |                 --- value is borrowed here
 LL |         *x += 1;
-   |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
+   |         ^^^^^^^ value is assigned to here but it was already borrowed
 LL |         y
-   |         - returning this value requires that `*x` is borrowed for `'1`
+   |         - returning this value requires that borrow lasts for `'1`
 
 error: lifetime may not live long enough
   --> $DIR/issue-74072-lifetime-name-annotations.rs:13:20
@@ -44,7 +44,7 @@ LL | |     })()
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:13:5
    |
-LL |    pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
+LL |    pub fn async_closure(x: &mut i32) -> impl Future<Output = &i32> {
    |                            - let's call the lifetime of this reference `'1`
 LL | //     (async move || {
 LL | ||
@@ -59,18 +59,18 @@ LL | ||     })()
 LL |    }
    |    - temporary value is freed at the end of this statement
 
-error[E0506]: cannot assign to `*x` because it is borrowed
+error[E0506]: cannot assign to value because it is borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:27:9
    |
 LL |     (async move || -> &i32 {
    |                          - return type of async closure is &'1 i32
 ...
 LL |         let y = &*x;
-   |                 --- `*x` is borrowed here
+   |                 --- value is borrowed here
 LL |         *x += 1;
-   |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
+   |         ^^^^^^^ value is assigned to here but it was already borrowed
 LL |         y
-   |         - returning this value requires that `*x` is borrowed for `'1`
+   |         - returning this value requires that borrow lasts for `'1`
 
 error: lifetime may not live long enough
   --> $DIR/issue-74072-lifetime-name-annotations.rs:23:28
@@ -93,7 +93,7 @@ LL | |     })()
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:23:5
    |
-LL |    pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
+LL |    pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output = &i32> {
    |                                                 - let's call the lifetime of this reference `'1`
 LL | //     (async move || -> &i32 {
 LL | ||
diff --git a/tests/ui/async-await/issue-86507.rs b/tests/ui/async-await/issue-86507.rs
index 484122a1ddcf..e959f2c1166f 100644
--- a/tests/ui/async-await/issue-86507.rs
+++ b/tests/ui/async-await/issue-86507.rs
@@ -15,6 +15,7 @@ impl Foo for () {
         -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
         where 'me:'async_trait {
             Box::pin( //~ ERROR future cannot be sent between threads safely
+                //~^ ERROR future cannot be sent between threads safely
                 async move {
                     let x = x;
                 }
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr
index 6385a8c975e3..83a2c9fe95c0 100644
--- a/tests/ui/async-await/issue-86507.stderr
+++ b/tests/ui/async-await/issue-86507.stderr
@@ -2,6 +2,7 @@ error: future cannot be sent between threads safely
   --> $DIR/issue-86507.rs:17:13
    |
 LL | /             Box::pin(
+LL | |
 LL | |                 async move {
 LL | |                     let x = x;
 LL | |                 }
@@ -9,15 +10,37 @@ LL | |             )
    | |_____________^ future created by async block is not `Send`
    |
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> $DIR/issue-86507.rs:19:29
+  --> $DIR/issue-86507.rs:20:29
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
+   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:19:17: 19:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
 help: consider further restricting type parameter `T` with trait `Sync`
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
    |                                       +++++++++++++++++++
 
-error: aborting due to 1 previous error
+error: future cannot be sent between threads safely
+  --> $DIR/issue-86507.rs:17:13
+   |
+LL | /             Box::pin(
+LL | |
+LL | |                 async move {
+LL | |                     let x = x;
+LL | |                 }
+LL | |             )
+   | |_____________^ future created by async block is not `Send`
+   |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+  --> $DIR/issue-86507.rs:14:40
+   |
+LL |     fn bar<'me, 'async_trait, T: Send>(x: &'me T)
+   |                                        ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:19:17: 19:27}>>` to `Pin<Box<dyn Future<Output = ()> + Send>>`
+help: consider further restricting type parameter `T` with trait `Sync`
+   |
+LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
+   |                                       +++++++++++++++++++
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs
index 4c239f9ee76c..c1ad400363af 100644
--- a/tests/ui/coroutine/auto-trait-regions.rs
+++ b/tests/ui/coroutine/auto-trait-regions.rs
@@ -30,6 +30,8 @@ fn main() {
     };
     assert_foo(gen);
     //~^ ERROR implementation of `Foo` is not general enough
+    //~| ERROR implementation of `Foo` is not general enough
+    //~| ERROR implementation of `Foo` is not general enough
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr
index a9a0bde2ba01..8ffa6ab6a549 100644
--- a/tests/ui/coroutine/auto-trait-regions.stderr
+++ b/tests/ui/coroutine/auto-trait-regions.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:45:24
+  --> $DIR/auto-trait-regions.rs:47:24
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                        ^^^^                - temporary value is freed at the end of this statement
@@ -16,7 +16,7 @@ LL ~         let a = A(&mut binding, &mut true, No);
    |
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:45:35
+  --> $DIR/auto-trait-regions.rs:47:35
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                                   ^^^^     - temporary value is freed at the end of this statement
@@ -42,7 +42,27 @@ LL |     assert_foo(gen);
    = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
 
 error: implementation of `Foo` is not general enough
-  --> $DIR/auto-trait-regions.rs:51:5
+  --> $DIR/auto-trait-regions.rs:31:5
+   |
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+   |
+   = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
+   = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:31:5
+   |
+LL |     assert_foo(gen);
+   |     ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+   |
+   = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
+   = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:53:5
    |
 LL |     assert_foo(gen);
    |     ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
@@ -50,6 +70,6 @@ LL |     assert_foo(gen);
    = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
    = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index ed933fe784ed..f8c1b7ae65bf 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -7,11 +7,14 @@ LL |     move || {
 LL |     check_copy(&gen_clone_0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
-note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:48:14
+note: coroutine does not implement `Copy` as this value is used across a yield
+  --> $DIR/clone-impl.rs:46:9
    |
-LL |         drop(clonable_0);
-   |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
+LL |     let clonable_0: Vec<u32> = Vec::new();
+   |         ---------- has type `Vec<u32>` which does not implement `Copy`
+...
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `clonable_0` maybe used later
 note: required by a bound in `check_copy`
   --> $DIR/clone-impl.rs:90:18
    |
@@ -49,11 +52,14 @@ LL |     move || {
 LL |     check_copy(&gen_clone_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
-note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:69:14
+note: coroutine does not implement `Copy` as this value is used across a yield
+  --> $DIR/clone-impl.rs:65:9
    |
-LL |         drop(clonable_1);
-   |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
+LL |     let clonable_1: Vec<u32> = Vec::new();
+   |         ---------- has type `Vec<u32>` which does not implement `Copy`
+...
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `clonable_1` maybe used later
 note: required by a bound in `check_copy`
   --> $DIR/clone-impl.rs:90:18
    |
@@ -92,11 +98,14 @@ LL |     move || {
 LL |     check_copy(&gen_non_clone);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Copy` is not implemented for `NonClone`
    |
-note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:82:14
+note: coroutine does not implement `Copy` as this value is used across a yield
+  --> $DIR/clone-impl.rs:81:9
    |
-LL |         drop(non_clonable);
-   |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
+LL |     let non_clonable: NonClone = NonClone;
+   |         ------------ has type `NonClone` which does not implement `Copy`
+...
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `non_clonable` maybe used later
 note: required by a bound in `check_copy`
   --> $DIR/clone-impl.rs:90:18
    |
@@ -117,11 +126,14 @@ LL |     move || {
 LL |     check_clone(&gen_non_clone);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Clone` is not implemented for `NonClone`
    |
-note: captured value does not implement `Clone`
-  --> $DIR/clone-impl.rs:82:14
+note: coroutine does not implement `Clone` as this value is used across a yield
+  --> $DIR/clone-impl.rs:81:9
    |
-LL |         drop(non_clonable);
-   |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
+LL |     let non_clonable: NonClone = NonClone;
+   |         ------------ has type `NonClone` which does not implement `Clone`
+...
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `non_clonable` maybe used later
 note: required by a bound in `check_clone`
   --> $DIR/clone-impl.rs:91:19
    |
diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
index 0f9c56786da0..def6fc060072 100644
--- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
@@ -1,16 +1,13 @@
 #![feature(coroutines, stmt_expr_attributes)]
 
 fn foo(x: &i32) {
-    // In this case, a reference to `b` escapes the coroutine, but not
-    // because of a yield. We see that there is no yield in the scope of
-    // `b` and give the more generic error message.
-    let mut a = &3;
+    let a = &mut &3;
     let mut b = #[coroutine]
     move || {
         yield ();
         let b = 5;
-        a = &b;
-        //~^ ERROR borrowed data escapes outside of coroutine
+        *a = &b;
+        //~^ ERROR: borrowed data escapes outside of coroutine
     };
 }
 
diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
index 6fa7082c0b8b..4e4577c9ceb5 100644
--- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
@@ -1,13 +1,13 @@
 error[E0521]: borrowed data escapes outside of coroutine
-  --> $DIR/ref-escapes-but-not-over-yield.rs:12:9
+  --> $DIR/ref-escapes-but-not-over-yield.rs:9:9
    |
-LL |     let mut a = &3;
-   |         ----- `a` declared here, outside of the coroutine body
+LL |     let a = &mut &3;
+   |         - `a` declared here, outside of the coroutine body
 ...
-LL |         a = &b;
-   |         ^^^^--
-   |         |   |
-   |         |   borrow is only valid in the coroutine body
+LL |         *a = &b;
+   |         ^^^^^--
+   |         |    |
+   |         |    borrow is only valid in the coroutine body
    |         reference to `b` escapes the coroutine body here
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coroutine/ref-upvar-not-send.rs b/tests/ui/coroutine/ref-upvar-not-send.rs
index 89bb5e5495f4..387c21015744 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.rs
+++ b/tests/ui/coroutine/ref-upvar-not-send.rs
@@ -8,24 +8,42 @@ fn assert_send<T: Send>(_: T) {}
 //~| NOTE required by this bound in `assert_send`
 //~| NOTE required by a bound in `assert_send`
 //~| NOTE required by this bound in `assert_send`
+//~| NOTE required by a bound in `assert_send`
+//~| NOTE required by this bound in `assert_send`
+//~| NOTE required by a bound in `assert_send`
+//~| NOTE required by this bound in `assert_send`
 
 fn main() {
     let x: &*mut () = &std::ptr::null_mut();
+    //~^ NOTE has type `&*mut ()` which is not `Send`
+    //~| NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
     let y: &mut *mut () = &mut std::ptr::null_mut();
-    assert_send(#[coroutine] move || {
+    //~^ NOTE has type `&mut *mut ()` which is not `Send`
+    //~| NOTE captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
+    assert_send(
         //~^ ERROR coroutine cannot be sent between threads safely
         //~| NOTE coroutine is not `Send`
-        yield;
-        let _x = x;
-    });
-    //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-    //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
-    assert_send(#[coroutine] move || {
+        #[coroutine]
+        move || {
+            //~^ ERROR coroutine cannot be sent between threads safely
+            //~| NOTE coroutine is not `Send`
+            yield;
+            let _x = x;
+            //~^ NOTE captured value is not `Send`
+            //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
+        },
+    );
+    assert_send(
         //~^ ERROR coroutine cannot be sent between threads safely
         //~| NOTE coroutine is not `Send`
-        yield;
-        let _y = y;
-    });
-    //~^^ NOTE captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
-    //~| NOTE has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+        #[coroutine]
+        move || {
+            //~^ ERROR coroutine cannot be sent between threads safely
+            //~| NOTE coroutine is not `Send`
+            yield;
+            let _y = y;
+            //~^ NOTE captured value is not `Send`
+            //~| NOTE has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+        },
+    );
 }
diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr
index 892b5d261c2b..48c0619172ea 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.stderr
+++ b/tests/ui/coroutine/ref-upvar-not-send.stderr
@@ -1,21 +1,67 @@
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:15:30
+  --> $DIR/ref-upvar-not-send.rs:27:9
    |
-LL |       assert_send(#[coroutine] move || {
-   |  ______________________________^
+LL | /         move || {
 LL | |
 LL | |
-LL | |         yield;
-LL | |         let _x = x;
-LL | |     });
+LL | |             yield;
+...  |
+LL | |         },
+   | |_________^ coroutine is not `Send`
+   |
+   = help: the trait `Sync` is not implemented for `*mut ()`
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+  --> $DIR/ref-upvar-not-send.rs:31:22
+   |
+LL |             let _x = x;
+   |                      ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
+note: required by a bound in `assert_send`
+  --> $DIR/ref-upvar-not-send.rs:6:19
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error: coroutine cannot be sent between threads safely
+  --> $DIR/ref-upvar-not-send.rs:40:9
+   |
+LL | /         move || {
+LL | |
+LL | |
+LL | |             yield;
+...  |
+LL | |         },
+   | |_________^ coroutine is not `Send`
+   |
+   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:40:9: 40:16}`, the trait `Send` is not implemented for `*mut ()`
+note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
+  --> $DIR/ref-upvar-not-send.rs:44:22
+   |
+LL |             let _y = y;
+   |                      ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+note: required by a bound in `assert_send`
+  --> $DIR/ref-upvar-not-send.rs:6:19
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error: coroutine cannot be sent between threads safely
+  --> $DIR/ref-upvar-not-send.rs:23:5
+   |
+LL | /     assert_send(
+LL | |
+LL | |
+LL | |         #[coroutine]
+...  |
+LL | |         },
+LL | |     );
    | |_____^ coroutine is not `Send`
    |
    = help: the trait `Sync` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
-  --> $DIR/ref-upvar-not-send.rs:19:18
+  --> $DIR/ref-upvar-not-send.rs:17:9
    |
-LL |         let _x = x;
-   |                  ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
+LL |     let x: &*mut () = &std::ptr::null_mut();
+   |         ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
 note: required by a bound in `assert_send`
   --> $DIR/ref-upvar-not-send.rs:6:19
    |
@@ -23,28 +69,28 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:23:30
+  --> $DIR/ref-upvar-not-send.rs:36:5
    |
-LL |       assert_send(#[coroutine] move || {
-   |  ______________________________^
+LL | /     assert_send(
 LL | |
 LL | |
-LL | |         yield;
-LL | |         let _y = y;
-LL | |     });
+LL | |         #[coroutine]
+...  |
+LL | |         },
+LL | |     );
    | |_____^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`
+   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:40:9: 40:16}`, the trait `Send` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
-  --> $DIR/ref-upvar-not-send.rs:27:18
+  --> $DIR/ref-upvar-not-send.rs:20:9
    |
-LL |         let _y = y;
-   |                  ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
+LL |     let y: &mut *mut () = &mut std::ptr::null_mut();
+   |         ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
 note: required by a bound in `assert_send`
   --> $DIR/ref-upvar-not-send.rs:6:19
    |
 LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/coroutine/unsized-capture-across-yield.rs b/tests/ui/coroutine/unsized-capture-across-yield.rs
index c86b1823aaff..27b0581e8d7b 100644
--- a/tests/ui/coroutine/unsized-capture-across-yield.rs
+++ b/tests/ui/coroutine/unsized-capture-across-yield.rs
@@ -7,6 +7,7 @@ use std::ops::Coroutine;
 
 fn capture() -> impl Coroutine {
     let b: [u8] = *(Box::new([]) as Box<[u8]>);
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
     #[coroutine]
     move || {
         println!("{:?}", &b);
diff --git a/tests/ui/coroutine/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr
index 03551f1bbff5..6faa9226f912 100644
--- a/tests/ui/coroutine/unsized-capture-across-yield.stderr
+++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-capture-across-yield.rs:12:27
+  --> $DIR/unsized-capture-across-yield.rs:13:27
    |
 LL |     move || {
    |          -- this closure captures all values by move
@@ -18,6 +18,15 @@ LL |         println!("{:?}", &b);
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: all values captured by value by a closure must have a statically known size
 
-error: aborting due to 1 previous error; 1 warning emitted
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-capture-across-yield.rs:9:9
+   |
+LL |     let b: [u8] = *(Box::new([]) as Box<[u8]>);
+   |         ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all values live across `yield` must have a statically known size
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 2d2731e4368f..63d373088eca 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -92,6 +92,12 @@ error[E0720]: cannot resolve opaque type
    |
 LL |   fn coroutine_capture() -> impl Sized {
    |                             ^^^^^^^^^^ recursive opaque type
+LL |
+LL |       let x = coroutine_capture();
+   |           -
+   |           |
+   |           coroutine captures itself here
+   |           coroutine captures itself here
 ...
 LL | /     move || {
 LL | |         yield;
diff --git a/tests/ui/mir/lint/storage-live.stderr b/tests/ui/mir/lint/storage-live.stderr
index 651b8e2327ee..1b936ea12692 100644
--- a/tests/ui/mir/lint/storage-live.stderr
+++ b/tests/ui/mir/lint/storage-live.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (after pass CheckForceInline) at bb0[1]:
+error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (after pass CheckForceInline 1-1-000) at bb0[1]:
                                 StorageLive(_1) which already has storage here
   --> $DIR/storage-live.rs:23:13
    |
diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout
index 83a6962e4cd1..6bc30dc71154 100644
--- a/tests/ui/print_type_sizes/async.stdout
+++ b/tests/ui/print_type_sizes/async.stdout
@@ -1,15 +1,13 @@
-print-type-size type: `{async fn body of test()}`: 16386 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 8194 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 8192 bytes
-print-type-size         upvar `.arg`: 8192 bytes
-print-type-size     variant `Suspend0`: 16385 bytes
-print-type-size         upvar `.arg`: 8192 bytes
+print-type-size         upvar `.arg`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         local `.arg`: 8192 bytes
+print-type-size     variant `Suspend0`: 8193 bytes
 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
-print-type-size     variant `Returned`: 8192 bytes
-print-type-size         upvar `.arg`: 8192 bytes
-print-type-size     variant `Panicked`: 8192 bytes
-print-type-size         upvar `.arg`: 8192 bytes
+print-type-size         local `.arg`: 8192 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
 print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 8192 bytes
 print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/coroutine.stdout b/tests/ui/print_type_sizes/coroutine.stdout
index 339bbddfc2a9..6abee21d415b 100644
--- a/tests/ui/print_type_sizes/coroutine.stdout
+++ b/tests/ui/print_type_sizes/coroutine.stdout
@@ -1,10 +1,15 @@
 print-type-size type: `{coroutine@$DIR/coroutine.rs:11:5: 11:14}`: 8193 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 8192 bytes
-print-type-size         upvar `.array`: 8192 bytes
+print-type-size         upvar `.array`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.array`: 8192 bytes
 print-type-size     variant `Suspend0`: 8192 bytes
-print-type-size         upvar `.array`: 8192 bytes
-print-type-size     variant `Returned`: 8192 bytes
-print-type-size         upvar `.array`: 8192 bytes
-print-type-size     variant `Panicked`: 8192 bytes
-print-type-size         upvar `.array`: 8192 bytes
+print-type-size         local `.array`: 8192 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 8192 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 8192 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 8192 bytes
diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout
index 21df1fd39540..4167af21cea4 100644
--- a/tests/ui/stable-mir-print/async-closure.stdout
+++ b/tests/ui/stable-mir-print/async-closure.stdout
@@ -27,13 +27,13 @@ fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {a
 fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
     let mut _0: Poll<()>;
     let  _3: i32;
-    let mut _4: &i32;
+    let  _4: &i32;
     let mut _5: u32;
     let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     debug _task_context => _2;
-    debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
+    debug y => (*_4);
     debug y => _3;
     bb0: {
         _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
@@ -42,7 +42,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
     }
     bb1: {
         _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _4 = CopyForDeref(((*_7).0: &i32));
+        _4 = move (((*_7) as variant#0).0: &i32);
         _3 = (*_4);
         _0 = std::task::Poll::Ready(());
         _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
@@ -59,13 +59,13 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
 fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
     let mut _0: Poll<()>;
     let  _3: i32;
-    let mut _4: &i32;
+    let  _4: &i32;
     let mut _5: u32;
     let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
     debug _task_context => _2;
-    debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
+    debug y => (*_4);
     debug y => _3;
     bb0: {
         _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
@@ -74,7 +74,7 @@ fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-clo
     }
     bb1: {
         _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        _4 = CopyForDeref(((*_7).0: &i32));
+        _4 = move (((*_7) as variant#0).0: &i32);
         _3 = (*_4);
         _0 = std::task::Poll::Ready(());
         _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index 2ca6a1994485..c12a270e8a2b 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -39,13 +39,13 @@ LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:14:5
+  --> $DIR/hkl_forbidden4.rs:14:21
    |
 LL | async fn operation(_: &mut ()) -> () {
    |                       - this generic parameter must be used with a generic lifetime parameter
 LL |
 LL |     call(operation).await
-   |     ^^^^^^^^^^^^^^^
+   |                     ^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
   --> $DIR/hkl_forbidden4.rs:23:1