about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs10
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl3
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs117
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs4
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs55
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs154
-rw-r--r--compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs10
-rw-r--r--compiler/rustc_codegen_gcc/example/std_example.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0626.md20
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0627.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0628.md8
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0727.md8
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs6
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_fs_util/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs42
-rw-r--r--compiler/rustc_middle/src/lib.rs3
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs82
-rw-r--r--compiler/rustc_middle/src/ty/context.rs29
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs13
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs10
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs14
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_resolve/src/lib.rs16
-rw-r--r--compiler/rustc_serialize/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/config.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs2
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs2
54 files changed, 531 insertions, 276 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index bddb50568d4..727c6bc82fe 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3112,6 +3112,7 @@ pub struct Delegation {
     /// Path resolution id.
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
+    pub rename: Option<Ident>,
     pub path: Path,
     pub body: Option<P<Block>>,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index c4e49d7dbea..7dbfb7c7364 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1149,10 +1149,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         }
         ItemKind::MacCall(m) => vis.visit_mac_call(m),
         ItemKind::MacroDef(def) => vis.visit_macro_def(def),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             vis.visit_id(id);
             vis.visit_qself(qself);
             vis.visit_path(path);
+            if let Some(rename) = rename {
+                vis.visit_ident(rename);
+            }
             if let Some(body) = body {
                 vis.visit_block(body);
             }
@@ -1195,10 +1198,13 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
         AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             visitor.visit_id(id);
             visitor.visit_qself(qself);
             visitor.visit_path(path);
+            if let Some(rename) = rename {
+                visitor.visit_ident(rename);
+            }
             if let Some(body) = body {
                 visitor.visit_block(body);
             }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 968d10ad487..d9740928f8d 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -382,11 +382,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu
         }
         ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
         ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
@@ -782,11 +783,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
         AssocItemKind::MacCall(mac) => {
             try_visit!(visitor.visit_mac_call(mac));
         }
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index a23e714ef01..73001c9990c 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign =
     .label = `_` not allowed here
 
 ast_lowering_use_angle_brackets = use angle brackets instead
+ast_lowering_yield_in_closure =
+    `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+    .suggestion = use `#[coroutine]` to make this closure a coroutine
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f4d5e71bade..a1e5c275c18 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -49,7 +49,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::ResolverAstLowering;
+use rustc_middle::ty::{Asyncness, ResolverAstLowering};
 use rustc_span::{symbol::Ident, Span};
 use rustc_target::spec::abi;
 use std::iter;
@@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return false;
         };
         if let Some(local_sig_id) = sig_id.as_local() {
-            self.resolver.has_self.contains(&local_sig_id)
+            self.resolver.delegation_fn_sigs[&local_sig_id].has_self
         } else {
             match self.tcx.def_kind(sig_id) {
                 DefKind::Fn => false,
@@ -82,13 +82,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         delegation: &Delegation,
         item_id: NodeId,
     ) -> DelegationResults<'hir> {
-        let span = delegation.path.segments.last().unwrap().ident.span;
+        let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
         let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
         match sig_id {
             Ok(sig_id) => {
-                let decl = self.lower_delegation_decl(sig_id, span);
-                let sig = self.lower_delegation_sig(span, decl);
-                let body_id = self.lower_delegation_body(sig.decl, delegation);
+                let (param_count, c_variadic) = self.param_count(sig_id);
+                let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
+                let sig = self.lower_delegation_sig(sig_id, decl, span);
+                let body_id = self.lower_delegation_body(delegation, param_count, span);
 
                 let generics = self.lower_delegation_generics(span);
                 DelegationResults { body_id, sig, generics }
@@ -123,34 +124,47 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    // Function parameter count, including C variadic `...` if present.
+    fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
+        if let Some(local_sig_id) = sig_id.as_local() {
+            // Map may be filled incorrectly due to recursive delegation.
+            // Error will be emmited later during HIR ty lowering.
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => (sig.param_count, sig.c_variadic),
+                None => (0, false),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            (sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
+        }
+    }
+
     fn lower_delegation_decl(
         &mut self,
         sig_id: DefId,
-        param_span: Span,
+        param_count: usize,
+        c_variadic: bool,
+        span: Span,
     ) -> &'hir hir::FnDecl<'hir> {
-        let args_count = if let Some(local_sig_id) = sig_id.as_local() {
-            // Map may be filled incorrectly due to recursive delegation.
-            // Error will be emitted later during HIR ty lowering.
-            self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
-        } else {
-            self.tcx.fn_arg_names(sig_id).len()
-        };
-        let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty {
+        // The last parameter in C variadic functions is skipped in the signature,
+        // like during regular lowering.
+        let decl_param_count = param_count - c_variadic as usize;
+        let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
-            span: self.lower_span(param_span),
+            span,
         }));
 
         let output = self.arena.alloc(hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
-            span: self.lower_span(param_span),
+            span,
         });
 
         self.arena.alloc(hir::FnDecl {
             inputs,
             output: hir::FnRetTy::Return(output),
-            c_variadic: false,
+            c_variadic,
             lifetime_elision_allowed: true,
             implicit_self: hir::ImplicitSelfKind::None,
         })
@@ -158,35 +172,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_delegation_sig(
         &mut self,
-        span: Span,
+        sig_id: DefId,
         decl: &'hir hir::FnDecl<'hir>,
+        span: Span,
     ) -> hir::FnSig<'hir> {
-        hir::FnSig {
-            decl,
-            header: hir::FnHeader {
-                unsafety: hir::Unsafety::Normal,
-                constness: hir::Constness::NotConst,
-                asyncness: hir::IsAsync::NotAsync,
-                abi: abi::Abi::Rust,
-            },
-            span: self.lower_span(span),
-        }
+        let header = if let Some(local_sig_id) = sig_id.as_local() {
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => self.lower_fn_header(sig.header),
+                None => self.generate_header_error(),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            let asyncness = match self.tcx.asyncness(sig_id) {
+                Asyncness::Yes => hir::IsAsync::Async(span),
+                Asyncness::No => hir::IsAsync::NotAsync,
+            };
+            hir::FnHeader {
+                unsafety: sig.unsafety,
+                constness: self.tcx.constness(sig_id),
+                asyncness,
+                abi: sig.abi,
+            }
+        };
+        hir::FnSig { decl, header, span }
     }
 
-    fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
+    fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) {
         let pat_node_id = self.next_node_id();
         let pat_id = self.lower_node_id(pat_node_id);
         let pat = self.arena.alloc(hir::Pat {
             hir_id: pat_id,
             kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
-            span: ty.span,
+            span,
             default_binding_modes: false,
         });
 
-        (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
+        (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
     }
 
-    fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
+    fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
         let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
             ident: Ident::empty(),
             hir_id: self.next_id(),
@@ -195,20 +219,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
             infer_args: false,
         }));
 
