about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-28 07:25:28 +0000
committerbors <bors@rust-lang.org>2024-06-28 07:25:28 +0000
commit99f77a2eda555b50b518f74823ab636a20efb87f (patch)
tree8dd11cc66cae04d768306ccb8e6c7e625e25104d
parent42add88d2275b95c98e512ab680436ede691e853 (diff)
parent89a0cfe72afe047c699df3810e1ce5e4d9cb98b4 (diff)
downloadrust-99f77a2eda555b50b518f74823ab636a20efb87f.tar.gz
rust-99f77a2eda555b50b518f74823ab636a20efb87f.zip
Auto merge of #127076 - matthiaskrgr:rollup-l01gm36, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #124741 (patchable-function-entry: Add unstable compiler flag and attribute)
 - #126470 (make cargo submodule optional)
 - #126956 (core: avoid `extern type`s in formatting infrastructure)
 - #126970 (Simplify `str::clone_into`)
 - #127022 (Support fetching `Attribute` of items.)
 - #127058 (Tighten `fn_decl_span` for async blocks)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_ast/src/ast.rs5
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs16
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs31
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs80
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs7
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs9
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs27
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs5
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs2
-rw-r--r--compiler/rustc_session/src/config.rs35
-rw-r--r--compiler/rustc_session/src/options.rs29
-rw-r--r--compiler/rustc_smir/Cargo.toml2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs40
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs10
-rw-r--r--compiler/stable_mir/src/crate_def.rs37
-rw-r--r--library/alloc/src/str.rs7
-rw-r--r--library/core/src/fmt/mod.rs6
-rw-r--r--library/core/src/fmt/rt.rs46
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs42
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs3
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/vendor.rs5
-rw-r--r--src/bootstrap/src/core/metadata.rs16
-rw-r--r--src/bootstrap/src/lib.rs3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md24
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/rustfmt/src/expr.rs2
-rw-r--r--tests/codegen/patchable-function-entry/patchable-function-entry-both-flags.rs64
-rw-r--r--tests/codegen/patchable-function-entry/patchable-function-entry-no-flag.rs39
-rw-r--r--tests/codegen/patchable-function-entry/patchable-function-entry-one-flag.rs66
-rw-r--r--tests/coverage/issue-83601.cov-map6
-rw-r--r--tests/coverage/issue-84561.cov-map14
-rw-r--r--tests/ui-fulldeps/stable-mir/check_attribute.rs155
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr26
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-block-error.stderr10
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.stderr24
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.stderr25
-rw-r--r--tests/ui/async-await/coroutine-desc.stderr4
-rw-r--r--tests/ui/async-await/coroutine-not-future.stderr4
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.stderr2
-rw-r--r--tests/ui/async-await/issue-68112.stderr15
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.stderr20
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr14
-rw-r--r--tests/ui/async-await/issue-86507.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-78938-async-block.stderr10
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.afn.stderr4
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr4
-rw-r--r--tests/ui/async-await/try-on-option-in-async.stderr12
-rw-r--r--tests/ui/borrowck/cloning-in-async-block-121547.stderr18
-rw-r--r--tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr50
-rw-r--r--tests/ui/coroutine/clone-impl-async.stderr24
-rw-r--r--tests/ui/coroutine/gen_block_is_coro.stderr12
-rw-r--r--tests/ui/coroutine/gen_block_is_no_future.stderr6
-rw-r--r--tests/ui/coroutine/gen_block_move.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-patchable-function-entry.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr13
-rw-r--r--tests/ui/fmt/send-sync.stderr30
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait.stderr2
-rw-r--r--tests/ui/impl-trait/issue-55872-3.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.stderr2
-rw-r--r--tests/ui/impl-trait/nested-return-type4.stderr2
-rw-r--r--tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr4
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs17
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr32
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-flags.rs2
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr2
-rw-r--r--tests/ui/pattern/non-structural-match-types.stderr2
-rw-r--r--tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr2
-rw-r--r--tests/ui/traits/next-solver/async.fail.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr4
80 files changed, 980 insertions, 308 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e977964b72c..0182eca0505 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4675,6 +4675,8 @@ name = "rustc_smir"
 version = "0.0.0"
 dependencies = [
  "rustc_abi",
+ "rustc_ast",
+ "rustc_ast_pretty",
  "rustc_data_structures",
  "rustc_hir",
  "rustc_middle",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4a3ce0e0c30..f5e79c04d78 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1454,7 +1454,10 @@ pub enum ExprKind {
     Block(P<Block>, Option<Label>),
     /// An `async` block (`async move { ... }`),
     /// or a `gen` block (`gen move { ... }`)
-    Gen(CaptureBy, P<Block>, GenBlockKind),
+    ///
+    /// The span is the "decl", which is the header before the body `{ }`
+    /// including the `asyng`/`gen` keywords and possibly `move`.
+    Gen(CaptureBy, P<Block>, GenBlockKind, Span),
     /// An await expression (`my_future.await`). Span is of await keyword.
     Await(P<Expr>, Span),
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a81c335aa23..27e781a5a63 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1528,8 +1528,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
             visit_opt(label, |label| vis.visit_label(label));
             vis.visit_block(blk);
         }
-        ExprKind::Gen(_capture_by, body, _kind) => {
+        ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
             vis.visit_block(body);
+            vis.visit_span(decl_span);
         }
         ExprKind::Await(expr, await_kw_span) => {
             vis.visit_expr(expr);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 0f3c30048ce..26cb04d4d47 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -1122,7 +1122,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
             visit_opt!(visitor, visit_label, opt_label);
             try_visit!(visitor.visit_block(block));
         }
-        ExprKind::Gen(_capt, body, _kind) => try_visit!(visitor.visit_block(body)),
+        ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
         ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
         ExprKind::Assign(lhs, rhs, _span) => {
             try_visit!(visitor.visit_expr(lhs));
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 79cff0fbcd2..624bca525b9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -227,7 +227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         *fn_arg_span,
                     ),
                 },
-                ExprKind::Gen(capture_clause, block, genblock_kind) => {
+                ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
                     let desugaring_kind = match genblock_kind {
                         GenBlockKind::Async => hir::CoroutineDesugaring::Async,
                         GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
@@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         *capture_clause,
                         e.id,
                         None,
+                        *decl_span,
                         e.span,
                         desugaring_kind,
                         hir::CoroutineSource::Block,
@@ -616,6 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         capture_clause: CaptureBy,
         closure_node_id: NodeId,
         return_ty: Option<hir::FnRetTy<'hir>>,
+        fn_decl_span: Span,
         span: Span,
         desugaring_kind: hir::CoroutineDesugaring,
         coroutine_source: hir::CoroutineSource,
@@ -692,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             bound_generic_params: &[],
             fn_decl,
             body,
-            fn_decl_span: self.lower_span(span),
+            fn_decl_span: self.lower_span(fn_decl_span),
             fn_arg_span: None,
             kind: hir::ClosureKind::Coroutine(coroutine_kind),
             constness: hir::Constness::NotConst,
@@ -1083,6 +1085,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
                     &inner_decl,
                     |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
+                    fn_decl_span,
                     body.span,
                     coroutine_kind,
                     hir::CoroutineSource::Closure,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 4c7e8c24d32..74e04eff4f3 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -211,6 +211,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     // declaration (decl), not the return types.
                     let coroutine_kind = header.coroutine_kind;
                     let body_id = this.lower_maybe_coroutine_body(
+                        *fn_sig_span,
                         span,
                         hir_id,
                         decl,
@@ -799,6 +800,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
                 let body_id = self.lower_maybe_coroutine_body(
+                    sig.span,
                     i.span,
                     hir_id,
                     &sig.decl,
@@ -915,6 +917,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ),
             AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
                 let body_id = self.lower_maybe_coroutine_body(
+                    sig.span,
                     i.span,
                     hir_id,
                     &sig.decl,
@@ -1111,6 +1114,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// `gen {}` block as appropriate.
     fn lower_maybe_coroutine_body(
         &mut self,
+        fn_decl_span: Span,
         span: Span,
         fn_id: hir::HirId,
         decl: &FnDecl,
@@ -1124,6 +1128,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
                 decl,
                 |this| this.lower_block_expr(body),
+                fn_decl_span,
                 body.span,
                 coroutine_kind,
                 hir::CoroutineSource::Fn,
@@ -1145,6 +1150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         decl: &FnDecl,
         lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
+        fn_decl_span: Span,
         body_span: Span,
         coroutine_kind: CoroutineKind,
         coroutine_source: hir::CoroutineSource,
@@ -1315,13 +1321,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let closure_id = coroutine_kind.closure_id();
 
-        let span = if let FnRetTy::Default(span) = decl.output
-            && matches!(coroutine_source, rustc_hir::CoroutineSource::Closure)
-        {
-            body_span.with_lo(span.lo())
-        } else {
-            body_span
-        };
         let coroutine_expr = self.make_desugared_coroutine_expr(
             // The default capture mode here is by-ref. Later on during upvar analysis,
             // we will force the captured arguments to by-move, but for async closures,
@@ -1330,7 +1329,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             CaptureBy::Ref,
             closure_id,
             None,
-            span,
+            fn_decl_span,
+            body_span,
             desugaring_kind,
             coroutine_source,
             mkbody,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index f2f6594e686..3d1f43a3766 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -540,7 +540,7 @@ impl<'a> State<'a> {
                 self.ibox(0);
                 self.print_block_with_attrs(blk, attrs);
             }
-            ast::ExprKind::Gen(capture_clause, blk, kind) => {
+            ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
                 self.word_nbsp(kind.modifier());
                 self.print_capture_clause(*capture_clause);
                 // cbox/ibox in analogy to the `ExprKind::Block` arm above
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index a98cb6f0f76..c664891dad5 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -298,7 +298,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
             // sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
             ExprKind::Assign(_, _, _)
             | ExprKind::AssignOp(_, _, _)
-            | ExprKind::Gen(_, _, _)
+            | ExprKind::Gen(_, _, _, _)
             | ExprKind::Await(_, _)
             | ExprKind::Block(_, _)
             | ExprKind::Break(_, _)
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 48693895da1..cd82894af18 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -2,7 +2,7 @@
 
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::DefId;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::{FunctionReturn, OptLevel};
 use rustc_span::symbol::sym;
@@ -53,6 +53,34 @@ fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll
     }
 }
 
+#[inline]
+fn patchable_function_entry_attrs<'ll>(
+    cx: &CodegenCx<'ll, '_>,
+    attr: Option<PatchableFunctionEntry>,
+) -> SmallVec<[&'ll Attribute; 2]> {
+    let mut attrs = SmallVec::new();
+    let patchable_spec = attr.unwrap_or_else(|| {
+        PatchableFunctionEntry::from_config(cx.tcx.sess.opts.unstable_opts.patchable_function_entry)
+    });
+    let entry = patchable_spec.entry();
+    let prefix = patchable_spec.prefix();
+    if entry > 0 {
+        attrs.push(llvm::CreateAttrStringValue(
+            cx.llcx,
+            "patchable-function-entry",
+            &format!("{}", entry),
+        ));
+    }
+    if prefix > 0 {
+        attrs.push(llvm::CreateAttrStringValue(
+            cx.llcx,
+            "patchable-function-prefix",
+            &format!("{}", prefix),
+        ));
+    }
+    attrs
+}
+
 /// Get LLVM sanitize attributes.
 #[inline]
 pub fn sanitize_attrs<'ll>(
@@ -421,6 +449,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
         llvm::set_alignment(llfn, align);
     }
     to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
+    to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
 
     // Always annotate functions with the target-cpu they are compiled for.
     // Without this, ThinLTO won't inline Rust functions into Clang generated
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index d224695d1f2..56a893738df 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,11 +1,13 @@
 use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::{codes::*, struct_span_code_err, DiagMessage, SubdiagMessage};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::middle::codegen_fn_attrs::{
+    CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
+};
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self as ty, TyCtxt};
@@ -447,6 +449,80 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     None
                 };
             }