-        let path =
-            self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
+        let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
 
         hir::Expr {
             hir_id: self.next_id(),
             kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
-            span: ty.span,
+            span,
         }
     }
 
     fn lower_delegation_body(
         &mut self,
-        decl: &'hir hir::FnDecl<'hir>,
         delegation: &Delegation,
+        param_count: usize,
+        span: Span,
     ) -> BodyId {
         let path = self.lower_qpath(
             delegation.id,
@@ -224,8 +248,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let mut parameters: Vec<hir::Param<'_>> = Vec::new();
             let mut args: Vec<hir::Expr<'hir>> = Vec::new();
 
-            for (idx, param_ty) in decl.inputs.iter().enumerate() {
-                let (param, pat_node_id) = this.generate_param(param_ty);
+            for idx in 0..param_count {
+                let (param, pat_node_id) = this.generate_param(span);
                 parameters.push(param);
 
                 let arg = if let Some(block) = block
@@ -245,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 } else {
                     let pat_hir_id = this.lower_node_id(pat_node_id);
-                    this.generate_arg(param_ty, pat_hir_id)
+                    this.generate_arg(pat_hir_id, span)
                 };
                 args.push(arg);
             }
@@ -304,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             implicit_self: hir::ImplicitSelfKind::None,
         });
 
-        let sig = self.lower_delegation_sig(span, decl);
+        let header = self.generate_header_error();
+        let sig = hir::FnSig { decl, header, span };
+
         let body_id = self.lower_body(|this| {
             let expr =
                 hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
@@ -312,6 +338,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         });
         DelegationResults { generics, body_id, sig }
     }
+
+    fn generate_header_error(&self) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: hir::Unsafety::Normal,
+            constness: hir::Constness::NotConst,
+            asyncness: hir::IsAsync::NotAsync,
+            abi: abi::Abi::Rust,
+        }
+    }
 }
 
 struct SelfResolver<'a> {
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 6799513a323..6f70e135c72 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_yield_in_closure)]
+pub(crate) struct YieldInClosure {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
+    pub suggestion: Option<Span>,
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2305cc07795..5cc05d7336e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -8,6 +8,7 @@ use super::errors::{
 };
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use crate::errors::YieldInClosure;
 use crate::{FnDeclKind, ImplTraitPosition};
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
@@ -217,6 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         binder,
                         *capture_clause,
                         e.id,
+                        hir_id,
                         *constness,
                         *movability,
                         fn_decl,
@@ -955,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         constness: Const,
         movability: Movability,
         decl: &FnDecl,
@@ -965,8 +968,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
         let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
-            let mut coroutine_kind = None;
+            let mut coroutine_kind = if this
+                .attrs
+                .get(&closure_hir_id.local_id)
+                .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
+            {
+                Some(hir::CoroutineKind::Coroutine(Movability::Movable))
+            } else {
+                None
+            };
             let body_id = this.lower_fn_body(decl, |this| {
+                this.coroutine_kind = coroutine_kind;
                 let e = this.lower_expr_mut(body);
                 coroutine_kind = this.coroutine_kind;
                 e
@@ -1565,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     )
                     .emit();
                 }
+                let suggestion = self.current_item.map(|s| s.shrink_to_lo());
+                self.dcx().emit_err(YieldInClosure { span, suggestion });
                 self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
+
                 false
             }
         };
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e4c633aa324..dcce54d66c2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 body,
                 ..
             }) => {
-                self.with_new_scopes(ident.span, |this| {
+                self.with_new_scopes(*fn_sig_span, |this| {
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
@@ -1344,7 +1344,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
             hir::IsAsync::Async(span)
         } else {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 70a3ccb0f44..d86196cbaa9 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -556,7 +556,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         half_open_range_patterns_in_slices,
         "half-open range patterns in slices are unstable"
     );
-    gate_all!(inline_const, "inline-const is experimental");
     gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
     gate_all!(associated_const_equality, "associated const equality is incomplete");
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 4878da530b0..93ea8fb6979 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -347,7 +347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         mpi: MovePathIndex,
         err: &mut Diag<'tcx>,
         in_pattern: &mut bool,
-        move_spans: UseSpans<'_>,
+        move_spans: UseSpans<'tcx>,
     ) {
         let move_span = match move_spans {
             UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
@@ -491,11 +491,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     ..
                 } = move_spans
                 {
-                    self.suggest_cloning(err, ty, expr, None);
+                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 } else if self.suggest_hoisting_call_outside_loop(err, expr) {
                     // The place where the the type moves would be misleading to suggest clone.
                     // #121466
-                    self.suggest_cloning(err, ty, expr, None);
+                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 }
             }
             if let Some(pat) = finder.pat {
@@ -1085,6 +1085,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         ty: Ty<'tcx>,
         mut expr: &'cx hir::Expr<'cx>,
         mut other_expr: Option<&'cx hir::Expr<'cx>>,
+        use_spans: Option<UseSpans<'tcx>>,
     ) {
         if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
             // We have `S { foo: val, ..base }`. In `check_aggregate_rvalue` we have a single
@@ -1197,14 +1198,50 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     .all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
             })
         {
+            let ty_span = self.infcx.tcx.def_span(def.did());
+            let mut span: MultiSpan = ty_span.into();
+            span.push_span_label(ty_span, "consider implementing `Clone` for this type");
+            span.push_span_label(expr.span, "you could clone this value");
             err.span_note(
-                self.infcx.tcx.def_span(def.did()),
+                span,
+                format!("if `{ty}` implemented `Clone`, you could clone the value"),
+            );
+        } else if let ty::Param(param) = ty.kind()
+            && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
+            && let generics = self.infcx.tcx.generics_of(self.mir_def_id())
+            && let generic_param = generics.type_param(*param, self.infcx.tcx)
+            && let param_span = self.infcx.tcx.def_span(generic_param.def_id)
+            && if let Some(UseSpans::FnSelfUse { kind, .. }) = use_spans
+                && let CallKind::FnCall { fn_trait_id, self_ty } = kind
+                && let ty::Param(_) = self_ty.kind()
+                && ty == self_ty
+                && [
+                    self.infcx.tcx.lang_items().fn_once_trait(),
+                    self.infcx.tcx.lang_items().fn_mut_trait(),
+                    self.infcx.tcx.lang_items().fn_trait(),
+                ]
+                .contains(&Some(fn_trait_id))
+            {
+                // Do not suggest `F: FnOnce() + Clone`.
+                false
+            } else {
+                true
+            }
+        {
+            let mut span: MultiSpan = param_span.into();
+            span.push_span_label(
+                param_span,
+                "consider constraining this type parameter with `Clone`",
+            );
+            span.push_span_label(expr.span, "you could clone this value");
+            err.span_help(
+                span,
                 format!("if `{ty}` implemented `Clone`, you could clone the value"),
             );
         }
     }
 
-    fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
+    pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
         let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
         self.infcx
             .type_implements_trait(clone_trait_def, [ty], self.param_env)
@@ -1403,7 +1440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let Some(expr) = self.find_expr(borrow_span)
             && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
         {
-            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span));
+            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
         }
         self.buffer_error(err);
     }