+            sym::patchable_function_entry => {
+                codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| {
+                    let mut prefix = None;
+                    let mut entry = None;
+                    for item in l {
+                        let Some(meta_item) = item.meta_item() else {
+                            tcx.dcx().span_err(item.span(), "expected name value pair");
+                            continue;
+                        };
+
+                        let Some(name_value_lit) = meta_item.name_value_literal() else {
+                            tcx.dcx().span_err(item.span(), "expected name value pair");
+                            continue;
+                        };
+
+                        fn emit_error_with_label(
+                            tcx: TyCtxt<'_>,
+                            span: Span,
+                            error: impl Into<DiagMessage>,
+                            label: impl Into<SubdiagMessage>,
+                        ) {
+                            let mut err: rustc_errors::Diag<'_, _> =
+                                tcx.dcx().struct_span_err(span, error);
+                            err.span_label(span, label);
+                            err.emit();
+                        }
+
+                        let attrib_to_write = match meta_item.name_or_empty() {
+                            sym::prefix_nops => &mut prefix,
+                            sym::entry_nops => &mut entry,
+                            _ => {
+                                emit_error_with_label(
+                                    tcx,
+                                    item.span(),
+                                    "unexpected parameter name",
+                                    format!("expected {} or {}", sym::prefix_nops, sym::entry_nops),
+                                );
+                                continue;
+                            }
+                        };
+
+                        let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else {
+                            emit_error_with_label(
+                                tcx,
+                                name_value_lit.span,
+                                "invalid literal value",
+                                "value must be an integer between `0` and `255`",
+                            );
+                            continue;
+                        };
+
+                        let Ok(val) = val.get().try_into() else {
+                            emit_error_with_label(
+                                tcx,
+                                name_value_lit.span,
+                                "integer value out of range",
+                                "value must be between `0` and `255`",
+                            );
+                            continue;
+                        };
+
+                        *attrib_to_write = Some(val);
+                    }
+
+                    if let (None, None) = (prefix, entry) {
+                        tcx.dcx().span_err(attr.span, "must specify at least one parameter");
+                    }
+
+                    Some(PatchableFunctionEntry::from_prefix_and_entry(
+                        prefix.unwrap_or(0),
+                        entry.unwrap_or(0),
+                    ))
+                })
+            }
             _ => {}
         }
     }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 32a047a9363..f884f996927 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -585,6 +585,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
     ),
 