@@ -1964,7 +2001,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> {
         let tcx = self.infcx.tcx;
         let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
-        let mut expr_finder = FindExprBySpan::new(span);
+        let mut expr_finder = FindExprBySpan::new(span, tcx);
         expr_finder.visit_expr(tcx.hir().body(body_id).value);
         expr_finder.result
     }
@@ -1998,14 +2035,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             };
 
             let mut expr_finder =
-                FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
+                FindExprBySpan::new(self.body.local_decls[*index1].source_info.span, tcx);
             expr_finder.visit_expr(hir.body(body_id).value);
             let Some(index1) = expr_finder.result else {
                 note_default_suggestion();
                 return;
             };
 
-            expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
+            expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span, tcx);
             expr_finder.visit_expr(hir.body(body_id).value);
             let Some(index2) = expr_finder.result else {
                 note_default_suggestion();
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 418eabe3ae2..5ebdb69050b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -76,7 +76,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 && let Some(body_id) = node.body_id()
             {
                 let body = tcx.hir().body(body_id);
-                let mut expr_finder = FindExprBySpan::new(span);
+                let mut expr_finder = FindExprBySpan::new(span, tcx);
                 expr_finder.visit_expr(body.value);
                 if let Some(mut expr) = expr_finder.result {
                     while let hir::ExprKind::AddrOf(_, _, inner)
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index bc02c5be93d..288b846daf5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -2,10 +2,13 @@
 #![allow(rustc::untranslatable_diagnostic)]
 
 use rustc_errors::{Applicability, Diag};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{CaptureBy, ExprKind, HirId, Node};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
 use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
+use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
 
 use crate::diagnostics::CapturedMessageOpt;
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
@@ -303,6 +306,121 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         self.cannot_move_out_of(span, &description)
     }
 
+    fn suggest_clone_of_captured_var_in_move_closure(
+        &self,
+        err: &mut Diag<'_>,
+        upvar_hir_id: HirId,
+        upvar_name: &str,
+        use_spans: Option<UseSpans<'tcx>>,
+    ) {
+        let tcx = self.infcx.tcx;
+        let typeck_results = tcx.typeck(self.mir_def_id());
+        let Some(use_spans) = use_spans else { return };
+        // We only care about the case where a closure captured a binding.
+        let UseSpans::ClosureUse { args_span, .. } = use_spans else { return };
+        let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
+        // Fetch the type of the expression corresponding to the closure-captured binding.
+        let Some(captured_ty) = typeck_results.node_type_opt(upvar_hir_id) else { return };
+        if !self.implements_clone(captured_ty) {
+            // We only suggest cloning the captured binding if the type can actually be cloned.
+            return;
+        };
+        // Find the closure that captured the binding.
+        let mut expr_finder = FindExprBySpan::new(args_span, tcx);
+        expr_finder.include_closures = true;
+        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        let Some(closure_expr) = expr_finder.result else { return };
+        let ExprKind::Closure(closure) = closure_expr.kind else { return };
+        // We'll only suggest cloning the binding if it's a `move` closure.
+        let CaptureBy::Value { .. } = closure.capture_clause else { return };
+        // Find the expression within the closure where the binding is consumed.
+        let mut suggested = false;
+        let use_span = use_spans.var_or_use();
+        let mut expr_finder = FindExprBySpan::new(use_span, tcx);
+        expr_finder.include_closures = true;
+        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        let Some(use_expr) = expr_finder.result else { return };
+        let parent = tcx.parent_hir_node(use_expr.hir_id);
+        if let Node::Expr(expr) = parent
+            && let ExprKind::Assign(lhs, ..) = expr.kind
+            && lhs.hir_id == use_expr.hir_id
+        {
+            // Cloning the value being assigned makes no sense:
+            //
+            // error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+            //   --> $DIR/option-content-move2.rs:11:9
+            //    |
+            // LL |     let mut var = None;
+            //    |         ------- captured outer variable
+            // LL |     func(|| {
+            //    |          -- captured by this `FnMut` closure
+            // LL |         // Shouldn't suggest `move ||.as_ref()` here
+            // LL |         move || {
+            //    |         ^^^^^^^ `var` is moved here
+            // LL |
+            // LL |             var = Some(NotCopyable);
+            //    |             ---
+            //    |             |
+            //    |             variable moved due to use in closure
+            //    |             move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
+            //    |
+            return;
+        }
+
+        // Search for an appropriate place for the structured `.clone()` suggestion to be applied.
+        // If we encounter a statement before the borrow error, we insert a statement there.
+        for (_, node) in tcx.hir().parent_iter(closure_expr.hir_id) {
+            if let Node::Stmt(stmt) = node {
+                let padding = tcx
+                    .sess
+                    .source_map()
+                    .indentation_before(stmt.span)
+                    .unwrap_or_else(|| "    ".to_string());
+                err.multipart_suggestion_verbose(
+                    "clone the value before moving it into the closure",
+                    vec![
+                        (
+                            stmt.span.shrink_to_lo(),
+                            format!("let value = {upvar_name}.clone();\n{padding}"),
+                        ),
+                        (use_span, "value".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+                suggested = true;
+                break;
+            } else if let Node::Expr(expr) = node
+                && let ExprKind::Closure(_) = expr.kind
+            {
+                // We want to suggest cloning only on the first closure, not
+                // subsequent ones (like `ui/suggestions/option-content-move2.rs`).
+                break;
+            }
+        }
+        if !suggested {
+            // If we couldn't find a statement for us to insert a new `.clone()` statement before,
+            // we have a bare expression, so we suggest the creation of a new block inline to go
+            // from `move || val` to `{ let value = val.clone(); move || value }`.
+            let padding = tcx
+                .sess
+                .source_map()
+                .indentation_before(closure_expr.span)
+                .unwrap_or_else(|| "    ".to_string());
+            err.multipart_suggestion_verbose(
+                "clone the value before moving it into the closure",
+                vec![
+                    (
+                        closure_expr.span.shrink_to_lo(),
+                        format!("{{\n{padding}let value = {upvar_name}.clone();\n{padding}"),
+                    ),
+                    (use_spans.var_or_use(), "value".to_string()),
+                    (closure_expr.span.shrink_to_hi(), format!("\n{padding}}}")),
+                ],
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     fn report_cannot_move_from_borrowed_content(
         &mut self,
         move_place: Place<'tcx>,
@@ -310,10 +428,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         span: Span,
         use_spans: Option<UseSpans<'tcx>>,
     ) -> Diag<'tcx> {
+        let tcx = self.infcx.tcx;
         // Inspect the type of the content behind the
         // borrow to provide feedback about why this
         // was a move rather than a copy.
-        let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty;
+        let ty = deref_target_place.ty(self.body, tcx).ty;
         let upvar_field = self
             .prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
@@ -363,8 +482,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
                 let upvar = &self.upvars[upvar_field.unwrap().index()];
                 let upvar_hir_id = upvar.get_root_variable();
-                let upvar_name = upvar.to_string(self.infcx.tcx);
-                let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
+                let upvar_name = upvar.to_string(tcx);
+                let upvar_span = tcx.hir().span(upvar_hir_id);
 
                 let place_name = self.describe_any_place(move_place.as_ref());
 
@@ -380,12 +499,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     closure_kind_ty, closure_kind, place_description,
                 );
 
-                self.cannot_move_out_of(span, &place_description)
+                let closure_span = tcx.def_span(def_id);
+                let mut err = self
+                    .cannot_move_out_of(span, &place_description)
                     .with_span_label(upvar_span, "captured outer variable")
                     .with_span_label(
-                        self.infcx.tcx.def_span(def_id),
+                        closure_span,
                         format!("captured by this `{closure_kind}` closure"),
-                    )
+                    );
+                self.suggest_clone_of_captured_var_in_move_closure(
+                    &mut err,
+                    upvar_hir_id,
+                    &upvar_name,
+                    use_spans,
+                );
+                err
             }
             _ => {
                 let source = self.borrowed_content_source(deref_base);
@@ -415,7 +543,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ),
                     (_, _, _) => self.cannot_move_out_of(
                         span,
-                        &source.describe_for_unnamed_place(self.infcx.tcx),
+                        &source.describe_for_unnamed_place(tcx),
                     ),
                 }
             }
@@ -447,7 +575,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     };
 
                     if let Some(expr) = self.find_expr(span) {
-                        self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span));
+                        self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None);
                     }
 
                     err.subdiagnostic(
@@ -482,7 +610,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 };
 
                 if let Some(expr) = self.find_expr(use_span) {
-                    self.suggest_cloning(err, place_ty, expr, self.find_expr(span));
+                    self.suggest_cloning(
+                        err,
+                        place_ty,
+                        expr,
+                        self.find_expr(span),
+                        Some(use_spans),
+                    );
                 }
 
                 err.subdiagnostic(
@@ -595,7 +729,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
 
                 if let Some(expr) = self.find_expr(binding_span) {
-                    self.suggest_cloning(err, bind_to.ty, expr, None);
+                    self.suggest_cloning(err, bind_to.ty, expr, None, None);
                 }
 
                 err.subdiagnostic(
diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
index c965b34e13b..407da94c0f0 100644
--- a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
+++ b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
@@ -8,7 +8,8 @@ fn main() {
 }
 
 fn run_coroutine<T>() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine]
+    || {
         yield;
         return;
     };
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 0205de55622..90d4ab721da 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -1,6 +1,7 @@
 #![feature(
     core_intrinsics,
     coroutines,
+    stmt_expr_attributes,
     coroutine_trait,
     is_sorted,
     repr_simd,
@@ -123,9 +124,12 @@ fn main() {
         test_simd();
     }
 
-    Box::pin(move |mut _task_context| {
-        yield ();
-    })
+    Box::pin(
+        #[coroutine]
+        move |mut _task_context| {
+            yield ();
+        },
+    )
     .as_mut()
     .resume(0);
 
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index ad69409eb65..8ab8fcc525e 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -1,5 +1,5 @@
 #![allow(internal_features)]
-#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
+#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
 
 #[cfg(feature="master")]
 #[cfg(target_arch="x86_64")]
@@ -103,7 +103,7 @@ fn main() {
         test_simd();
     }
 
-    Box::pin(move |mut _task_context| {
+    Box::pin(#[coroutine] move |mut _task_context| {
         yield ();
     }).as_mut().resume(0);
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index d353704fb75..23a5e5ff873 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -898,26 +898,20 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.gcc_checked_binop(oop, typ, lhs, rhs)
     }
 
-    fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
-        // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
-        // Ideally, we shouldn't need to do this check.
-        let aligned_type = if ty == self.cx.u128_type || ty == self.cx.i128_type {
-            ty
-        } else {
-            ty.get_aligned(align.bytes())
-        };
+    fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> {
+        let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes());
         // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.
         self.stack_var_count.set(self.stack_var_count.get() + 1);
         self.current_func()
             .new_local(
                 self.location,
-                aligned_type,
+                ty,
                 &format!("stack_var_{}", self.stack_var_count.get()),
             )
             .get_address(self.location)
     }
 