+    // RFC 3543
+    // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
+    gated!(
+        patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
+        EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
+    ),
+
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index f4e20328814..ad6f7da8937 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -563,6 +563,8 @@ declare_features! (
     (unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
+    /// Allows specifying nop padding on functions for dynamic patching.
+    (unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(123115)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
     /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 6ffc518097e..02322c9b282 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -8,8 +8,8 @@ use rustc_session::config::{
     ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
     Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
     LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
-    PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
-    SymbolManglingVersion, WasiExecModel,
+    PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
+    SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -813,6 +813,11 @@ fn test_unstable_options_tracking_hash() {
     tracked!(packed_bundled_libs, true);
     tracked!(panic_abort_tests, true);
     tracked!(panic_in_drop, PanicStrategy::Abort);
+    tracked!(
+        patchable_function_entry,
+        PatchableFunctionEntry::from_total_and_prefix_nops(10, 5)
+            .expect("total must be greater than or equal to prefix")
+    );
     tracked!(plt, Some(true));
     tracked!(polonius, Polonius::Legacy);
     tracked!(precise_enum_drop_elaboration, false);
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index c8f0d0795a3..3ddf889b63a 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -45,6 +45,32 @@ pub struct CodegenFnAttrs {
     /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
     /// aligned to.
     pub alignment: Option<Align>,
+    /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
+    /// the function entry.
+    pub patchable_function_entry: Option<PatchableFunctionEntry>,
+}
+
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct PatchableFunctionEntry {
+    /// Nops to prepend to the function
+    prefix: u8,
+    /// Nops after entry, but before body
+    entry: u8,
+}
+
+impl PatchableFunctionEntry {
+    pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self {
+        Self { prefix: config.prefix(), entry: config.entry() }
+    }
+    pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self {
+        Self { prefix, entry }
+    }
+    pub fn prefix(&self) -> u8 {
+        self.prefix
+    }
+    pub fn entry(&self) -> u8 {
+        self.entry
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
@@ -121,6 +147,7 @@ impl CodegenFnAttrs {
             no_sanitize: SanitizerSet::empty(),
             instruction_set: None,
             alignment: None,
+            patchable_function_entry: None,
         }
     }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e0c70884fee..3cdc20b6c65 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -3432,8 +3432,9 @@ impl<'a> Parser<'a> {
             }
         }
         let capture_clause = self.parse_capture_clause()?;
+        let decl_span = lo.to(self.prev_token.span);
         let (attrs, body) = self.parse_inner_attrs_and_block()?;
-        let kind = ExprKind::Gen(capture_clause, body, kind);
+        let kind = ExprKind::Gen(capture_clause, body, kind, decl_span);
         Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
     }
 
@@ -4022,7 +4023,7 @@ impl MutVisitor for CondChecker<'_> {
             | ExprKind::Match(_, _, _)
             | ExprKind::Closure(_)
             | ExprKind::Block(_, _)
-            | ExprKind::Gen(_, _, _)
+            | ExprKind::Gen(_, _, _, _)
             | ExprKind::TryBlock(_)
             | ExprKind::Underscore
             | ExprKind::Path(_, _)
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 1bca5602a4e..80619c59cc3 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -334,7 +334,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
                     None => closure_def,
                 }
             }
-            ExprKind::Gen(_, _, _) => {
+            ExprKind::Gen(_, _, _, _) => {
                 self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
             }
             ExprKind::ConstBlock(ref constant) => {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 2d38ad37133..41c99f7edee 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2965,8 +2965,9 @@ pub(crate) mod dep_tracking {
         CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
         LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
-        Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
-        SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
+        PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
+        SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
+        WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -3073,6 +3074,7 @@ pub(crate) mod dep_tracking {
         OomStrategy,
         LanguageIdentifier,
         NextSolverConfig,
+        PatchableFunctionEntry,
         Polonius,
         InliningThreshold,
         FunctionReturn,
@@ -3250,6 +3252,35 @@ impl DumpMonoStatsFormat {
     }
 }
 
+/// `-Z patchable-function-entry` representation - how many nops to put before and after function
+/// entry.
+#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
+pub struct PatchableFunctionEntry {
+    /// Nops before the entry
+    prefix: u8,
+    /// Nops after the entry
+    entry: u8,
+}
+
+impl PatchableFunctionEntry {
+    pub fn from_total_and_prefix_nops(
+        total_nops: u8,
+        prefix_nops: u8,
+    ) -> Option<PatchableFunctionEntry> {
+        if total_nops < prefix_nops {
+            None
+        } else {
+            Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops })
+        }
+    }
+    pub fn prefix(&self) -> u8 {
+        self.prefix
+    }
+    pub fn entry(&self) -> u8 {
+        self.entry
+    }
+}
+
 /// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
 /// or future prototype.
 #[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 9a10adeb6d1..80f7ca544f3 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -379,6 +379,7 @@ mod desc {
     pub const parse_passes: &str = "a space-separated list of passes, or `all`";
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
     pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
+    pub const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_oom_strategy: &str = "either `panic` or `abort`";
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@@ -734,6 +735,32 @@ mod parse {
         true
     }
 
+    pub(crate) fn parse_patchable_function_entry(
+        slot: &mut PatchableFunctionEntry,
+        v: Option<&str>,
+    ) -> bool {
+        let mut total_nops = 0;
+        let mut prefix_nops = 0;
+
+        if !parse_number(&mut total_nops, v) {
+            let parts = v.and_then(|v| v.split_once(',')).unzip();
+            if !parse_number(&mut total_nops, parts.0) {
+                return false;
+            }
+            if !parse_number(&mut prefix_nops, parts.1) {
+                return false;
+            }
+        }
+
+        if let Some(pfe) =
+            PatchableFunctionEntry::from_total_and_prefix_nops(total_nops, prefix_nops)
+        {
+            *slot = pfe;
+            return true;
+        }
+        false
+    }
+
     pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
         match v {
             Some("panic") => *slot = OomStrategy::Panic,
@@ -1859,6 +1886,8 @@ options! {
         "panic strategy for panics in drops"),
     parse_only: bool = (false, parse_bool, [UNTRACKED],
         "parse only; do not compile, assemble, or link (default: no)"),
+    patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
+        "nop padding at function entry"),
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "whether to use the PLT when calling into shared libraries;
         only has effect for PIC code on systems with ELF binaries
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 1e0a60bc371..1230667ee91 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index dde5e30c3d0..e23f4289e98 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -228,6 +228,46 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
+    fn get_attrs_by_path(
+        &self,
+        def_id: stable_mir::DefId,
+        attr: &[stable_mir::Symbol],
+    ) -> Vec<stable_mir::crate_def::Attribute> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let did = tables[def_id];
+        let attr_name: Vec<_> =
+            attr.iter().map(|seg| rustc_span::symbol::Symbol::intern(&seg)).collect();
+        tcx.get_attrs_by_path(did, &attr_name)
+            .map(|attribute| {
+                let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
+                let span = attribute.span;
+                stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
+            })
+            .collect()
+    }
+
+    fn get_all_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let did = tables[def_id];
+        let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
+            matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
+        };
+        let attrs_iter = if let Some(did) = did.as_local() {
+            tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
+        } else {
+            tcx.item_attrs(did).iter().filter(filter_fn)
+        };
+        attrs_iter
+            .map(|attribute| {
+                let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
+                let span = attribute.span;
+                stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
+            })
+            .collect()
+    }
+
     fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
         let tables = self.0.borrow();
         tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6d4a8c29bc9..3b6147c4c0f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -768,6 +768,7 @@ symbols! {
         enable,
         encode,
         end,
+        entry_nops,
         enumerate_method,
         env,
         env_CFG_RELEASE: env!("CFG_RELEASE"),
@@ -1383,6 +1384,7 @@ symbols! {
         passes,
         pat,
         pat_param,
+        patchable_function_entry,
         path,
         pattern_complexity,
         pattern_parentheses,
@@ -1421,6 +1423,7 @@ symbols! {
         prefetch_read_instruction,
         prefetch_write_data,
         prefetch_write_instruction,
+        prefix_nops,
         preg,
         prelude,
         prelude_import,
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index 44dbf549c1a..5f2d9b96c73 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -6,6 +6,7 @@
 use std::cell::Cell;
 
 use crate::abi::{FnAbi, Layout, LayoutShape};
+use crate::crate_def::Attribute;
 use crate::mir::alloc::{AllocId, GlobalAlloc};
 use crate::mir::mono::{Instance, InstanceDef, StaticDef};
 use crate::mir::{BinOp, Body, Place, UnOp};
@@ -55,6 +56,15 @@ pub trait Context {
     /// Returns the name of given `DefId`
     fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
 
+    /// Return attributes with the given attribute name.
+    ///
+    /// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
+    /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
+    fn get_attrs_by_path(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
+
+    /// Get all attributes of a definition.
+    fn get_all_attrs(&self, def_id: DefId) -> Vec<Attribute>;
+
     /// Returns printable, human readable form of `Span`
     fn span_to_string(&self, span: Span) -> String;
 
diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs
index 67752a5e629..d9b987c28a2 100644
--- a/compiler/stable_mir/src/crate_def.rs
+++ b/compiler/stable_mir/src/crate_def.rs
@@ -50,6 +50,21 @@ pub trait CrateDef {
         let def_id = self.def_id();
         with(|cx| cx.span_of_an_item(def_id))
     }
+
+    /// Return attributes with the given attribute name.
+    ///
+    /// Single segmented name like `#[inline]` is specified as `&["inline".to_string()]`.
+    /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
+    fn attrs_by_path(&self, attr: &[Symbol]) -> Vec<Attribute> {
+        let def_id = self.def_id();
+        with(|cx| cx.get_attrs_by_path(def_id, attr))
+    }
+
+    /// Return all attributes of this definition.
+    fn all_attrs(&self) -> Vec<Attribute> {
+        let def_id = self.def_id();
+        with(|cx| cx.get_all_attrs(def_id))
+    }
 }
 
 /// A trait that can be used to retrieve a definition's type.
@@ -69,6 +84,28 @@ pub trait CrateDefType: CrateDef {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Attribute {
+    value: String,
+    span: Span,
+}
+
+impl Attribute {
+    pub fn new(value: String, span: Span) -> Attribute {
+        Attribute { value, span }
+    }
+
+    /// Get the span of this attribute.
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Get the string representation of this attribute.
+    pub fn as_str(&self) -> &str {
+        &self.value
+    }
+}
+
 macro_rules! crate_def {
     ( $(#[$attr:meta])*
       $vis:vis $name:ident $(;)?
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 3e23612d0c1..3bb808a6c73 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -206,15 +206,16 @@ impl BorrowMut<str> for String {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for str {
     type Owned = String;
+
     #[inline]
     fn to_owned(&self) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
 
+    #[inline]
     fn clone_into(&self, target: &mut String) {
-        let mut b = mem::take(target).into_bytes();
-        self.as_bytes().clone_into(&mut b);
-        *target = unsafe { String::from_utf8_unchecked(b) }
+        target.clear();
+        target.push_str(self);
     }
 }
 
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index c25bc5a1b13..3bcd4be1834 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -459,6 +459,12 @@ impl<'a> Arguments<'a> {
     }
 }
 
+// Manually implementing these results in better error messages.
+#[stable(feature = "rust1", since = "1.0.0")]
+impl !Send for Arguments<'_> {}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl !Sync for Arguments<'_> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for Arguments<'_> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 92626feabf3..65a4d537cc7 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -5,6 +5,7 @@
 
 use super::*;
 use crate::hint::unreachable_unchecked;
+use crate::ptr::NonNull;
 
 #[lang = "format_placeholder"]
 #[derive(Copy, Clone)]
@@ -66,7 +67,13 @@ pub(super) enum Flag {
 
 #[derive(Copy, Clone)]
 enum ArgumentType<'a> {
-    Placeholder { value: &'a Opaque, formatter: fn(&Opaque, &mut Formatter<'_>) -> Result },
+    Placeholder {
+        // INVARIANT: `formatter` has type `fn(&T, _) -> _` for some `T`, and `value`
+        // was derived from a `&'a T`.
+        value: NonNull<()>,
+        formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
+        _lifetime: PhantomData<&'a ()>,
+    },
     Count(usize),
 }
 
@@ -90,21 +97,15 @@ pub struct Argument<'a> {
 impl<'a> Argument<'a> {
     #[inline(always)]
     fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
-        // SAFETY: `mem::transmute(x)` is safe because
-        //     1. `&'b T` keeps the lifetime it originated with `'b`
-        //              (so as to not have an unbounded lifetime)
-        //     2. `&'b T` and `&'b Opaque` have the same memory layout
-        //              (when `T` is `Sized`, as it is here)
-        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
-        // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
-        // (as long as `T` is `Sized`)
-        unsafe {
-            Argument {
-                ty: ArgumentType::Placeholder {
-                    formatter: mem::transmute(f),
-                    value: mem::transmute(x),
-                },
-            }
+        Argument {
+            // INVARIANT: this creates an `ArgumentType<'b>` from a `&'b T` and
+            // a `fn(&T, ...)`, so the invariant is maintained.
+            ty: ArgumentType::Placeholder {
+                value: NonNull::from(x).cast(),
+                // SAFETY: function pointers always have the same layout.
+                formatter: unsafe { mem::transmute(f) },
+                _lifetime: PhantomData,
+            },
         }
     }
 
@@ -162,7 +163,14 @@ impl<'a> Argument<'a> {
     #[inline(always)]
     pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
         match self.ty {
-            ArgumentType::Placeholder { formatter, value } => formatter(value, f),
+            // SAFETY:
+            // Because of the invariant that if `formatter` had the type
+            // `fn(&T, _) -> _` then `value` has type `&'b T` where `'b` is
+            // the lifetime of the `ArgumentType`, and because references
+            // and `NonNull` are ABI-compatible, this is completely equivalent
+            // to calling the original function passed to `new` with the
+            // original reference, which is sound.
+            ArgumentType::Placeholder { formatter, value, .. } => unsafe { formatter(value, f) },
             // SAFETY: the caller promised this.
             ArgumentType::Count(_) => unsafe { unreachable_unchecked() },
         }
@@ -208,7 +216,3 @@ impl UnsafeArg {
         Self { _private: () }
     }
 }
-
-extern "C" {
-    type Opaque;
-}
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 6748625f132..87c700dad06 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -888,12 +888,11 @@ impl Step for Rustc {
 macro_rules! tool_doc {
     (
         $tool: ident,
-        $should_run: literal,
         $path: literal,
         $(rustc_tool = $rustc_tool:literal, )?
-        $(in_tree = $in_tree:literal ,)?
         $(is_library = $is_library:expr,)?
         $(crates = $crates:expr)?
+        $(, submodule $(= $submodule:literal)? )?
        ) => {
         #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
@@ -907,7 +906,7 @@ macro_rules! tool_doc {
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                 let builder = run.builder;
-                run.crate_or_deps($should_run).default_condition(builder.config.compiler_docs)
+                run.path($path).default_condition(builder.config.compiler_docs)
             }
 
             fn make_run(run: RunConfig<'_>) {
@@ -921,6 +920,15 @@ macro_rules! tool_doc {
             /// we do not merge it with the other documentation from std, test and
             /// proc_macros. This is largely just a wrapper around `cargo doc`.
             fn run(self, builder: &Builder<'_>) {
+                let source_type = SourceType::InTree;
+                $(
+                    let _ = source_type; // silence the "unused variable" warning
+                    let source_type = SourceType::Submodule;
+
+                    let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
+                    builder.update_submodule(&path);
+                )?
+
                 let stage = builder.top_stage;
                 let target = self.target;
 
@@ -941,12 +949,6 @@ macro_rules! tool_doc {
                     builder.ensure(compile::Rustc::new(compiler, target));
                 }
 
-                let source_type = if true $(&& $in_tree)? {
-                    SourceType::InTree
-                } else {
-                    SourceType::Submodule
-                };
-
                 // Build cargo command.
                 let mut cargo = prepare_tool_cargo(
                     builder,
@@ -1008,21 +1010,14 @@ macro_rules! tool_doc {
     }
 }
 
-tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]);
-tool_doc!(
-    Rustfmt,
-    "rustfmt-nightly",
-    "src/tools/rustfmt",
-    crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]
-);
-tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
-tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]);
+tool_doc!(Rustdoc, "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]);
+tool_doc!(Rustfmt, "src/tools/rustfmt", crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]);
+tool_doc!(Clippy, "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
+tool_doc!(Miri, "src/tools/miri", crates = ["miri"]);
 tool_doc!(
     Cargo,
-    "cargo",
     "src/tools/cargo",
     rustc_tool = false,
-    in_tree = false,
     crates = [
         "cargo",
         "cargo-credential",
@@ -1034,12 +1029,12 @@ tool_doc!(
         "crates-io",
         "mdman",
         "rustfix",
-    ]
+    ],
+    submodule = "src/tools/cargo"
 );
-tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, crates = ["tidy"]);
+tool_doc!(Tidy, "src/tools/tidy", rustc_tool = false, crates = ["tidy"]);
 tool_doc!(
     Bootstrap,
-    "bootstrap",
     "src/bootstrap",
     rustc_tool = false,
     is_library = true,
@@ -1047,7 +1042,6 @@ tool_doc!(
 );
 tool_doc!(
     RunMakeSupport,
-    "run_make_support",
     "src/tools/run-make-support",
     rustc_tool = false,
     is_library = true,
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index efc09c41bf4..1ef5af7cc2d 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2983,6 +2983,9 @@ impl Step for Bootstrap {
         let compiler = builder.compiler(0, host);
         let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
 
+        // Some tests require cargo submodule to be present.
+        builder.build.update_submodule(Path::new("src/tools/cargo"));
+
         let mut check_bootstrap = Command::new(builder.python());
         check_bootstrap
             .args(["-m", "unittest", "bootstrap_test.py"])
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index cc5d490e4ad..a95a7f5491f 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -656,6 +656,8 @@ impl Step for Cargo {
     }
 
     fn run(self, builder: &Builder<'_>) -> PathBuf {
+        builder.build.update_submodule(Path::new("src/tools/cargo"));
+
         builder.ensure(ToolBuild {
             compiler: self.compiler,
             target: self.target,
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 68f1b1bef3f..e92ab57619b 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -1,5 +1,5 @@
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -34,6 +34,9 @@ impl Step for Vendor {
             cmd.arg("--versioned-dirs");
         }
 
+        // cargo submodule must be present for `x vendor` to work.
+        builder.build.update_submodule(Path::new("src/tools/cargo"));
+
         // Sync these paths by default.
         for p in [
             "src/tools/cargo/Cargo.toml",
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 08a96407a69..220eb5ba126 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -67,9 +67,9 @@ pub fn build(build: &mut Build) {
 
 /// Invokes `cargo metadata` to get package metadata of each workspace member.
 ///
-/// Note that `src/tools/cargo` is no longer a workspace member but we still
-/// treat it as one here, by invoking an additional `cargo metadata` command.
-fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
+/// This is used to resolve specific crate paths in `fn should_run` to compile
+/// particular crate (e.g., `x build sysroot` to build library/sysroot).
+fn workspace_members(build: &Build) -> Vec<Package> {
     let collect_metadata = |manifest_path| {
         let mut cargo = Command::new(&build.initial_cargo);
         cargo
@@ -88,13 +88,5 @@ fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
     };
 
     // Collects `metadata.packages` from all workspaces.
-    let packages = collect_metadata("Cargo.toml");
-    let cargo_packages = collect_metadata("src/tools/cargo/Cargo.toml");
-    let ra_packages = collect_metadata("src/tools/rust-analyzer/Cargo.toml");
-    let bootstrap_packages = collect_metadata("src/bootstrap/Cargo.toml");
-
-    // We only care about the root package from `src/tool/cargo` workspace.
-    let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
-
-    packages.into_iter().chain(cargo_package).chain(ra_packages).chain(bootstrap_packages)
+    collect_metadata("Cargo.toml")
 }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index dfc30298c28..afba907ee92 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -469,8 +469,7 @@ impl Build {
 
             // Make sure we update these before gathering metadata so we don't get an error about missing
             // Cargo.toml files.
-            let rust_submodules =
-                ["src/tools/cargo", "src/doc/book", "library/backtrace", "library/stdarch"];
+            let rust_submodules = ["src/doc/book", "library/backtrace", "library/stdarch"];
             for s in rust_submodules {
                 build.update_submodule(Path::new(s));
             }
diff --git a/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md b/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md
new file mode 100644
index 00000000000..4a9bf47a290
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md
@@ -0,0 +1,24 @@
+# `patchable-function-entry`
+
+--------------------
+
+The `-Z patchable-function-entry=total_nops,prefix_nops` or `-Z patchable-function-entry=total_nops`
+compiler flag enables nop padding of function entries with 'total_nops' nops, with
+an offset for the entry of the function at 'prefix_nops' nops. In the second form,
+'prefix_nops' defaults to 0.
+
+As an illustrative example, `-Z patchable-function-entry=3,2` would produce:
+
+```text
+nop
+nop
+function_label:
+nop
+//Actual function code begins here
+```
+
+This flag is used for hotpatching, especially in the Linux kernel. The flag
+arguments are modeled after the `-fpatchable-function-entry` flag as defined
+for both [Clang](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fpatchable-function-entry)
+and [gcc](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fpatchable-function-entry)
+and is intended to provide the same effect.
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index ab1b3043f0c..1c1de805db0 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -549,7 +549,7 @@ fn ident_difference_expr_with_base_location(
         | (Assign(_, _, _), Assign(_, _, _))
         | (TryBlock(_), TryBlock(_))
         | (Await(_, _), Await(_, _))
-        | (Gen(_, _, _), Gen(_, _, _))
+        | (Gen(_, _, _, _), Gen(_, _, _, _))
         | (Block(_, _), Block(_, _))
         | (Closure(_), Closure(_))
         | (Match(_, _, _), Match(_, _, _))
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 13256c5557d..181bbdde8e5 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -226,7 +226,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
                 && eq_fn_decl(lf, rf)
                 && eq_expr(le, re)
         },
-        (Gen(lc, lb, lk), Gen(rc, rb, rk)) => lc == rc && eq_block(lb, rb) && lk == rk,
+        (Gen(lc, lb, lk, _), Gen(rc, rb, rk, _)) => lc == rc && eq_block(lb, rb) && lk == rk,
         (Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt),
         (AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 8266f95fd70..c7c4b680b07 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -372,7 +372,7 @@ pub(crate) fn format_expr(
                 ))
             }
         }
-        ast::ExprKind::Gen(capture_by, ref block, ref kind) => {
+        ast::ExprKind::Gen(capture_by, ref block, ref kind, _) => {
             let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
                 "move "
             } else {
diff --git a/tests/codegen/patchable-function-entry/patchable-function-entry-both-flags.rs b/tests/codegen/patchable-function-entry/patchable-function-entry-both-flags.rs
new file mode 100644
index 00000000000..72204c78a49
--- /dev/null
+++ b/tests/codegen/patchable-function-entry/patchable-function-entry-both-flags.rs
@@ -0,0 +1,64 @@
+//@ compile-flags: -Z patchable-function-entry=15,10
+
+#![feature(patchable_function_entry)]
+#![crate_type = "lib"]
+
+// This should have the default, as set by the compile flags
+#[no_mangle]
+pub fn fun0() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
+pub fn fun1() {}
+
+// If we override an attribute to 0 or unset, the attribute should go away
+#[no_mangle]
+#[patchable_function_entry(entry_nops = 0)]
+pub fn fun2() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 20, entry_nops = 1)]
+pub fn fun3() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 2, entry_nops = 19)]
+pub fn fun4() {}
+
+// The attribute should override patchable-function-entry to 3 and
+// patchable-function-prefix to the default of 0, clearing it entirely
+#[no_mangle]
+#[patchable_function_entry(entry_nops = 3)]
+pub fn fun5() {}
+
+// The attribute should override patchable-function-prefix to 4
+// and patchable-function-entry to the default of 0, clearing it entirely
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 4)]
+pub fn fun6() {}
+
+// CHECK: @fun0() unnamed_addr #0
+// CHECK: @fun1() unnamed_addr #1
+// CHECK: @fun2() unnamed_addr #2
+// CHECK: @fun3() unnamed_addr #3
+// CHECK: @fun4() unnamed_addr #4
+// CHECK: @fun5() unnamed_addr #5
+// CHECK: @fun6() unnamed_addr #6
+
+// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-prefix"="10" {{.*}} }
+// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
+
+// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-entry{{.*}} }
+// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
+// CHECK: attributes #2 = { {{.*}} }
+
+// CHECK: attributes #3 = { {{.*}}"patchable-function-entry"="1"{{.*}}"patchable-function-prefix"="20" {{.*}} }
+// CHECK: attributes #4 = { {{.*}}"patchable-function-entry"="19"{{.*}}"patchable-function-prefix"="2" {{.*}} }
+
+// CHECK: attributes #5 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
+// CHECK-NOT: attributes #5 = { {{.*}}patchable-function-prefix{{.*}} }
+
+// CHECK: attributes #6 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
+// CHECK-NOT: attributes #6 = { {{.*}}patchable-function-entry{{.*}} }
diff --git a/tests/codegen/patchable-function-entry/patchable-function-entry-no-flag.rs b/tests/codegen/patchable-function-entry/patchable-function-entry-no-flag.rs
new file mode 100644
index 00000000000..3a7078fe551
--- /dev/null
+++ b/tests/codegen/patchable-function-entry/patchable-function-entry-no-flag.rs
@@ -0,0 +1,39 @@
+#![feature(patchable_function_entry)]
+#![crate_type = "lib"]
+
+// No patchable function entry should be set
+#[no_mangle]
+pub fn fun0() {}
+
+// The attribute should work even without compiler flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
+pub fn fun1() {}
+
+// The attribute should work even without compiler flags
+// and only set patchable-function-entry to 3.
+#[no_mangle]
+#[patchable_function_entry(entry_nops = 3)]
+pub fn fun2() {}
+
+// The attribute should work even without compiler flags
+// and only set patchable-function-prefix to 4.
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 4)]
+pub fn fun3() {}
+
+// CHECK: @fun0() unnamed_addr #0
+// CHECK: @fun1() unnamed_addr #1
+// CHECK: @fun2() unnamed_addr #2
+// CHECK: @fun3() unnamed_addr #3
+
+// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-entry{{.*}} }
+// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-prefix{{.*}} }
+
+// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
+
+// CHECK: attributes #2 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
+// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
+
+// CHECK: attributes #3 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
+// CHECK-NOT: attributes #3 = { {{.*}}patchable-function-entry{{.*}} }
diff --git a/tests/codegen/patchable-function-entry/patchable-function-entry-one-flag.rs b/tests/codegen/patchable-function-entry/patchable-function-entry-one-flag.rs
new file mode 100644
index 00000000000..8bdd61e461b
--- /dev/null
+++ b/tests/codegen/patchable-function-entry/patchable-function-entry-one-flag.rs
@@ -0,0 +1,66 @@
+//@ compile-flags: -Z patchable-function-entry=15
+
+#![feature(patchable_function_entry)]
+#![crate_type = "lib"]
+
+// This should have the default, as set by the compile flags
+#[no_mangle]
+pub fn fun0() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 1, entry_nops = 2)]
+pub fn fun1() {}
+
+// If we override an attribute to 0 or unset, the attribute should go away
+#[no_mangle]
+#[patchable_function_entry(entry_nops = 0)]
+pub fn fun2() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 20, entry_nops = 1)]
+pub fn fun3() {}
+
+// The attribute should override the compile flags
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 2, entry_nops = 19)]
+pub fn fun4() {}
+
+// The attribute should override patchable-function-entry to 3
+// and patchable-function-prefix to the default of 0, clearing it entirely
+#[no_mangle]
+#[patchable_function_entry(entry_nops = 3)]
+pub fn fun5() {}
+
+// The attribute should override patchable-function-prefix to 4
+// and patchable-function-entry to the default of 0, clearing it entirely
+#[no_mangle]
+#[patchable_function_entry(prefix_nops = 4)]
+pub fn fun6() {}
+
+// CHECK: @fun0() unnamed_addr #0
+// CHECK: @fun1() unnamed_addr #1
+// CHECK: @fun2() unnamed_addr #2
+// CHECK: @fun3() unnamed_addr #3
+// CHECK: @fun4() unnamed_addr #4
+// CHECK: @fun5() unnamed_addr #5
+// CHECK: @fun6() unnamed_addr #6
+
+// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="15" {{.*}} }
+// CHECK-NOT: attributes #0 = { {{.*}}patchable-function-prefix{{.*}} }
+
+// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
+
+// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-entry{{.*}} }
+// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
+// CHECK: attributes #2 = { {{.*}} }
+
+// CHECK: attributes #3 = { {{.*}}"patchable-function-entry"="1"{{.*}}"patchable-function-prefix"="20" {{.*}} }
+// CHECK: attributes #4 = { {{.*}}"patchable-function-entry"="19"{{.*}}"patchable-function-prefix"="2" {{.*}} }
+
+// CHECK: attributes #5 = { {{.*}}"patchable-function-entry"="3"{{.*}} }
+// CHECK-NOT: attributes #5 = { {{.*}}patchable-function-prefix{{.*}} }
+
+// CHECK: attributes #6 = { {{.*}}"patchable-function-prefix"="4"{{.*}} }
+// CHECK-NOT: attributes #6 = { {{.*}}patchable-function-entry{{.*}} }
diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map
index ddb4407881a..f2447e3c92c 100644
--- a/tests/coverage/issue-83601.cov-map
+++ b/tests/coverage/issue-83601.cov-map
@@ -1,12 +1,12 @@
 Function name: issue_83601::main
-Raw bytes (21): 0x[01, 01, 01, 05, 00, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
-- expression 0 operands: lhs = Counter(1), rhs = Zero
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
-    = (c1 - Zero)
+    = (c1 - c2)
 
diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index c4087d9369d..d3c4671e0ba 100644
--- a/tests/coverage/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
@@ -54,15 +54,15 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10)
 
 Function name: issue_84561::test3
-Raw bytes (375): 0x[01, 01, 31, 05, 00, 0d, 00, 15, 00, 12, 00, 15, 00, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
+Raw bytes (375): 0x[01, 01, 31, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 49
-- expression 0 operands: lhs = Counter(1), rhs = Zero
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Counter(3), rhs = Zero
-- expression 2 operands: lhs = Counter(5), rhs = Zero
+- expression 2 operands: lhs = Counter(5), rhs = Counter(6)
 - expression 3 operands: lhs = Expression(4, Sub), rhs = Zero
-- expression 4 operands: lhs = Counter(5), rhs = Zero
+- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
 - expression 5 operands: lhs = Counter(8), rhs = Zero
 - expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
 - expression 7 operands: lhs = Counter(8), rhs = Zero
@@ -111,15 +111,15 @@ Number of file 0 mappings: 51
 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
 - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31)
-    = (c1 - Zero)
+    = (c1 - c2)
 - Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
 - Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
     = (c3 - Zero)
 - Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
 - Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31)
-    = (c5 - Zero)
+    = (c5 - c6)
 - Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
-    = ((c5 - Zero) - Zero)
+    = ((c5 - c6) - Zero)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 48)
 - Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
 - Code(Zero) at (prev + 3, 32) to (start + 0, 48)
diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs
new file mode 100644
index 00000000000..be52853a479
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs
@@ -0,0 +1,155 @@
+//@ run-pass
+//! Test information regarding type layout.
+
+//@ ignore-stage1
+//@ ignore-cross-compile
+//@ ignore-remote
+//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
+
+#![feature(rustc_private)]
+#![feature(control_flow_enum)]
+
+extern crate rustc_hir;
+#[macro_use]
+extern crate rustc_smir;
+extern crate rustc_driver;
+extern crate rustc_interface;
+extern crate stable_mir;
+
+use rustc_smir::rustc_internal;
+use stable_mir::{CrateDef, CrateItems};
+use std::io::Write;
+use std::ops::ControlFlow;
+
+const CRATE_NAME: &str = "input";
+
+/// This function uses the Stable MIR APIs to get information about the test crate.
+fn test_stable_mir() -> ControlFlow<()> {
+    // Find items in the local crate.
+    let items = stable_mir::all_local_items();
+
+    test_builtins(&items);
+    test_derive(&items);
+    test_tool(&items);
+    test_all_attrs(&items);
+
+    ControlFlow::Continue(())
+}
+
+// Test built-in attributes.
+fn test_builtins(items: &CrateItems) {
+    let target_fn = *get_item(&items, "builtins_fn").unwrap();
+    let allow_attrs = target_fn.attrs_by_path(&["allow".to_string()]);
+    assert_eq!(allow_attrs[0].as_str(), "#![allow(unused_variables)]");
+
+    let inline_attrs = target_fn.attrs_by_path(&["inline".to_string()]);
+    assert_eq!(inline_attrs[0].as_str(), "#[inline]");
+
+    let deprecated_attrs = target_fn.attrs_by_path(&["deprecated".to_string()]);
+    assert_eq!(deprecated_attrs[0].as_str(), "#[deprecated(since = \"5.2.0\")]");
+}
+
+// Test derive attribute.
+fn test_derive(items: &CrateItems) {
+    let target_struct = *get_item(&items, "Foo").unwrap();
+    let attrs = target_struct.attrs_by_path(&["derive".to_string()]);
+    // No `derive` attribute since it's expanded before MIR.
+    assert_eq!(attrs.len(), 0);
+
+    // Check derived trait method's attributes.
+    let derived_fmt = *get_item(&items, "<Foo as std::fmt::Debug>::fmt").unwrap();
+    // The Rust reference lies about this attribute. It doesn't show up in `clone` or `fmt` impl.
+    let _fmt_attrs = derived_fmt.attrs_by_path(&["automatically_derived".to_string()]);
+}
+
+// Test tool attributes.
+fn test_tool(items: &CrateItems) {
+    let rustfmt_fn = *get_item(&items, "do_not_format").unwrap();
+    let rustfmt_attrs = rustfmt_fn.attrs_by_path(&["rustfmt".to_string(), "skip".to_string()]);
+    assert_eq!(rustfmt_attrs[0].as_str(), "#[rustfmt::skip]");
+
+    let clippy_fn = *get_item(&items, "complex_fn").unwrap();
+    let clippy_attrs = clippy_fn.attrs_by_path(&["clippy".to_string(),
+                                               "cyclomatic_complexity".to_string()]);
+    assert_eq!(clippy_attrs[0].as_str(), "#[clippy::cyclomatic_complexity = \"100\"]");
+}
+
+fn test_all_attrs(items: &CrateItems) {
+    let target_fn = *get_item(&items, "many_attrs").unwrap();
+    let all_attrs = target_fn.all_attrs();
+    assert_eq!(all_attrs[0].as_str(), "#[inline]");
+    assert_eq!(all_attrs[1].as_str(), "#[allow(unused_variables)]");
+    assert_eq!(all_attrs[2].as_str(), "#[allow(dead_code)]");
+    assert_eq!(all_attrs[3].as_str(), "#[allow(unused_imports)]");
+    assert_eq!(all_attrs[4].as_str(), "#![allow(clippy::filter_map)]");
+}
+
+
+fn get_item<'a>(
+    items: &'a CrateItems,
+    name: &str,
+) -> Option<&'a stable_mir::CrateItem> {
+    items.iter().find(|crate_item| crate_item.name() == name)
+}
+
+/// This test will generate and analyze a dummy crate using the stable mir.
+/// For that, it will first write the dummy crate into a file.
+/// Then it will create a `StableMir` using custom arguments and then
+/// it will run the compiler.
+fn main() {
+    let path = "attribute_input.rs";
+    generate_input(&path).unwrap();
+    let args = vec![
+        "rustc".to_string(),
+        "--crate-type=lib".to_string(),
+        "--crate-name".to_string(),
+        CRATE_NAME.to_string(),
+        path.to_string(),
+    ];
+    run!(args, test_stable_mir).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+        // General metadata applied to the enclosing module or crate.
+        #![crate_type = "lib"]
+
+        // Mixed inner and outer attributes.
+        #[inline]
+        #[deprecated(since = "5.2.0")]
+        fn builtins_fn() {{
+            #![allow(unused_variables)]
+
+            let x = ();
+            let y = ();
+            let z = ();
+        }}
+
+        // A derive attribute to automatically implement a trait.
+        #[derive(Debug, Clone, Copy)]
+        struct Foo(u32);
+
+        // A rustfmt tool attribute.
+        #[rustfmt::skip]
+        fn do_not_format() {{}}
+
+        // A clippy tool attribute.
+        #[clippy::cyclomatic_complexity = "100"]
+        pub fn complex_fn() {{}}
+
+        // A function with many attributes.
+        #[inline]
+        #[allow(unused_variables)]
+        #[allow(dead_code)]
+        #[allow(unused_imports)]
+        fn many_attrs() {{
+            #![allow(clippy::filter_map)]
+            todo!()
+        }}
+        "#
+    )?;
+    Ok(())
+}
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
index ce0d003f014..3bc467cc84d 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -1,20 +1,18 @@
 error[E0267]: `break` inside `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:32:9
    |
-LL | /     async {
-LL | |         break 0u8;
-   | |         ^^^^^^^^^ cannot `break` inside `async` block
-LL | |     };
-   | |_____- enclosing `async` block
+LL |     async {
+   |     ----- enclosing `async` block
+LL |         break 0u8;
+   |         ^^^^^^^^^ cannot `break` inside `async` block
 
 error[E0267]: `break` inside `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:39:13
    |