-    fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
+    fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index bee6bda007c..b7aec97ad8c 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -531,7 +531,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 // We instead thus allocate some scratch space...
                 let scratch_size = cast.size(bx);
                 let scratch_align = cast.align(bx);
-                let llscratch = bx.alloca(cast.gcc_type(bx), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
 
                 // ... where we first store the value...
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 6039a4aaf01..0c7cffbe730 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -18,7 +18,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::abi::Align;
+use rustc_target::abi::{Align, Size};
 
 use crate::builder::Builder;
 #[cfg(not(feature = "master"))]
@@ -558,7 +558,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 let ze = bx.zext(result, bx.type_ix(expected_bytes * 8));
 
                 // Convert the integer to a byte array
-                let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
+                let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
                 bx.store(ze, ptr, Align::ONE);
                 let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
                 let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index c0b43b77897..aec11e9905f 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -227,7 +227,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 //   when passed by value, making it larger.
                 let copy_bytes = cmp::min(scratch_size.bytes(), self.layout.size.bytes());
                 // Allocate some scratch space...
-                let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
                 // ...store the value...
                 bx.store(val, llscratch, scratch_align);
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 4c2bdb2f5ec..f7546039540 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -468,9 +468,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         val
     }
 
-    fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
+    fn alloca(&mut self, size: Size, align: Align) -> &'ll Value {
         let mut bx = Builder::with_cx(self.cx);
         bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
+        let ty = self.cx().type_array(self.cx().type_i8(), size.bytes());
         unsafe {
             let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
@@ -478,10 +479,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn byte_array_alloca(&mut self, len: &'ll Value, align: Align) -> &'ll Value {
+    fn dynamic_alloca(&mut self, size: &'ll Value, align: Align) -> &'ll Value {
         unsafe {
             let alloca =
-                llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, UNNAMED);
+                llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
             alloca
         }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index ab9f20fdf63..41347333ea6 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
+use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 
 use std::cmp::Ordering;
@@ -649,8 +649,9 @@ fn codegen_msvc_try<'ll>(
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
+        let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(bx.type_ptr(), ptr_align);
+        let slot = bx.alloca(ptr_size, ptr_align);
         let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
         bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
 
@@ -920,15 +921,14 @@ fn codegen_emcc_try<'ll>(
 
         // We need to pass two values to catch_func (ptr and is_rust_panic), so
         // create an alloca and pass a pointer to that.
+        let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let i8_align = bx.tcx().data_layout.i8_align.abi;
-        let catch_data_type = bx.type_struct(&[bx.type_ptr(), bx.type_bool()], false);
-        let catch_data = bx.alloca(catch_data_type, ptr_align);
-        let catch_data_0 =
-            bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
-        bx.store(ptr, catch_data_0, ptr_align);
-        let catch_data_1 =
-            bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
+        // Required in order for there to be no padding between the fields.
+        assert!(i8_align <= ptr_align);
+        let catch_data = bx.alloca(2 * ptr_size, ptr_align);
+        bx.store(ptr, catch_data, ptr_align);
+        let catch_data_1 = bx.inbounds_ptradd(catch_data, bx.const_usize(ptr_size.bytes()));
         bx.store(is_rust_panic, catch_data_1, i8_align);
 
         let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
@@ -1374,7 +1374,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
 
                 // Convert the integer to a byte array
-                let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
+                let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
                 bx.store(ze, ptr, Align::ONE);
                 let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
                 return Ok(bx.load(array_ty, ptr, Align::ONE));
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 930b9b8c0db..ae7c0f24b40 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -508,7 +508,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let arg_argc = bx.const_int(cx.type_isize(), 2);
-        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align);
+        let arg_argv = bx.alloca(2 * ptr_size, ptr_align);
         bx.store(param_handle, arg_argv, ptr_align);
         let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes()));
         bx.store(param_system_table, arg_argv_el1, ptr_align);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 64c13fa7c1f..d4d172c000f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1517,7 +1517,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 //   when passed by value, making it larger.
                 let copy_bytes = cmp::min(scratch_size.bytes(), arg.layout.size.bytes());
                 // Allocate some scratch space...
-                let llscratch = bx.alloca(bx.cast_backend_type(cast), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
                 // ...memcpy the value...
                 bx.memcpy(
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9cf64e2d676..e5fd59657a4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -327,7 +327,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 let llfield_ty = bx.cx().backend_type(field);
 
                 // Can't bitcast an aggregate, so round trip through memory.
-                let llptr = bx.alloca(llfield_ty, field.align.abi);
+                let llptr = bx.alloca(field.size, field.align.abi);
                 bx.store(*llval, llptr, field.align.abi);
                 *llval = bx.load(llfield_ty, llptr, field.align.abi);
             }
@@ -470,7 +470,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
         let align_minus_1 = bx.sub(align, one);
         let size_extra = bx.add(size, align_minus_1);
         let min_align = Align::ONE;
-        let alloca = bx.byte_array_alloca(size_extra, min_align);
+        let alloca = bx.dynamic_alloca(size_extra, min_align);
         let address = bx.ptrtoint(alloca, bx.type_isize());
         let neg_address = bx.neg(address);
         let offset = bx.and(neg_address, align_minus_1);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 90627da579e..b23d0894da6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -81,7 +81,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         align: Align,
     ) -> Self {
         assert!(layout.is_sized(), "tried to statically allocate unsized place");
-        let tmp = bx.alloca(bx.cx().backend_type(layout), align);
+        let tmp = bx.alloca(layout.size, align);
         Self::new_sized_aligned(tmp, layout, align)
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 9191618c064..51b22bfaf25 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -144,8 +144,8 @@ pub trait BuilderMethods<'a, 'tcx>:
     }
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
 
-    fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
-    fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value;
+    fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
+    fn dynamic_alloca(&mut self, size: Self::Value, align: Align) -> Self::Value;
 
     fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
     fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
diff --git a/compiler/rustc_error_codes/src/error_codes/E0626.md b/compiler/rustc_error_codes/src/error_codes/E0626.md
index e2534415d83..28d543350ff 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0626.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0626.md
@@ -4,10 +4,10 @@ yield point.
 Erroneous code example:
 
 ```compile_fail,E0626
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
     let a = &String::new(); // <-- This borrow...
     yield (); // ...is still in scope here, when the yield occurs.
     println!("{}", a);
@@ -23,10 +23,10 @@ resolve the previous example by removing the borrow and just storing
 the integer by value:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
     let a = 3;
     yield ();
     println!("{}", a);
@@ -41,10 +41,10 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
 This error also frequently arises with iteration:
 
 ```compile_fail,E0626
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   for &x in &v { // <-- borrow of `v` is still in scope...
     yield x; // ...when this yield occurs.
@@ -57,10 +57,10 @@ Such cases can sometimes be resolved by iterating "by value" (or using
 `into_iter()`) to avoid borrowing:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   for x in v { // <-- Take ownership of the values instead!
     yield x; // <-- Now yield is OK.
@@ -72,10 +72,10 @@ Pin::new(&mut b).resume(());
 If taking ownership is not an option, using indices can work too:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   let len = v.len(); // (*)
   for i in 0..len {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0627.md b/compiler/rustc_error_codes/src/error_codes/E0627.md
index 5d366f78fc5..da2e2d355a1 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0627.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0627.md
@@ -3,7 +3,7 @@ A yield expression was used outside of the coroutine literal.
 Erroneous code example:
 
 ```compile_fail,E0627
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn fake_coroutine() -> &'static str {
     yield 1;
@@ -19,10 +19,10 @@ The error occurs because keyword `yield` can only be used inside the coroutine
 literal. This can be fixed by constructing the coroutine correctly.
 
 ```
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
diff --git a/compiler/rustc_error_codes/src/error_codes/E0628.md b/compiler/rustc_error_codes/src/error_codes/E0628.md
index ce19bcd56cc..d0d387cf6c7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0628.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0628.md
@@ -3,10 +3,10 @@ More than one parameter was used for a coroutine.
 Erroneous code example:
 
 ```compile_fail,E0628
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = |a: i32, b: i32| {
+    let coroutine = #[coroutine] |a: i32, b: i32| {
         // error: too many parameters for a coroutine
         // Allowed only 0 or 1 parameter
         yield a;
@@ -20,10 +20,10 @@ at most 1 parameter for the coroutine. For example, we might resolve
 the previous example by passing only one parameter.
 
 ```
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = |a: i32| {
+    let coroutine = #[coroutine] |a: i32| {
         yield a;
     };
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0727.md b/compiler/rustc_error_codes/src/error_codes/E0727.md
index fde35885c92..7754186508f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0727.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0727.md
@@ -3,10 +3,10 @@ A `yield` clause was used in an `async` context.
 Erroneous code example:
 
 ```compile_fail,E0727,edition2018
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = || {
+    let coroutine = #[coroutine] || {
         async {
             yield;
         }
@@ -20,10 +20,10 @@ which is not yet supported.
 To fix this error, you have to move `yield` out of the `async` block:
 
 ```edition2018
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = || {
+    let coroutine = #[coroutine] || {
         yield;
     };
 }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 1eee11604ce..c0e664f6eed 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -211,6 +211,8 @@ declare_features! (
     (accepted, inclusive_range_syntax, "1.26.0", Some(28237)),
     /// Allows inferring outlives requirements (RFC 2093).
     (accepted, infer_outlives_requirements, "1.30.0", Some(44493)),
+    /// Allow anonymous constants from an inline `const` block
+    (accepted, inline_const, "CURRENT_RUSTC_VERSION", Some(76001)),
     /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
     (accepted, irrefutable_let_patterns, "1.33.0", Some(44495)),
     /// Allows `#[instruction_set(_)]` attribute.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 23b3f31b437..647cd8d06f2 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -534,6 +534,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::Yes, experimental!(cfi_encoding)
     ),
 
+    // `#[coroutine]` attribute to be applied to closures to make them coroutines instead
+    gated!(
+        coroutine, Normal, template!(Word), ErrorFollowing,
+        EncodeCrossCrate::No, coroutines, experimental!(coroutines)
+    ),
+
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 9641d336c3f..2647f09c8c9 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -501,8 +501,6 @@ declare_features! (
     (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995)),
-    /// Allow anonymous constants from an inline `const` block
-    (unstable, inline_const, "1.49.0", Some(76001)),
     /// Allow anonymous constants from an inline `const` block in pattern position
     (unstable, inline_const_pat, "1.58.0", Some(76001)),
     /// Allows using `pointer` and `reference` in intra-doc links
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 3359fef8c1c..d376c24cb58 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -1,5 +1,3 @@
-#![feature(absolute_path)]
-
 use std::ffi::CString;
 use std::fs;
 use std::io;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 4a0df6cf7b8..63da27246a2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1964,11 +1964,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("recursive delegation");
         }
 
-        let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
-        if sig.output().has_opaque_types() {
-            try_emit("delegation to a function with opaque type");
-        }
-
         let sig_generics = self.tcx().generics_of(sig_id);
         let parent = self.tcx().parent(self.item_def_id());
         let parent_generics = self.tcx().generics_of(parent);
@@ -1991,29 +1986,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("delegation to a trait method from a free function");
         }
 
-        if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
-            try_emit("delegation to async functions");
-        }
-
-        if self.tcx().constness(sig_id) == hir::Constness::Const {
-            try_emit("delegation to const functions");
-        }
-
-        if sig.c_variadic() {
-            try_emit("delegation to variadic functions");
-            // variadic functions are also `unsafe` and `extern "C"`.
-            // Do not emit same error multiple times.
-            return error_occured;
-        }
-
-        if let hir::Unsafety::Unsafe = sig.unsafety() {
-            try_emit("delegation to unsafe functions");
-        }
-
-        if abi::Abi::Rust != sig.abi() {
-            try_emit("delegation to non Rust ABI functions");
-        }
-
         error_occured
     }
 
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 9ebb5f95f05..4165fa7f07d 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1139,7 +1139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // are the same function and their parameters have a LUB.
                         match self.commit_if_ok(|_| {
                             self.at(cause, self.param_env).lub(
-                                DefineOpaqueTypes::No,
+                                DefineOpaqueTypes::Yes,
                                 prev_ty,
                                 new_ty,
                             )
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index c4ab4eb2657..fd42c9c1faa 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1260,30 +1260,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         id: DefIndex,
         sess: &'a Session,
     ) -> impl Iterator<Item = ModChild> + 'a {
-        iter::from_coroutine(move || {
-            if let Some(data) = &self.root.proc_macro_data {
-                // If we are loading as a proc macro, we want to return
-                // the view of this crate as a proc macro crate.
-                if id == CRATE_DEF_INDEX {
-                    for child_index in data.macros.decode(self) {
+        iter::from_coroutine(
+            #[cfg_attr(not(bootstrap), coroutine)]
+            move || {
+                if let Some(data) = &self.root.proc_macro_data {
+                    // If we are loading as a proc macro, we want to return
+                    // the view of this crate as a proc macro crate.
+                    if id == CRATE_DEF_INDEX {
+                        for child_index in data.macros.decode(self) {
+                            yield self.get_mod_child(child_index, sess);
+                        }
+                    }
+                } else {
+                    // Iterate over all children.
+                    let non_reexports =
+                        self.root.tables.module_children_non_reexports.get(self, id);
+                    for child_index in non_reexports.unwrap().decode(self) {
                         yield self.get_mod_child(child_index, sess);
                     }
-                }
-            } else {
-                // Iterate over all children.
-                let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
-                for child_index in non_reexports.unwrap().decode(self) {
-                    yield self.get_mod_child(child_index, sess);
-                }
 
-                let reexports = self.root.tables.module_children_reexports.get(self, id);
-                if !reexports.is_default() {
-                    for reexport in reexports.decode((self, sess)) {
-                        yield reexport;
+                    let reexports = self.root.tables.module_children_reexports.get(self, id);
+                    if !reexports.is_default() {
+                        for reexport in reexports.decode((self, sess)) {
+                            yield reexport;
+                        }
                     }
                 }
-            }
-        })
+            },
+        )
     }
 
     fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index aadaca18326..501052b7411 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -35,8 +35,9 @@
 #![feature(const_type_name)]
 #![feature(discriminant_kind)]
 #![feature(coroutines)]
+#![feature(stmt_expr_attributes)]
 #![feature(if_let_guard)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(iter_from_coroutine)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 11167515b7c..b66c664e6ae 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -422,49 +422,53 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>(
     child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
     mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T,
 ) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> {
-    std::iter::from_coroutine(move || {
-        let mut child_captures = child_captures.into_iter().enumerate().peekable();
-
-        // One parent capture may correspond to several child captures if we end up
-        // refining the set of captures via edition-2021 precise captures. We want to
-        // match up any number of child captures with one parent capture, so we keep
-        // peeking off this `Peekable` until the child doesn't match anymore.
-        for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
-            // Make sure we use every field at least once, b/c why are we capturing something
-            // if it's not used in the inner coroutine.
-            let mut field_used_at_least_once = false;
-
-            // A parent matches a child if they share the same prefix of projections.
-            // The child may have more, if it is capturing sub-fields out of
-            // something that is captured by-move in the parent closure.
-            while child_captures.peek().map_or(false, |(_, child_capture)| {
-                child_prefix_matches_parent_projections(parent_capture, child_capture)
-            }) {
-                let (child_field_idx, child_capture) = child_captures.next().unwrap();
-                // This analysis only makes sense if the parent capture is a
-                // prefix of the child capture.
-                assert!(
-                    child_capture.place.projections.len() >= parent_capture.place.projections.len(),
-                    "parent capture ({parent_capture:#?}) expected to be prefix of \
+    std::iter::from_coroutine(
+        #[cfg_attr(not(bootstrap), coroutine)]
+        move || {
+            let mut child_captures = child_captures.into_iter().enumerate().peekable();
+
+            // One parent capture may correspond to several child captures if we end up
+            // refining the set of captures via edition-2021 precise captures. We want to
+            // match up any number of child captures with one parent capture, so we keep
+            // peeking off this `Peekable` until the child doesn't match anymore.
+            for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
+                // Make sure we use every field at least once, b/c why are we capturing something
+                // if it's not used in the inner coroutine.
+                let mut field_used_at_least_once = false;
+
+                // A parent matches a child if they share the same prefix of projections.
+                // The child may have more, if it is capturing sub-fields out of
+                // something that is captured by-move in the parent closure.
+                while child_captures.peek().map_or(false, |(_, child_capture)| {
+                    child_prefix_matches_parent_projections(parent_capture, child_capture)
+                }) {
+                    let (child_field_idx, child_capture) = child_captures.next().unwrap();
+                    // This analysis only makes sense if the parent capture is a
+                    // prefix of the child capture.
+                    assert!(
+                        child_capture.place.projections.len()
+                            >= parent_capture.place.projections.len(),
+                        "parent capture ({parent_capture:#?}) expected to be prefix of \
                     child capture ({child_capture:#?})"
-                );
+                    );
 
-                yield for_each(
-                    (parent_field_idx, parent_capture),
-                    (child_field_idx, child_capture),
-                );
+                    yield for_each(
+                        (parent_field_idx, parent_capture),
+                        (child_field_idx, child_capture),
+                    );
 
-                field_used_at_least_once = true;
-            }
+                    field_used_at_least_once = true;
+                }
 
-            // Make sure the field was used at least once.
-            assert!(
-                field_used_at_least_once,
-                "we captured {parent_capture:#?} but it was not used in the child coroutine?"
-            );
-        }
-        assert_eq!(child_captures.next(), None, "leftover child captures?");
-    })
+                // Make sure the field was used at least once.
+                assert!(
+                    field_used_at_least_once,
+                    "we captured {parent_capture:#?} but it was not used in the child coroutine?"
+                );
+            }
+            assert_eq!(child_captures.next(), None, "leftover child captures?");
+        },
+    )
 }
 
 fn child_prefix_matches_parent_projections(
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 7dbe59e132d..45fa5e8f7ca 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1284,20 +1284,23 @@ impl<'tcx> TyCtxt<'tcx> {
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
         let definitions = &self.untracked.definitions;
-        std::iter::from_coroutine(|| {
-            let mut i = 0;
-
-            // Recompute the number of definitions each time, because our caller may be creating
-            // new ones.
-            while i < { definitions.read().num_definitions() } {
-                let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
-                yield LocalDefId { local_def_index };
-                i += 1;
-            }
+        std::iter::from_coroutine(
+            #[cfg_attr(not(bootstrap), coroutine)]
+            || {
+                let mut i = 0;
+
+                // Recompute the number of definitions each time, because our caller may be creating
+                // new ones.
+                while i < { definitions.read().num_definitions() } {
+                    let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
+                    yield LocalDefId { local_def_index };
+                    i += 1;
+                }
 
-            // Freeze definitions once we finish iterating on them, to prevent adding new ones.
-            definitions.freeze();
-        })
+                // Freeze definitions once we finish iterating on them, to prevent adding new ones.
+                definitions.freeze();
+            },
+        )
     }
 
     pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index cc026e349d7..cda332aee56 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -45,7 +45,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_index::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
@@ -224,8 +224,15 @@ pub struct ResolverAstLowering {
     pub lint_buffer: Steal<LintBuffer>,
 
     /// Information about functions signatures for delegation items expansion
-    pub has_self: LocalDefIdSet,
-    pub fn_parameter_counts: LocalDefIdMap<usize>,
+    pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
+}
+
+#[derive(Debug)]
+pub struct DelegationFnSig {
+    pub header: ast::FnHeader,
+    pub param_count: usize,
+    pub has_self: bool,
+    pub c_variadic: bool,
 }
 
 #[derive(Clone, Copy, Debug)]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index b308a80f7ba..e42755ca7bf 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -4,7 +4,7 @@
 #![feature(cow_is_borrowed)]
 #![feature(decl_macro)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(map_try_insert)]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 84ecd0a0de5..ed51710564a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -686,6 +686,8 @@ impl<'a> Parser<'a> {
             (None, self.parse_path(PathStyle::Expr)?)
         };
 