-LL | /         async {
-LL | |             break 0u8;
-   | |             ^^^^^^^^^ cannot `break` inside `async` block
-LL | |         };
-   | |_________- enclosing `async` block
+LL |         async {
+   |         ----- enclosing `async` block
+LL |             break 0u8;
+   |             ^^^^^^^^^ cannot `break` inside `async` block
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:21:58
@@ -29,13 +27,13 @@ LL | |
 LL | | }
    | |_^ expected `u8`, found `()`
 
-error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 23:22}` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:26:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6}` to `&dyn Future<Output = ()>`
+   = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 23:22}` to `&dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:12:43
@@ -45,13 +43,13 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 14:22}` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:17:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6}` to `&dyn Future<Output = ()>`
+   = note: required for the cast from `&{async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 14:22}` to `&dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:49:44
diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.stderr b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr
index 190c59e32eb..8410e7eca57 100644
--- a/tests/ui/async-await/async-borrowck-escaping-block-error.stderr
+++ b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -2,9 +2,8 @@ error[E0373]: async block may outlive the current function, but it borrows `x`,
   --> $DIR/async-borrowck-escaping-block-error.rs:6:14
    |
 LL |     Box::new(async { x } )
-   |              ^^^^^^^^-^^
-   |              |       |
-   |              |       `x` is borrowed here
+   |              ^^^^^   - `x` is borrowed here
+   |              |
    |              may outlive borrowed value `x`
    |
 note: async block is returned here
@@ -21,9 +20,8 @@ error[E0373]: async block may outlive the current function, but it borrows `x`,
   --> $DIR/async-borrowck-escaping-block-error.rs:11:5
    |
 LL |     async { *x }
-   |     ^^^^^^^^--^^
-   |     |       |
-   |     |       `x` is borrowed here
+   |     ^^^^^   -- `x` is borrowed here
+   |     |
    |     may outlive borrowed value `x`
    |
 note: async block is returned here
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
index 6f07a6feed3..4b626c1bed6 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
@@ -22,20 +22,18 @@ LL | fn needs_async_fn(_: impl async Fn()) {}
 error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/wrong-fn-kind.rs:9:20
    |
-LL |   fn needs_async_fn(_: impl async Fn()) {}
-   |                        --------------- change this to accept `FnMut` instead of `Fn`
+LL | fn needs_async_fn(_: impl async Fn()) {}
+   |                      --------------- change this to accept `FnMut` instead of `Fn`
 ...
-LL |       needs_async_fn(async || {
-   |       -------------- ^-------
-   |       |              |
-   |  _____|______________in this closure
-   | |     |
-   | |     expects `Fn` instead of `FnMut`
-LL | |
-LL | |         x += 1;
-   | |         - mutable borrow occurs due to use of `x` in closure
-LL | |     });
-   | |_____^ cannot borrow as mutable
+LL |     needs_async_fn(async || {
+   |     -------------- ^^^^^^^^
+   |     |              |
+   |     |              cannot borrow as mutable
+   |     |              in this closure
+   |     expects `Fn` instead of `FnMut`
+LL |
+LL |         x += 1;
+   |         - mutable borrow occurs due to use of `x` in closure
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr
index 85fdcda3b8c..9c5e8f0252c 100644
--- a/tests/ui/async-await/async-is-unwindsafe.stderr
+++ b/tests/ui/async-await/async-is-unwindsafe.stderr
@@ -1,20 +1,19 @@
 error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
   --> $DIR/async-is-unwindsafe.rs:12:5
    |
-LL |        is_unwindsafe(async {
-   |  ______^             -
-   | | ___________________|
-LL | ||
-LL | ||         use std::ptr::null;
-LL | ||         use std::task::{Context, RawWaker, RawWakerVTable, Waker};
-...  ||
-LL | ||         drop(cx_ref);
-LL | ||     });
-   | ||_____-^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
-   |  |_____|
-   |        within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`
+LL |       is_unwindsafe(async {
+   |       ^             ----- within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`
+   |  _____|
+   | |
+LL | |
+LL | |         use std::ptr::null;
+LL | |         use std::task::{Context, RawWaker, RawWakerVTable, Waker};
+...  |
+LL | |         drop(cx_ref);
+LL | |     });
+   | |______^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
    |
-   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe`
+   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}: UnwindSafe`
    = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>`
 note: future does not implement `UnwindSafe` as this value is used across an await
   --> $DIR/async-is-unwindsafe.rs:25:18
diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr
index 4c165ff619a..e1d7898478e 100644
--- a/tests/ui/async-await/coroutine-desc.stderr
+++ b/tests/ui/async-await/coroutine-desc.stderr
@@ -8,8 +8,8 @@ LL |     fun(async {}, async {});
    |     |   expected all arguments to be this `async` block type because they need to match the type of this parameter
    |     arguments to this function are incorrect
    |
-   = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
-              found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:27}`
+   = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:14}`
+              found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:24}`
    = note: no two async blocks, even if identical, have the same type
    = help: consider pinning your async block and casting it to a trait object
 note: function defined here
diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr
index 403e547a753..72921a72a95 100644
--- a/tests/ui/async-await/coroutine-not-future.stderr
+++ b/tests/ui/async-await/coroutine-not-future.stderr
@@ -26,11 +26,11 @@ note: required by a bound in `takes_coroutine`
 LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
 
-error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}: Coroutine<_>` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}: Coroutine<_>` is not satisfied
   --> $DIR/coroutine-not-future.rs:39:21
    |
 LL |     takes_coroutine(async {});
-   |     --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}`
+   |     --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr
index 51c06b9c8af..2ed40284702 100644
--- a/tests/ui/async-await/issue-67252-unnamed-future.stderr
+++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr
@@ -8,7 +8,7 @@ LL | |         let _a = a;
 LL | |     });
    | |______^ future created by async block is not `Send`
    |
-   = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}: Send`
+   = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}: Send`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-67252-unnamed-future.rs:20:17
    |
diff --git a/tests/ui/async-await/issue-68112.stderr b/tests/ui/async-await/issue-68112.stderr
index 96fc1633cc9..ca60079f3ef 100644
--- a/tests/ui/async-await/issue-68112.stderr
+++ b/tests/ui/async-await/issue-68112.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 33:6}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 29:25}: Send`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/issue-68112.rs:31:17
@@ -23,7 +23,7 @@ error: future cannot be sent between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 42:6}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 39:25}: Send`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/issue-68112.rs:40:17
@@ -42,7 +42,7 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 61:6}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 57:25}: Send`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this `async` fn body
@@ -61,13 +61,8 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
 note: required because it's used within this `async` block
   --> $DIR/issue-68112.rs:57:20
    |
-LL |       let send_fut = async {
-   |  ____________________^
-LL | |         let non_send_fut = make_non_send_future2();
-LL | |         let _ = non_send_fut.await;
-LL | |         ready(0).await;
-LL | |     };
-   | |_____^
+LL |     let send_fut = async {
+   |                    ^^^^^
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:11:25
    |
diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr
index 85c0c0c3088..1ca0b339c16 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.stderr
@@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
 LL | fn foo(x: NotSync) -> impl Future + Send {
    |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
 note: required because it appears within the type `PhantomData<*mut ()>`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 note: required because it appears within the type `NotSync`
@@ -28,12 +28,8 @@ LL | | }
 note: required because it's used within this `async` block
   --> $DIR/issue-70935-complex-spans.rs:18:5
    |
-LL | /     async move {
-LL | |         baz(|| async {
-LL | |             foo(x.clone());
-LL | |         }).await;
-LL | |     }
-   | |_____^
+LL |     async move {
+   |     ^^^^^^^^^^
 
 error[E0277]: `*mut ()` cannot be shared between threads safely
   --> $DIR/issue-70935-complex-spans.rs:15:23
@@ -41,7 +37,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
 LL | fn foo(x: NotSync) -> impl Future + Send {
    |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
 note: required because it appears within the type `PhantomData<*mut ()>`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 note: required because it appears within the type `NotSync`
@@ -65,12 +61,8 @@ LL | | }
 note: required because it's used within this `async` block
   --> $DIR/issue-70935-complex-spans.rs:18:5
    |
-LL | /     async move {
-LL | |         baz(|| async {
-LL | |             foo(x.clone());
-LL | |         }).await;
-LL | |     }
-   | |_____^
+LL |     async move {
+   |     ^^^^^^^^^^
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
index bdf2820887c..9d963686dea 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -13,14 +13,15 @@ LL |     y
 error[E0506]: cannot assign to `*x` because it is borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
    |
+LL |     (async move || {
+   |                  - return type of async closure is &'1 i32
+...
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
 LL |         *x += 1;
    |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
 LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
-LL |     })()
-   |     - return type of async closure is &'1 i32
 
 error: lifetime may not live long enough
   --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
@@ -61,14 +62,15 @@ LL |    }
 error[E0506]: cannot assign to `*x` because it is borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
    |
+LL |     (async move || -> &i32 {
+   |                          - return type of async closure is &'1 i32
+...
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
 LL |         *x += 1;
    |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
 LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
-LL |     })()
-   |     - return type of async closure is &'1 i32
 
 error: lifetime may not live long enough
   --> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
@@ -109,14 +111,14 @@ LL |    }
 error[E0506]: cannot assign to `*x` because it is borrowed
   --> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
    |
+LL |     async move {
+   |              - return type of async block is &'1 i32
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
 LL |         *x += 1;
    |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
 LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
-LL |     }
-   |     - return type of async block is &'1 i32
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr
index 0398e57ef78..f4cd7c42706 100644
--- a/tests/ui/async-await/issue-86507.stderr
+++ b/tests/ui/async-await/issue-86507.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 20:18}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
+   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/async-await/issues/issue-78938-async-block.stderr b/tests/ui/async-await/issues/issue-78938-async-block.stderr
index dc373a24f6f..2974ff59ad2 100644
--- a/tests/ui/async-await/issues/issue-78938-async-block.stderr
+++ b/tests/ui/async-await/issues/issue-78938-async-block.stderr
@@ -1,12 +1,10 @@
 error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
   --> $DIR/issue-78938-async-block.rs:8:33
    |
-LL |       let gameloop_handle = spawn(async {
-   |  _________________________________^
-LL | |         game_loop(Arc::clone(&room_ref))
-   | |                               -------- `room_ref` is borrowed here
-LL | |     });
-   | |_____^ may outlive borrowed value `room_ref`
+LL |     let gameloop_handle = spawn(async {
+   |                                 ^^^^^ may outlive borrowed value `room_ref`
+LL |         game_loop(Arc::clone(&room_ref))
+   |                               -------- `room_ref` is borrowed here
    |
    = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
 help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
index 640d946421a..8344b7a07dc 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
@@ -72,7 +72,7 @@ LL | |     }
    | |_____^ expected `()`, found `async` block
    |
    = note:  expected unit type `()`
-           found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 32:6}`
+           found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 27:10}`
 
 error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:44:5
@@ -89,7 +89,7 @@ LL | |     }
    | |_____^ expected `()`, found `async` block
    |
    = note:  expected unit type `()`
-           found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 51:6}`
+           found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 44:10}`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
index 640d946421a..8344b7a07dc 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
@@ -72,7 +72,7 @@ LL | |     }
    | |_____^ expected `()`, found `async` block
    |
    = note:  expected unit type `()`
-           found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 32:6}`
+           found `async` block `{async block@$DIR/async-closure-gate.rs:27:5: 27:10}`
 
 error[E0308]: mismatched types
   --> $DIR/async-closure-gate.rs:44:5