+        let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
+
         let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
             Some(self.parse_block()?)
         } else {
@@ -695,11 +697,9 @@ impl<'a> Parser<'a> {
         let span = span.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::fn_delegation, span);
 
-        let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
-        Ok((
-            ident,
-            ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })),
-        ))
+        let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
+        let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
+        Ok((ident, ItemKind::Delegation(Box::new(deleg))))
     }
 
     fn parse_item_list<T>(
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 742f4bd3c83..7486da33b21 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1252,8 +1252,6 @@ impl<'a> Parser<'a> {
     fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
         if pat {
             self.psess.gated_spans.gate(sym::inline_const_pat, span);
-        } else {
-            self.psess.gated_spans.gate(sym::inline_const, span);
         }
         self.eat_keyword(kw::Const);
         let (attrs, blk) = self.parse_inner_attrs_and_block()?;
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c877ae5e21f..292af43b602 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
+use rustc_middle::ty::DelegationFnSig;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
 use rustc_session::lint;
@@ -4749,12 +4750,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> {
 
 impl ItemInfoCollector<'_, '_, '_> {
     fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
-        let def_id = self.r.local_def_id(id);
-        self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
-
-        if sig.decl.has_self() {
-            self.r.has_self.insert(def_id);
-        }
+        let sig = DelegationFnSig {
+            header: sig.header,
+            param_count: sig.decl.inputs.len(),
+            has_self: sig.decl.has_self(),
+            c_variadic: sig.decl.c_variadic(),
+        };
+        self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d79c638fa07..64451030adf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2039,7 +2039,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
                         ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
                         ast::AssocItemKind::Delegation(..)
-                            if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
+                            if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
+                                .has_self =>
                         {
                             AssocSuggestion::MethodWithSelf { called }
                         }
@@ -2062,7 +2063,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 if filter_fn(res) {
                     let def_id = res.def_id();
                     let has_self = match def_id.as_local() {
-                        Some(def_id) => self.r.has_self.contains(&def_id),
+                        Some(def_id) => {
+                            self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
+                        }
                         None => self
                             .r
                             .tcx
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b5b6d899cc5..e07c3247d07 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::NonMacroAttrKind;
 use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_index::IndexVec;
@@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed};
-use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs};
+use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools};
+use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
@@ -992,7 +992,6 @@ pub struct Resolver<'a, 'tcx> {
     extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
 
     /// N.B., this is used only for better diagnostics, not name resolution itself.
-    has_self: LocalDefIdSet,
     field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
 
     /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
@@ -1149,8 +1148,7 @@ pub struct Resolver<'a, 'tcx> {
     legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
     /// Amount of lifetime parameters for each item in the crate.
     item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
-    /// Amount of parameters for each function in the crate.
-    fn_parameter_counts: LocalDefIdMap<usize>,
+    delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
 
     main_def: Option<MainDefinition>,
     trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -1399,7 +1397,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             prelude: None,
             extern_prelude,
 
-            has_self: Default::default(),
             field_def_ids: Default::default(),
             field_visibility_spans: FxHashMap::default(),
 
@@ -1508,7 +1505,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             doc_link_resolutions: Default::default(),
             doc_link_traits_in_scope: Default::default(),
             all_macro_rules: Default::default(),
-            fn_parameter_counts: Default::default(),
+            delegation_fn_sigs: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1621,8 +1618,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
-            has_self: self.has_self,
-            fn_parameter_counts: self.fn_parameter_counts,
+            delegation_fn_sigs: self.delegation_fn_sigs,
         };
         ResolverOutputs { global_ctxt, ast_lowering }
     }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 3e1d8f3828b..19f4e6994ac 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -11,7 +11,7 @@
 #![cfg_attr(bootstrap, feature(associated_type_bounds))]
 #![feature(const_option)]
 #![feature(core_intrinsics)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(ptr_sub_ptr)]
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 07c11663173..4f259960ac3 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1888,9 +1888,12 @@ fn collect_print_requests(
                 let prints =
                     PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
                 let prints = prints.join(", ");
-                early_dcx.early_fatal(format!(
-                    "unknown print request `{req}`. Valid print requests are: {prints}"
-                ));
+
+                let mut diag =
+                    early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
+                #[allow(rustc::diagnostic_outside_of_impl)]
+                diag.help(format!("valid print requests are: {prints}"));
+                diag.emit()
             }
         };
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8abf42e2c13..99591b5e144 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -192,6 +192,7 @@ symbols! {
         Duration,
         Encodable,
         Encoder,
+        Enumerate,
         Eq,
         Equal,
         Err,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 837b784f272..e50edfdc656 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -50,22 +50,38 @@ pub struct FindExprBySpan<'hir> {
     pub span: Span,
     pub result: Option<&'hir hir::Expr<'hir>>,
     pub ty_result: Option<&'hir hir::Ty<'hir>>,
+    pub include_closures: bool,
+    pub tcx: TyCtxt<'hir>,
 }
 
 impl<'hir> FindExprBySpan<'hir> {
-    pub fn new(span: Span) -> Self {
-        Self { span, result: None, ty_result: None }
+    pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self {
+        Self { span, result: None, ty_result: None, tcx, include_closures: false }
     }
 }
 
 impl<'v> Visitor<'v> for FindExprBySpan<'v> {
+    type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+
     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
         if self.span == ex.span {
             self.result = Some(ex);
         } else {
+            if let hir::ExprKind::Closure(..) = ex.kind
+                && self.include_closures
+                && let closure_header_sp = self.span.with_hi(ex.span.hi())
+                && closure_header_sp == ex.span
+            {
+                self.result = Some(ex);
+            }
             hir::intravisit::walk_expr(self, ex);
         }
     }
+
     fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         if self.span == ty.span {
             self.ty_result = Some(ty);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 9d3caaa01ab..cc879c42ce9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -901,7 +901,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // Remove all the desugaring and macro contexts.
             span.remove_mark();
         }
-        let mut expr_finder = FindExprBySpan::new(span);
+        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
         let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
             return;
         };
@@ -1367,7 +1367,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             return false;
                         };
                         let body = self.tcx.hir().body(body_id);
-                        let mut expr_finder = FindExprBySpan::new(span);
+                        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
                         expr_finder.visit_expr(body.value);
                         let Some(expr) = expr_finder.result else {
                             return false;
@@ -1469,7 +1469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // Remove all the hir desugaring contexts while maintaining the macro contexts.
             span.remove_mark();
         }
-        let mut expr_finder = super::FindExprBySpan::new(span);
+        let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
         let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
             return false;
         };
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 0e309689680..1971136e54c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -2457,7 +2457,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     && let Some(body_id) =
                         self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
                 {
-                    let mut expr_finder = FindExprBySpan::new(span);
+                    let mut expr_finder = FindExprBySpan::new(span, self.tcx);
                     expr_finder.visit_expr(self.tcx.hir().body(body_id).value);
 
                     if let Some(hir::Expr {
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 3be0be83e09..3924b371bbc 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -183,7 +183,7 @@ pub enum TyKind<I: Interner> {
     ///
     /// ```
     /// #![feature(coroutines)]
-    /// static |a| {
+    /// #[coroutine] static |a| {
     ///     let x = &vec![3];
     ///     yield a;
     ///     yield x[0];