@@ -89,7 +89,7 @@ LL | |     }
    | |_____^ expected `()`, found `async` block
    |
    = note:  expected unit type `()`
-           found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 51:6}`
+           found `async` block `{async block@$DIR/async-closure-gate.rs:44:5: 44:10}`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/async-await/try-on-option-in-async.stderr b/tests/ui/async-await/try-on-option-in-async.stderr
index 4c7b4fa41fa..65f63093728 100644
--- a/tests/ui/async-await/try-on-option-in-async.stderr
+++ b/tests/ui/async-await/try-on-option-in-async.stderr
@@ -1,13 +1,11 @@
 error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:8:10
    |
-LL | /     async {
-LL | |         let x: Option<u32> = None;
-LL | |         x?;
-   | |          ^ cannot use the `?` operator in an async block that returns `{integer}`
-LL | |         22
-LL | |     }
-   | |_____- this function should return `Result` or `Option` to accept `?`
+LL |     async {
+   |     ----- this function should return `Result` or `Option` to accept `?`
+LL |         let x: Option<u32> = None;
+LL |         x?;
+   |          ^ cannot use the `?` operator in an async block that returns `{integer}`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
 
diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.stderr b/tests/ui/borrowck/cloning-in-async-block-121547.stderr
index ae57e0018f8..0023644a1f5 100644
--- a/tests/ui/borrowck/cloning-in-async-block-121547.stderr
+++ b/tests/ui/borrowck/cloning-in-async-block-121547.stderr
@@ -1,16 +1,14 @@
 error[E0382]: use of moved value: `value`
   --> $DIR/cloning-in-async-block-121547.rs:5:9
    |
-LL |   async fn clone_async_block(value: String) {
-   |                              ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
-LL |       for _ in 0..10 {
-   |       -------------- inside of this loop
-LL | /         async {
-LL | |             drop(value);
-   | |                  ----- use occurs due to use in coroutine
-LL | |
-LL | |         }.await
-   | |_________^ value moved here, in previous iteration of loop
+LL | async fn clone_async_block(value: String) {
+   |                            ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
+LL |     for _ in 0..10 {
+   |     -------------- inside of this loop
+LL |         async {
+   |         ^^^^^ value moved here, in previous iteration of loop
+LL |             drop(value);
+   |                  ----- use occurs due to use in coroutine
    |
 help: consider cloning the value if the performance cost is acceptable
    |
diff --git a/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
index f030961b7ed..77dc214bcec 100644
--- a/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
+++ b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
@@ -1,67 +1,57 @@
 error[E0267]: `break` inside `async` function
   --> $DIR/break-inside-coroutine-issue-124495.rs:8:5
    |
-LL |   async fn async_fn() {
-   |  _____________________-
-LL | |     break;
-   | |     ^^^^^ cannot `break` inside `async` function
-LL | | }
-   | |_- enclosing `async` function
+LL | async fn async_fn() {
+   | ------------------- enclosing `async` function
+LL |     break;
+   |     ^^^^^ cannot `break` inside `async` function
 
 error[E0267]: `break` inside `gen` function
   --> $DIR/break-inside-coroutine-issue-124495.rs:12:5
    |
-LL |   gen fn gen_fn() {
-   |  _________________-
-LL | |     break;
-   | |     ^^^^^ cannot `break` inside `gen` function
-LL | | }
-   | |_- enclosing `gen` function
+LL | gen fn gen_fn() {
+   | --------------- enclosing `gen` function
+LL |     break;
+   |     ^^^^^ cannot `break` inside `gen` function
 
 error[E0267]: `break` inside `async gen` function
   --> $DIR/break-inside-coroutine-issue-124495.rs:16:5
    |
-LL |   async gen fn async_gen_fn() {
-   |  _____________________________-
-LL | |     break;
-   | |     ^^^^^ cannot `break` inside `async gen` function
-LL | | }
-   | |_- enclosing `async gen` function
+LL | async gen fn async_gen_fn() {
+   | --------------------------- enclosing `async gen` function
+LL |     break;
+   |     ^^^^^ cannot `break` inside `async gen` function
 
 error[E0267]: `break` inside `async` block
   --> $DIR/break-inside-coroutine-issue-124495.rs:20:21
    |
 LL |     let _ = async { break; };
-   |             --------^^^^^---
-   |             |       |
-   |             |       cannot `break` inside `async` block
+   |             -----   ^^^^^ cannot `break` inside `async` block
+   |             |
    |             enclosing `async` block
 
 error[E0267]: `break` inside `async` closure
   --> $DIR/break-inside-coroutine-issue-124495.rs:22:24
    |
 LL |     let _ = async || { break; };
-   |             -----------^^^^^---
-   |             |          |
-   |             |          cannot `break` inside `async` closure
+   |             --------   ^^^^^ cannot `break` inside `async` closure
+   |             |
    |             enclosing `async` closure
 
 error[E0267]: `break` inside `gen` block
   --> $DIR/break-inside-coroutine-issue-124495.rs:24:19
    |
 LL |     let _ = gen { break; };
-   |             ------^^^^^---
-   |             |     |
-   |             |     cannot `break` inside `gen` block
+   |             ---   ^^^^^ cannot `break` inside `gen` block
+   |             |
    |             enclosing `gen` block
 
 error[E0267]: `break` inside `async gen` block
   --> $DIR/break-inside-coroutine-issue-124495.rs:26:25
    |
 LL |     let _ = async gen { break; };
-   |             ------------^^^^^---
-   |             |           |
-   |             |           cannot `break` inside `async gen` block
+   |             ---------   ^^^^^ cannot `break` inside `async gen` block
+   |             |
    |             enclosing `async gen` block
 
 error: aborting due to 7 previous errors
diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr
index d172dff3abd..b5074911aa9 100644
--- a/tests/ui/coroutine/clone-impl-async.stderr
+++ b/tests/ui/coroutine/clone-impl-async.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Copy` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:17:16
    |
 LL |     check_copy(&inner_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -12,11 +12,11 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}: Clone` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:19:17
    |
 LL |     check_clone(&inner_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 16:6}`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -26,11 +26,11 @@ note: required by a bound in `check_clone`
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Copy` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:26:16
    |
 LL |     check_copy(&outer_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -40,11 +40,11 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}: Clone` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:28:17
    |
 LL |     check_clone(&outer_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 25:6}`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -54,11 +54,11 @@ note: required by a bound in `check_clone`
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Copy` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:32:16
    |
 LL |     check_copy(&maybe_copy_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}`
+   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -68,11 +68,11 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}: Clone` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:34:17
    |
 LL |     check_clone(&maybe_copy_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:41}`
+   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/coroutine/gen_block_is_coro.stderr b/tests/ui/coroutine/gen_block_is_coro.stderr
index 83a674fa53c..afcdce1d58d 100644
--- a/tests/ui/coroutine/gen_block_is_coro.stderr
+++ b/tests/ui/coroutine/gen_block_is_coro.stderr
@@ -1,20 +1,20 @@
-error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:21}: Coroutine` is not satisfied
+error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}: Coroutine` is not satisfied
   --> $DIR/gen_block_is_coro.rs:6:13
    |
 LL | fn foo() -> impl Coroutine<Yield = u32, Return = ()> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:21}`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}`
 
-error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:21}: Coroutine` is not satisfied
+error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}: Coroutine` is not satisfied
   --> $DIR/gen_block_is_coro.rs:10:13
    |
 LL | fn bar() -> impl Coroutine<Yield = i64, Return = ()> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:21}`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}`
 
-error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:21}: Coroutine` is not satisfied
+error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}: Coroutine` is not satisfied
   --> $DIR/gen_block_is_coro.rs:14:13
    |
 LL | fn baz() -> impl Coroutine<Yield = i32, Return = ()> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:21}`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr
index fb2f2ba5597..bf0985a76a2 100644
--- a/tests/ui/coroutine/gen_block_is_no_future.stderr
+++ b/tests/ui/coroutine/gen_block_is_no_future.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
+error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future
   --> $DIR/gen_block_is_no_future.rs:4:13
    |
 LL | fn foo() -> impl std::future::Future {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future
    |
-   = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}`
+   = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/gen_block_move.stderr b/tests/ui/coroutine/gen_block_move.stderr
index b93f6a9a610..720b8d73322 100644
--- a/tests/ui/coroutine/gen_block_move.stderr
+++ b/tests/ui/coroutine/gen_block_move.stderr
@@ -1,14 +1,11 @@
 error[E0373]: gen block may outlive the current function, but it borrows `x`, which is owned by the current function
   --> $DIR/gen_block_move.rs:7:5
    |
-LL | /     gen {
-LL | |         yield 42;
-LL | |         if x == "foo" { return }
-LL | |         x.clear();
-   | |         - `x` is borrowed here
-LL | |         for x in 3..6 { yield x }
-LL | |     }
-   | |_____^ may outlive borrowed value `x`
+LL |     gen {
+   |     ^^^ may outlive borrowed value `x`
+...
+LL |         x.clear();
+   |         - `x` is borrowed here
    |
 note: gen block is returned here
   --> $DIR/gen_block_move.rs:7:5
diff --git a/tests/ui/feature-gates/feature-gate-patchable-function-entry.rs b/tests/ui/feature-gates/feature-gate-patchable-function-entry.rs
new file mode 100644
index 00000000000..b9642c7bfd4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-patchable-function-entry.rs
@@ -0,0 +1,3 @@
+#[patchable_function_entry(prefix_nops = 1, entry_nops = 1)]
+//~^ ERROR: the `#[patchable_function_entry]` attribute is an experimental feature
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr b/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr
new file mode 100644
index 00000000000..55fcdb4f729
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-patchable-function-entry.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the `#[patchable_function_entry]` attribute is an experimental feature
+  --> $DIR/feature-gate-patchable-function-entry.rs:1:1
+   |
+LL | #[patchable_function_entry(prefix_nops = 1, entry_nops = 1)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123115 <https://github.com/rust-lang/rust/issues/123115> for more information
+   = help: add `#![feature(patchable_function_entry)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr
index bebf575d9a7..dff9b23ba67 100644
--- a/tests/ui/fmt/send-sync.stderr
+++ b/tests/ui/fmt/send-sync.stderr
@@ -1,45 +1,27 @@
-error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
+error[E0277]: `Arguments<'_>` cannot be sent between threads safely
   --> $DIR/send-sync.rs:8:10
    |
 LL |     send(format_args!("{:?}", c));
-   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `Arguments<'_>` cannot be sent between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Send`
-   = note: required because it appears within the type `&core::fmt::rt::Opaque`
-note: required because it appears within the type `core::fmt::rt::ArgumentType<'_>`
-  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
-note: required because it appears within the type `core::fmt::rt::Argument<'_>`
-  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
-   = note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
-   = note: required for `&[core::fmt::rt::Argument<'_>]` to implement `Send`
-note: required because it appears within the type `Arguments<'_>`
-  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   = help: the trait `Send` is not implemented for `Arguments<'_>`
 note: required by a bound in `send`
   --> $DIR/send-sync.rs:1:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
-error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
+error[E0277]: `Arguments<'_>` cannot be shared between threads safely
   --> $DIR/send-sync.rs:9:10
    |
 LL |     sync(format_args!("{:?}", c));
-   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `Arguments<'_>` cannot be shared between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Sync`
-   = note: required because it appears within the type `&core::fmt::rt::Opaque`
-note: required because it appears within the type `core::fmt::rt::ArgumentType<'_>`
-  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
-note: required because it appears within the type `core::fmt::rt::Argument<'_>`
-  --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
-   = note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
-   = note: required because it appears within the type `&[core::fmt::rt::Argument<'_>]`
-note: required because it appears within the type `Arguments<'_>`
-  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   = help: the trait `Sync` is not implemented for `Arguments<'_>`
 note: required by a bound in `sync`
   --> $DIR/send-sync.rs:2:12
    |
diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr
index e4bcc92bf6e..09c2903ab02 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait.stderr
+++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr
@@ -10,7 +10,7 @@ LL |         async { () }
    |         ^^^^^^^^^^^^ expected future, found `async` block
    |
    = note: expected opaque type `Foo<'_>::Fut<'a>`
-            found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18:21}`
+            found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18:14}`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/issue-90014-tait.rs:17:8
    |
diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr
index 9af0fad9cdb..f892da2a535 100644
--- a/tests/ui/impl-trait/issue-55872-3.stderr
+++ b/tests/ui/impl-trait/issue-55872-3.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}: Copy` is not satisfied
+error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}: Copy` is not satisfied
   --> $DIR/issue-55872-3.rs:13:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}`
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr
index 91dad1b5e67..dc5579c1c82 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr
@@ -1,4 +1,4 @@
-error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:21}` to be a future that resolves to `u8`, but it resolves to `()`
+error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be a future that resolves to `u8`, but it resolves to `()`
   --> $DIR/issue-78722-2.rs:11:30
    |
 LL |         fn concrete_use() -> F {
@@ -16,7 +16,7 @@ LL |         let f: F = async { 1 };
    |                expected due to this
    |
    = note: expected opaque type `F`
-            found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:31}`
+            found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:25}`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr
index 0bb24fae822..3642000597f 100644
--- a/tests/ui/impl-trait/issues/issue-78722.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722.stderr
@@ -8,7 +8,7 @@ LL |         let f: F = async { 1 };
    = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:21}` to be a future that resolves to `u8`, but it resolves to `()`
+error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:18}` to be a future that resolves to `u8`, but it resolves to `()`
   --> $DIR/issue-78722.rs:8:30
    |
 LL |         fn concrete_use() -> F {
diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr
index 14d51a1b064..f1e3b97be02 100644
--- a/tests/ui/impl-trait/nested-return-type4.stderr
+++ b/tests/ui/impl-trait/nested-return-type4.stderr
@@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
 LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
    |         --                     --------------------------------------------- opaque type defined here
    |         |
-   |         hidden type `{async block@$DIR/nested-return-type4.rs:4:5: 4:31}` captures the lifetime `'s` as defined here
+   |         hidden type `{async block@$DIR/nested-return-type4.rs:4:5: 4:15}` captures the lifetime `'s` as defined here
 LL |     async move { let _s = s; }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr
index 1baf95d2bf7..225d7503a02 100644
--- a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr
+++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr
@@ -52,13 +52,13 @@ error[E0308]: mismatched types
   --> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20
    |
 LL |     let a = async { 42 };
-   |             ------------ the found `async` block
+   |             ----- the found `async` block
 ...
 LL |     let s = Demo { a };
    |                    ^ expected `Pin<Box<...>>`, found `async` block
    |
    = note:     expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}`
+           found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:18}`
 help: you need to pin and box this expression
    |
 LL |     let s = Demo { a: Box::pin(a) };
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs
new file mode 100644
index 00000000000..1e376c9ff3c
--- /dev/null
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs
@@ -0,0 +1,17 @@
+#![feature(patchable_function_entry)]
+fn main() {}
+
+#[patchable_function_entry(prefix_nops = 256, entry_nops = 0)]//~error: integer value out of range
+pub fn too_high_pnops() {}
+
+#[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)]//~error: invalid literal value
+pub fn non_int_nop() {}
+
+#[patchable_function_entry]//~error: malformed `patchable_function_entry` attribute input
+pub fn malformed_attribute() {}
+
+#[patchable_function_entry(prefix_nops = 10, something = 0)]//~error: unexpected parameter name
+pub fn unexpected_parameter_name() {}
+
+#[patchable_function_entry()]//~error: must specify at least one parameter
+pub fn no_parameters_given() {}
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr
new file mode 100644
index 00000000000..d9710c6e6a2
--- /dev/null
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr
@@ -0,0 +1,32 @@
+error: malformed `patchable_function_entry` attribute input
+  --> $DIR/patchable-function-entry-attribute.rs:10:1
+   |
+LL | #[patchable_function_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
+
+error: integer value out of range
+  --> $DIR/patchable-function-entry-attribute.rs:4:42
+   |
+LL | #[patchable_function_entry(prefix_nops = 256, entry_nops = 0)]
+   |                                          ^^^ value must be between `0` and `255`
+
+error: invalid literal value
+  --> $DIR/patchable-function-entry-attribute.rs:7:42
+   |
+LL | #[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)]
+   |                                          ^^^^^^^^^^^^^ value must be an integer between `0` and `255`
+
+error: unexpected parameter name
+  --> $DIR/patchable-function-entry-attribute.rs:13:46
+   |
+LL | #[patchable_function_entry(prefix_nops = 10, something = 0)]
+   |                                              ^^^^^^^^^^^^^ expected prefix_nops or entry_nops
+
+error: must specify at least one parameter
+  --> $DIR/patchable-function-entry-attribute.rs:16:1
+   |
+LL | #[patchable_function_entry()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs
new file mode 100644
index 00000000000..cb5bc62b6b3
--- /dev/null
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs
@@ -0,0 +1,2 @@
+//@ compile-flags: -Z patchable-function-entry=1,2
+fn main() {}
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr b/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr
new file mode 100644
index 00000000000..b09af94a615
--- /dev/null
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `1,2` for unstable option `patchable-function-entry` - either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops) was expected
+
diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr
index f3e0665fef5..9075cf40dda 100644
--- a/tests/ui/pattern/non-structural-match-types.stderr
+++ b/tests/ui/pattern/non-structural-match-types.stderr
@@ -4,7 +4,7 @@ error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used
 LL |         const { || {} } => {}
    |         ^^^^^^^^^^^^^^^
 
-error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns
+error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:12:9
    |
 LL |         const { async {} } => {}
diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 60ab392f55d..42bc094859a 100644
--- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -79,7 +79,7 @@ LL | |     }
    | |_____^ expected `Pin<Box<...>>`, found `async` block
    |
    = note:     expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found `async` block `{async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6}`
+           found `async` block `{async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 28:10}`
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr
index ebd0ada2604..83d520341bc 100644
--- a/tests/ui/traits/next-solver/async.fail.stderr
+++ b/tests/ui/traits/next-solver/async.fail.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:25} as Future>::Output == i32`
+error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:22} as Future>::Output == i32`
   --> $DIR/async.rs:12:17
    |
 LL |     needs_async(async {});
diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
index b62186103c7..6cbffaaed4d 100644
--- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
@@ -2,9 +2,7 @@ error[E0733]: recursion in an async block requires boxing
   --> $DIR/indirect-recursion-issue-112047.rs:22:9
    |
 LL |         async move { recur(self).await; }
-   |         ^^^^^^^^^^^^^-----------------^^^
-   |                      |
-   |                      recursive call here
+   |         ^^^^^^^^^^   ----------------- recursive call here
    |
 note: which leads to this async fn
   --> $DIR/indirect-recursion-issue-112047.rs:14:1