about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-04-25 05:04:32 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-04-25 05:04:32 +0000
commitff6fc757815055923e7f7ff73eaed8f9cbcfba75 (patch)
treebfd3766e077a0f447004b74063ad40ec02cd00e3
parentbed7caf20638dde1822553d432f6fe213baf4eae (diff)
parentcb3752d20e0f5d24348062211102a08d46fbecff (diff)
downloadrust-ff6fc757815055923e7f7ff73eaed8f9cbcfba75.tar.gz
rust-ff6fc757815055923e7f7ff73eaed8f9cbcfba75.zip
Merge from rustc
-rw-r--r--.github/ISSUE_TEMPLATE/tracking_issue.md2
-rw-r--r--.github/workflows/ci.yml570
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs10
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl3
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs117
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs4
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs55
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs154
-rw-r--r--compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs10
-rw-r--r--compiler/rustc_codegen_gcc/example/std_example.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0626.md20
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0627.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0628.md8
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0727.md8
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs6
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_fs_util/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs42
-rw-r--r--compiler/rustc_middle/src/lib.rs3
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs82
-rw-r--r--compiler/rustc_middle/src/ty/context.rs29
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs13
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs10
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs14
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_resolve/src/lib.rs16
-rw-r--r--compiler/rustc_serialize/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/config.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs2
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs2
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs2
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/core/src/iter/adapters/enumerate.rs1
-rw-r--r--library/core/src/iter/sources/from_coroutine.rs2
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/ops/coroutine.rs3
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/sync/atomic.rs9
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/lib.rs1
-rw-r--r--library/std/src/path.rs4
-rw-r--r--library/std/src/sys/pal/windows/mod.rs17
-rw-r--r--library/std/src/sys/pal/windows/os.rs2
-rw-r--r--library/std/src/sys/pal/windows/thread_local_key.rs26
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh2
-rwxr-xr-xsrc/ci/docker/scripts/build-fuchsia-toolchain.sh8
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py2
-rwxr-xr-xsrc/ci/github-actions/calculate-job-matrix.py115
-rw-r--r--src/ci/github-actions/ci.yml438
-rw-r--r--src/ci/github-actions/jobs.yml426
-rwxr-xr-xsrc/ci/scripts/calculate-job-matrix.py25
-rw-r--r--src/doc/unstable-book/src/language-features/coroutines.md23
-rw-r--r--src/doc/unstable-book/src/language-features/inline-const-pat.md2
-rw-r--r--src/doc/unstable-book/src/language-features/inline-const.md32
-rw-r--r--src/doc/unstable-book/src/the-unstable-book.md4
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr12
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs2
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.rs2
-rw-r--r--src/tools/clippy/tests/ui/const_is_empty.rs1
-rw-r--r--src/tools/clippy/tests/ui/const_is_empty.stderr52
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5238.rs4
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.rs1
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.stderr32
-rw-r--r--src/tools/clippy/tests/ui/large_futures.fixed1
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs1
-rw-r--r--src/tools/clippy/tests/ui/large_futures.stderr16
-rw-r--r--src/tools/clippy/tests/ui/manual_float_methods.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_float_methods.stderr12
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/panicking_macros.rs1
-rw-r--r--src/tools/clippy/tests/ui/panicking_macros.stderr32
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs6
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/fail/coroutine-pinned-moved.rs4
-rw-r--r--src/tools/miri/tests/pass/coroutine.rs36
-rw-r--r--src/tools/miri/tests/pass/portable-simd.rs2
-rw-r--r--src/tools/miri/tests/pass/shims/path.rs1
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs4
-rw-r--r--src/tools/miri/tests/pass/track-caller-attribute.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs6
-rw-r--r--src/tools/rustfmt/tests/source/immovable_coroutines.rs3
-rw-r--r--src/tools/rustfmt/tests/target/immovable_coroutines.rs3
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs30
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs30
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect.rs55
-rw-r--r--tests/codegen/align-byval-alignment-mismatch.rs6
-rw-r--r--tests/codegen/align-byval.rs12
-rw-r--r--tests/codegen/align-enum.rs4
-rw-r--r--tests/codegen/align-struct.rs8
-rw-r--r--tests/codegen/array-codegen.rs2
-rw-r--r--tests/codegen/array-map.rs2
-rw-r--r--tests/codegen/cast-target-abi.rs121
-rw-r--r--tests/codegen/cffi/ffi-out-of-bounds-loads.rs2
-rw-r--r--tests/codegen/const_scalar_pair.rs2
-rw-r--r--tests/codegen/coroutine-debug-msvc.rs2
-rw-r--r--tests/codegen/coroutine-debug.rs2
-rw-r--r--tests/codegen/debug-fndef-size.rs2
-rw-r--r--tests/codegen/emcripten-catch-unwind.rs59
-rw-r--r--tests/codegen/enum/enum-match.rs2
-rw-r--r--tests/codegen/i128-x86-align.rs9
-rw-r--r--tests/codegen/intrinsics/transmute.rs17
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs2
-rw-r--r--tests/codegen/issues/issue-111603.rs2
-rw-r--r--tests/codegen/issues/issue-96274.rs1
-rw-r--r--tests/codegen/overaligned-constant.rs9
-rw-r--r--tests/codegen/packed.rs4
-rw-r--r--tests/codegen/personality_lifetimes.rs2
-rw-r--r--tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs2
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs1
-rw-r--r--tests/codegen/sroa-fragment-debuginfo.rs6
-rw-r--r--tests/codegen/stores.rs8
-rw-r--r--tests/codegen/swap-large-types.rs2
-rw-r--r--tests/codegen/swap-small-types.rs2
-rw-r--r--tests/coverage/coroutine.cov-map4
-rw-r--r--tests/coverage/coroutine.coverage4
-rw-r--r--tests/coverage/coroutine.rs4
-rw-r--r--tests/coverage/yield.cov-map8
-rw-r--r--tests/coverage/yield.coverage6
-rw-r--r--tests/coverage/yield.rs6
-rw-r--r--tests/debuginfo/coroutine-locals.rs9
-rw-r--r--tests/debuginfo/coroutine-objects.rs5
-rw-r--r--tests/debuginfo/function-names.rs5
-rw-r--r--tests/debuginfo/issue-57822.rs8
-rw-r--r--tests/mir-opt/building/custom/arrays.rs2
-rw-r--r--tests/mir-opt/building/custom/consts.rs2
-rw-r--r--tests/mir-opt/building/custom/operators.rs2
-rw-r--r--tests/mir-opt/const_prop/invalid_constant.rs1
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir2
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir2
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.rs5
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir2
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir2
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.rs5
-rw-r--r--tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir12
-rw-r--r--tests/mir-opt/coroutine_tiny.rs5
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff22
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff22
-rw-r--r--tests/mir-opt/inline/inline_coroutine.rs3
-rw-r--r--tests/pretty/stmt_expr_attributes.rs1
-rw-r--r--tests/run-make/valid-print-requests/Makefile4
-rw-r--r--tests/run-make/valid-print-requests/valid-print-requests.stderr2
-rw-r--r--tests/ui/associated-types/issue-25700.stderr5
-rw-r--r--tests/ui/async-await/async-outside-of-await-issue-121096.stderr2
-rw-r--r--tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr10
-rw-r--r--tests/ui/async-await/coroutine-not-future.rs23
-rw-r--r--tests/ui/async-await/coroutine-not-future.stderr42
-rw-r--r--tests/ui/async-await/issues/issue-51751.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-62009-1.stderr6
-rw-r--r--tests/ui/async-await/issues/issue-62009-2.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs10
-rw-r--r--tests/ui/async-await/issues/non-async-enclosing-span.stderr2
-rw-r--r--tests/ui/async-await/non-trivial-drop.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs8
-rw-r--r--tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs8
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs31
-rw-r--r--tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr7
-rw-r--r--tests/ui/binop/binop-consume-args.stderr140
-rw-r--r--tests/ui/binop/binop-move-semantics.stderr41
-rw-r--r--tests/ui/borrowck/borrowck-move-by-capture.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-move-out-of-static-item.stderr5
-rw-r--r--tests/ui/borrowck/borrowck-move-subcomponent.stderr5
-rw-r--r--tests/ui/borrowck/borrowck-overloaded-call.stderr5
-rw-r--r--tests/ui/borrowck/clone-on-ref.stderr12
-rw-r--r--tests/ui/borrowck/issue-101119.stderr5
-rw-r--r--tests/ui/borrowck/issue-103624.stderr5
-rw-r--r--tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr5
-rw-r--r--tests/ui/borrowck/issue-17718-static-move.stderr5
-rw-r--r--tests/ui/borrowck/issue-20801.stderr20
-rw-r--r--tests/ui/borrowck/move-error-in-promoted-2.stderr5
-rw-r--r--tests/ui/borrowck/move-error-snippets.stderr7
-rw-r--r--tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr10
-rw-r--r--tests/ui/box/leak-alloc.stderr5
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.rs1
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.stock.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr6
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs1
-rw-r--r--tests/ui/const_prop/dont-propagate-generic-instance-2.rs2
-rw-r--r--tests/ui/consts/closure-structural-match-issue-90013.rs1
-rw-r--r--tests/ui/consts/const-block-const-bound.rs2
-rw-r--r--tests/ui/consts/const-blocks/fn-call-in-const.rs1
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs1
-rw-r--r--tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs1
-rw-r--r--tests/ui/consts/issue-102117.rs2
-rw-r--r--tests/ui/coroutine/addassign-yield.rs8
-rw-r--r--tests/ui/coroutine/auto-trait-regions.rs8
-rw-r--r--tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs1
-rw-r--r--tests/ui/coroutine/auxiliary/unwind-aux.rs5
-rw-r--r--tests/ui/coroutine/auxiliary/xcrate-reachable.rs1
-rw-r--r--tests/ui/coroutine/auxiliary/xcrate.rs12
-rw-r--r--tests/ui/coroutine/borrow-in-tail-expr.rs4
-rw-r--r--tests/ui/coroutine/borrowing.rs6
-rw-r--r--tests/ui/coroutine/borrowing.stderr16
-rw-r--r--tests/ui/coroutine/check-resume-ty-lifetimes-2.rs8
-rw-r--r--tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr12
-rw-r--r--tests/ui/coroutine/check-resume-ty-lifetimes.rs15
-rw-r--r--tests/ui/coroutine/check-resume-ty-lifetimes.stderr6
-rw-r--r--tests/ui/coroutine/clone-impl-static.rs5
-rw-r--r--tests/ui/coroutine/clone-impl-static.stderr16
-rw-r--r--tests/ui/coroutine/clone-impl.rs17
-rw-r--r--tests/ui/coroutine/clone-impl.stderr84
-rw-r--r--tests/ui/coroutine/clone-rpit.next.stderr12
-rw-r--r--tests/ui/coroutine/clone-rpit.rs1
-rw-r--r--tests/ui/coroutine/conditional-drop.rs6
-rw-r--r--tests/ui/coroutine/control-flow.rs12
-rw-r--r--tests/ui/coroutine/coroutine-region-requirements.rs4
-rw-r--r--tests/ui/coroutine/coroutine-resume-after-panic.rs4
-rw-r--r--tests/ui/coroutine/coroutine-with-nll.rs1
-rw-r--r--tests/ui/coroutine/coroutine-with-nll.stderr2
-rw-r--r--tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs6
-rw-r--r--tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr16
-rw-r--r--tests/ui/coroutine/derived-drop-parent-expr.rs8
-rw-r--r--tests/ui/coroutine/discriminant.rs6
-rw-r--r--tests/ui/coroutine/drop-and-replace.rs5
-rw-r--r--tests/ui/coroutine/drop-control-flow.rs20
-rw-r--r--tests/ui/coroutine/drop-env.rs8
-rw-r--r--tests/ui/coroutine/drop-track-addassign-yield.rs6
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.rs6
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.stderr18
-rw-r--r--tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs4
-rw-r--r--tests/ui/coroutine/drop-yield-twice.rs4
-rw-r--r--tests/ui/coroutine/drop-yield-twice.stderr4
-rw-r--r--tests/ui/coroutine/dropck-resume.rs5
-rw-r--r--tests/ui/coroutine/dropck-resume.stderr2
-rw-r--r--tests/ui/coroutine/dropck.rs5
-rw-r--r--tests/ui/coroutine/dropck.stderr9
-rw-r--r--tests/ui/coroutine/gen_block.e2024.stderr47
-rw-r--r--tests/ui/coroutine/gen_block.none.stderr66
-rw-r--r--tests/ui/coroutine/gen_block.rs9
-rw-r--r--tests/ui/coroutine/issue-102645.rs5
-rw-r--r--tests/ui/coroutine/issue-102645.stderr2
-rw-r--r--tests/ui/coroutine/issue-105084.rs3
-rw-r--r--tests/ui/coroutine/issue-105084.stderr18
-rw-r--r--tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs5
-rw-r--r--tests/ui/coroutine/issue-113279.rs5
-rw-r--r--tests/ui/coroutine/issue-113279.stderr4
-rw-r--r--tests/ui/coroutine/issue-44197.rs4
-rw-r--r--tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs5
-rw-r--r--tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr2
-rw-r--r--tests/ui/coroutine/issue-48048.rs2
-rw-r--r--tests/ui/coroutine/issue-52304.rs1
-rw-r--r--tests/ui/coroutine/issue-52398.rs4
-rw-r--r--tests/ui/coroutine/issue-52398.stderr10
-rw-r--r--tests/ui/coroutine/issue-53548.rs4
-rw-r--r--tests/ui/coroutine/issue-57017.rs6
-rw-r--r--tests/ui/coroutine/issue-57084.rs4
-rw-r--r--tests/ui/coroutine/issue-57084.stderr5
-rw-r--r--tests/ui/coroutine/issue-57478.rs15
-rw-r--r--tests/ui/coroutine/issue-58888.rs2
-rw-r--r--tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs8
-rw-r--r--tests/ui/coroutine/issue-64620-yield-array-element.rs1
-rw-r--r--tests/ui/coroutine/issue-64620-yield-array-element.stderr13
-rw-r--r--tests/ui/coroutine/issue-68112.rs8
-rw-r--r--tests/ui/coroutine/issue-68112.stderr16
-rw-r--r--tests/ui/coroutine/issue-69017.rs1
-rw-r--r--tests/ui/coroutine/issue-69039.rs1
-rw-r--r--tests/ui/coroutine/issue-87142.rs1
-rw-r--r--tests/ui/coroutine/issue-88653.rs1
-rw-r--r--tests/ui/coroutine/issue-91477.rs1
-rw-r--r--tests/ui/coroutine/issue-91477.stderr13
-rw-r--r--tests/ui/coroutine/iterator-count.rs2
-rw-r--r--tests/ui/coroutine/live-upvar-across-yield.rs4
-rw-r--r--tests/ui/coroutine/match-bindings.rs2
-rw-r--r--tests/ui/coroutine/match-bindings.stderr5
-rw-r--r--tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed8
-rw-r--r--tests/ui/coroutine/missing_coroutine_attr_suggestion.rs8
-rw-r--r--tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr13
-rw-r--r--tests/ui/coroutine/nested_coroutine.rs8
-rw-r--r--tests/ui/coroutine/niche-in-coroutine.rs4
-rw-r--r--tests/ui/coroutine/non-static-is-unpin.rs4
-rw-r--r--tests/ui/coroutine/not-send-sync.rs6
-rw-r--r--tests/ui/coroutine/not-send-sync.stderr8
-rw-r--r--tests/ui/coroutine/overlap-locals.rs5
-rw-r--r--tests/ui/coroutine/panic-drops-resume.rs4
-rw-r--r--tests/ui/coroutine/panic-drops.rs17
-rw-r--r--tests/ui/coroutine/panic-safe.rs4
-rw-r--r--tests/ui/coroutine/parent-expression.rs6
-rw-r--r--tests/ui/coroutine/parent-expression.stderr18
-rw-r--r--tests/ui/coroutine/partial-drop.rs45
-rw-r--r--tests/ui/coroutine/partial-initialization-across-yield.rs8
-rw-r--r--tests/ui/coroutine/pattern-borrow.rs2
-rw-r--r--tests/ui/coroutine/pin-box-coroutine.rs6
-rw-r--r--tests/ui/coroutine/polymorphize-args.rs5
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-1.rs8
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-1.stderr12
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.rs6
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.stderr4
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-3.rs9
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-3.stderr11
-rw-r--r--tests/ui/coroutine/reborrow-mut-upvar.rs2
-rw-r--r--tests/ui/coroutine/reborrow-mut-upvar.stderr5
-rw-r--r--tests/ui/coroutine/ref-escapes-but-not-over-yield.rs9
-rw-r--r--tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr2
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.rs6
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.stderr16
-rw-r--r--tests/ui/coroutine/reinit-in-match-guard.rs6
-rw-r--r--tests/ui/coroutine/resume-after-return.rs12
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.rs4
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.stderr2
-rw-r--r--tests/ui/coroutine/resume-arg-size.rs8
-rw-r--r--tests/ui/coroutine/resume-live-across-yield.rs5
-rw-r--r--tests/ui/coroutine/retain-resume-ref.rs5
-rw-r--r--tests/ui/coroutine/retain-resume-ref.stderr2
-rw-r--r--tests/ui/coroutine/size-moved-locals.rs4
-rw-r--r--tests/ui/coroutine/sized-yield.rs5
-rw-r--r--tests/ui/coroutine/sized-yield.stderr7
-rw-r--r--tests/ui/coroutine/smoke-resume-args.rs17
-rw-r--r--tests/ui/coroutine/smoke.rs32
-rw-r--r--tests/ui/coroutine/static-coroutine.rs7
-rw-r--r--tests/ui/coroutine/static-mut-reference-across-yield.rs8
-rw-r--r--tests/ui/coroutine/static-not-unpin.current.stderr6
-rw-r--r--tests/ui/coroutine/static-not-unpin.next.stderr6
-rw-r--r--tests/ui/coroutine/static-not-unpin.rs8
-rw-r--r--tests/ui/coroutine/static-reference-across-yield.rs4
-rw-r--r--tests/ui/coroutine/too-live-local-in-immovable-gen.rs2
-rw-r--r--tests/ui/coroutine/too-live-local-in-immovable-gen.stderr5
-rw-r--r--tests/ui/coroutine/too-many-parameters.rs1
-rw-r--r--tests/ui/coroutine/too-many-parameters.stderr2
-rw-r--r--tests/ui/coroutine/type-mismatch-error.rs3
-rw-r--r--tests/ui/coroutine/type-mismatch-error.stderr2
-rw-r--r--tests/ui/coroutine/type-mismatch-signature-deduction.rs1
-rw-r--r--tests/ui/coroutine/type-mismatch-signature-deduction.stderr6
-rw-r--r--tests/ui/coroutine/uninhabited-field.rs4
-rw-r--r--tests/ui/coroutine/unsized-capture-across-yield.rs1
-rw-r--r--tests/ui/coroutine/unsized-capture-across-yield.stderr2
-rw-r--r--tests/ui/coroutine/unsized-local-across-yield.rs1
-rw-r--r--tests/ui/coroutine/unsized-local-across-yield.stderr2
-rw-r--r--tests/ui/coroutine/yield-in-args-rev.rs2
-rw-r--r--tests/ui/coroutine/yield-in-args-rev.stderr5
-rw-r--r--tests/ui/coroutine/yield-in-args.rs1
-rw-r--r--tests/ui/coroutine/yield-in-args.stderr2
-rw-r--r--tests/ui/coroutine/yield-in-const.rs1
-rw-r--r--tests/ui/coroutine/yield-in-const.stderr8
-rw-r--r--tests/ui/coroutine/yield-in-function.rs1
-rw-r--r--tests/ui/coroutine/yield-in-function.stderr13
-rw-r--r--tests/ui/coroutine/yield-in-initializer.rs2
-rw-r--r--tests/ui/coroutine/yield-in-initializer.stderr5
-rw-r--r--tests/ui/coroutine/yield-in-static.rs1
-rw-r--r--tests/ui/coroutine/yield-in-static.stderr8
-rw-r--r--tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs1
-rw-r--r--tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr13
-rw-r--r--tests/ui/coroutine/yield-subtype.rs2
-rw-r--r--tests/ui/coroutine/yield-subtype.stderr5
-rw-r--r--tests/ui/coroutine/yield-while-iterating.rs14
-rw-r--r--tests/ui/coroutine/yield-while-iterating.stderr4
-rw-r--r--tests/ui/coroutine/yield-while-local-borrowed.rs8
-rw-r--r--tests/ui/coroutine/yield-while-ref-reborrowed.rs21
-rw-r--r--tests/ui/coroutine/yield-while-ref-reborrowed.stderr6
-rw-r--r--tests/ui/delegation/auxiliary/fn-header-aux.rs9
-rw-r--r--tests/ui/delegation/fn-header.rs57
-rw-r--r--tests/ui/delegation/impl-trait.rs27
-rw-r--r--tests/ui/delegation/not-supported.rs30
-rw-r--r--tests/ui/delegation/not-supported.stderr75
-rw-r--r--tests/ui/delegation/rename.rs20
-rw-r--r--tests/ui/derives/deriving-with-repr-packed.stderr5
-rw-r--r--tests/ui/drop/dynamic-drop.rs4
-rw-r--r--tests/ui/error-codes/E0504.stderr5
-rw-r--r--tests/ui/error-codes/E0505.stderr5
-rw-r--r--tests/ui/error-codes/E0507.stderr5
-rw-r--r--tests/ui/error-codes/E0508-fail.stderr5
-rw-r--r--tests/ui/error-codes/E0508.stderr5
-rw-r--r--tests/ui/error-codes/E0509.stderr5
-rw-r--r--tests/ui/feature-gates/feature-gate-closure_track_caller.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-closure_track_caller.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr26
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.none.stderr32
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-inline_const.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-inline_const.stderr13
-rw-r--r--tests/ui/fn/fn_def_coercion.rs58
-rw-r--r--tests/ui/fn/fn_def_coercion.stderr154
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion.rs69
-rw-r--r--tests/ui/fn/suggest-return-closure.rs1
-rw-r--r--tests/ui/fn/suggest-return-closure.stderr9
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.rs2
-rw-r--r--tests/ui/impl-trait/lifetimes.rs2
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.rs1
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr6
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr9
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.rs3
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr6
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr6
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.rs2
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs2
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr8
-rw-r--r--tests/ui/inline-const/const-expr-array-init.rs2
-rw-r--r--tests/ui/inline-const/const-expr-basic.rs2
-rw-r--r--tests/ui/inline-const/const-expr-generic-err.rs1
-rw-r--r--tests/ui/inline-const/const-expr-generic-err.stderr16
-rw-r--r--tests/ui/inline-const/const-expr-generic-err2.rs2
-rw-r--r--tests/ui/inline-const/const-expr-generic-err2.stderr2
-rw-r--r--tests/ui/inline-const/const-expr-generic.rs1
-rw-r--r--tests/ui/inline-const/const-expr-inference.rs2
-rw-r--r--tests/ui/inline-const/const-expr-lifetime-err.rs1
-rw-r--r--tests/ui/inline-const/const-expr-lifetime-err.stderr2
-rw-r--r--tests/ui/inline-const/const-expr-lifetime.rs1
-rw-r--r--tests/ui/inline-const/const-expr-macro.rs2
-rw-r--r--tests/ui/inline-const/const-expr-reference.rs2
-rw-r--r--tests/ui/inline-const/const-match-pat-lifetime.rs1
-rw-r--r--tests/ui/inline-const/elided-lifetime-being-infer-vars.rs2
-rw-r--r--tests/ui/inline-const/expr-unsafe-err.rs1
-rw-r--r--tests/ui/inline-const/expr-unsafe-err.stderr2
-rw-r--r--tests/ui/inline-const/expr-unsafe.rs2
-rw-r--r--tests/ui/inline-const/expr-with-block-err.rs2
-rw-r--r--tests/ui/inline-const/expr-with-block-err.stderr2
-rw-r--r--tests/ui/inline-const/expr-with-block.rs2
-rw-r--r--tests/ui/inline-const/instance-doesnt-depend-on-type.rs2
-rw-r--r--tests/ui/inline-const/interpolated.rs2
-rw-r--r--tests/ui/inline-const/promotion.rs1
-rw-r--r--tests/ui/inline-const/promotion.stderr2
-rw-r--r--tests/ui/inline-const/required-const.rs1
-rw-r--r--tests/ui/inline-const/required-const.stderr6
-rw-r--r--tests/ui/invalid-compile-flags/print.rs1
-rw-r--r--tests/ui/invalid-compile-flags/print.stderr4
-rw-r--r--tests/ui/issues/issue-17385.stderr10
-rw-r--r--tests/ui/issues/issue-24357.rs2
-rw-r--r--tests/ui/issues/issue-24357.stderr7
-rw-r--r--tests/ui/issues/issue-4335.stderr8
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.rs2
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr16
-rw-r--r--tests/ui/lint/invalid_from_utf8.rs1
-rw-r--r--tests/ui/lint/invalid_from_utf8.stderr42
-rw-r--r--tests/ui/lint/must_not_suspend/tuple-mismatch.rs5
-rw-r--r--tests/ui/lint/must_not_suspend/tuple-mismatch.stderr2
-rw-r--r--tests/ui/lint/non-local-defs/consts.rs2
-rw-r--r--tests/ui/lint/non-local-defs/consts.stderr16
-rw-r--r--tests/ui/lint/non-local-defs/from-local-for-global.rs2
-rw-r--r--tests/ui/lint/non-local-defs/from-local-for-global.stderr10
-rw-r--r--tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs4
-rw-r--r--tests/ui/lint/unused/unused-closure.rs4
-rw-r--r--tests/ui/liveness/liveness-upvars.rs4
-rw-r--r--tests/ui/loops/dont-suggest-break-thru-item.rs2
-rw-r--r--tests/ui/loops/dont-suggest-break-thru-item.stderr8
-rw-r--r--tests/ui/mir/issue-102389.stderr5
-rw-r--r--tests/ui/moves/borrow-closures-instead-of-move.rs4
-rw-r--r--tests/ui/moves/borrow-closures-instead-of-move.stderr16
-rw-r--r--tests/ui/moves/issue-72649-uninit-in-loop.rs8
-rw-r--r--tests/ui/moves/issue-72649-uninit-in-loop.stderr34
-rw-r--r--tests/ui/moves/issue-75904-move-closure-loop.stderr5
-rw-r--r--tests/ui/moves/move-fn-self-receiver.stderr10
-rw-r--r--tests/ui/moves/move-out-of-array-1.stderr5
-rw-r--r--tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr7
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.fixed4
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.rs4
-rw-r--r--tests/ui/moves/use_of_moved_value_copy_suggestions.stderr50
-rw-r--r--tests/ui/nll/closure-borrow-spans.stderr6
-rw-r--r--tests/ui/nll/closure-requirements/escape-upvar-nested.stderr3
-rw-r--r--tests/ui/nll/closure-requirements/escape-upvar-ref.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr2
-rw-r--r--tests/ui/nll/coroutine-distinct-lifetime.rs1
-rw-r--r--tests/ui/nll/coroutine-upvar-mutability.rs2
-rw-r--r--tests/ui/nll/coroutine-upvar-mutability.stderr4
-rw-r--r--tests/ui/nll/extra-unused-mut.rs6
-rw-r--r--tests/ui/nll/issue-21232-partial-init-and-use.stderr10
-rw-r--r--tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed23
-rw-r--r--tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs6
-rw-r--r--tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr16
-rw-r--r--tests/ui/nll/issue-27282-mutation-in-guard.stderr8
-rw-r--r--tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr2
-rw-r--r--tests/ui/nll/issue-48623-coroutine.rs2
-rw-r--r--tests/ui/nll/issue-48623-coroutine.stderr6
-rw-r--r--tests/ui/nll/issue-55850.rs2
-rw-r--r--tests/ui/nll/match-guards-always-borrow.fixed66
-rw-r--r--tests/ui/nll/match-guards-always-borrow.rs6
-rw-r--r--tests/ui/nll/match-guards-always-borrow.stderr20
-rw-r--r--tests/ui/nll/move-errors.stderr30
-rw-r--r--tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr2
-rw-r--r--tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr2
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-1.stderr4
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-2.stderr4
-rw-r--r--tests/ui/packed/packed-struct-drop-aligned.rs10
-rw-r--r--tests/ui/parser/bad-let-else-statement.rs1
-rw-r--r--tests/ui/parser/bad-let-else-statement.stderr76
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr10
-rw-r--r--tests/ui/polymorphization/coroutine.rs6
-rw-r--r--tests/ui/polymorphization/coroutine.stderr6
-rw-r--r--tests/ui/print_type_sizes/coroutine.rs1
-rw-r--r--tests/ui/print_type_sizes/coroutine.stdout2
-rw-r--r--tests/ui/print_type_sizes/coroutine_discr_placement.rs5
-rw-r--r--tests/ui/print_type_sizes/coroutine_discr_placement.stdout2
-rw-r--r--tests/ui/regions/regions-addr-of-upvar-self.stderr2
-rw-r--r--tests/ui/regions/regions-nested-fns-2.stderr3
-rw-r--r--tests/ui/regions/regions-nested-fns.stderr3
-rw-r--r--tests/ui/regions/regions-steal-closure.stderr1
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs6
-rw-r--r--tests/ui/sanitizer/cfi-coroutine.rs4
-rw-r--r--tests/ui/simd/const-err-trumps-simd-err.rs2
-rw-r--r--tests/ui/simd/intrinsic/generic-elements-pass.rs1
-rw-r--r--tests/ui/span/send-is-not-static-ensures-scoping.stderr3
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.rs2
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.stderr8
-rw-r--r--tests/ui/suggestions/option-content-move2.rs14
-rw-r--r--tests/ui/suggestions/option-content-move2.stderr21
-rw-r--r--tests/ui/suggestions/option-content-move3.rs30
-rw-r--r--tests/ui/suggestions/option-content-move3.stderr95
-rw-r--r--tests/ui/suggestions/unnamable-types.rs4
-rw-r--r--tests/ui/suggestions/unnamable-types.stderr10
-rw-r--r--tests/ui/traits/next-solver/coroutine.fail.stderr54
-rw-r--r--tests/ui/traits/next-solver/coroutine.rs26
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-94429.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-94429.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr7
-rw-r--r--tests/ui/union/union-borrow-move-parent-sibling.stderr5
-rw-r--r--tests/ui/union/union-move.stderr10
-rw-r--r--tests/ui/unop-move-semantics.stderr34
-rw-r--r--tests/ui/variance/variance-issue-20533.stderr15
-rw-r--r--tests/ui/weird-exprs.rs1
539 files changed, 4084 insertions, 2769 deletions
diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md
index 5f17f30b3b0..59862893611 100644
--- a/.github/ISSUE_TEMPLATE/tracking_issue.md
+++ b/.github/ISSUE_TEMPLATE/tracking_issue.md
@@ -28,6 +28,8 @@ Tracking issues are used to record the overall progress of implementation.
 They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
 A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature.
 Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
+Discussion comments will get marked as off-topic or deleted.
+Repeated discussions on the tracking issue may lead to the tracking issue getting locked.
 
 ### Steps
 <!--
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 90269f56c52..872b671b031 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -45,575 +45,25 @@ jobs:
       - name: Checkout the source code
         uses: actions/checkout@v4
       - name: Calculate the CI job matrix
-        run: python3 src/ci/scripts/calculate-job-matrix.py >> $GITHUB_OUTPUT
+        run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT
         id: jobs
-  pr:
-    name: "PR - ${{ matrix.name }}"
+  job:
+    name: "${{ matrix.name }}"
     needs:
       - calculate_matrix
     env:
-      PR_CI_JOB: 1
-      CI_JOB_NAME: "${{ matrix.name }}"
+      CI_JOB_NAME: "${{ matrix.image }}"
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
       DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       SCCACHE_BUCKET: rust-lang-ci-sccache2
       TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
       CACHE_DOMAIN: ci-caches.rust-lang.org
-    if: "github.event_name == 'pull_request'"
-    continue-on-error: "${{ matrix.name == 'mingw-check-tidy' }}"
+    continue-on-error: "${{ matrix.continue_on_error || false }}"
     strategy:
       matrix:
         include: "${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}"
-    defaults:
-      run:
-        shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}"
-    timeout-minutes: 600
-    runs-on: "${{ matrix.os }}"
-    steps:
-      - if: "contains(matrix.os, 'windows')"
-        uses: msys2/setup-msys2@v2.22.0
-        with:
-          msystem: "${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}"
-          update: false
-          release: true
-          path-type: inherit
-          install: "make dos2unix diffutils\n"
-      - name: disable git crlf conversion
-        run: git config --global core.autocrlf false
-      - name: checkout the source code
-        uses: actions/checkout@v4
-        with:
-          fetch-depth: 2
-      - name: configure the PR in which the error message will be posted
-        run: "echo \"[CI_PR_NUMBER=$num]\""
-        env:
-          num: "${{ github.event.number }}"
-        if: "success() && !env.SKIP_JOB && github.event_name == 'pull_request'"
-      - name: add extra environment variables
-        run: src/ci/scripts/setup-environment.sh
-        env:
-          EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
-        if: success() && !env.SKIP_JOB
-      - name: decide whether to skip this job
-        run: src/ci/scripts/should-skip-this.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure the channel matches the target branch
-        run: src/ci/scripts/verify-channel.sh
-        if: success() && !env.SKIP_JOB
-      - name: collect CPU statistics
-        run: src/ci/scripts/collect-cpu-stats.sh
-        if: success() && !env.SKIP_JOB
-      - name: show the current environment
-        run: src/ci/scripts/dump-environment.sh
-        if: success() && !env.SKIP_JOB
-      - name: install awscli
-        run: src/ci/scripts/install-awscli.sh
-        if: success() && !env.SKIP_JOB
-      - name: install sccache
-        run: src/ci/scripts/install-sccache.sh
-        if: success() && !env.SKIP_JOB
-      - name: select Xcode
-        run: src/ci/scripts/select-xcode.sh
-        if: success() && !env.SKIP_JOB
-      - name: install clang
-        run: src/ci/scripts/install-clang.sh
-        if: success() && !env.SKIP_JOB
-      - name: install tidy
-        run: src/ci/scripts/install-tidy.sh
-        if: success() && !env.SKIP_JOB
-      - name: install WIX
-        run: src/ci/scripts/install-wix.sh
-        if: success() && !env.SKIP_JOB
-      - name: disable git crlf conversion
-        run: src/ci/scripts/disable-git-crlf-conversion.sh
-        if: success() && !env.SKIP_JOB
-      - name: checkout submodules
-        run: src/ci/scripts/checkout-submodules.sh
-        if: success() && !env.SKIP_JOB
-      - name: install MSYS2
-        run: src/ci/scripts/install-msys2.sh
-        if: success() && !env.SKIP_JOB
-      - name: install MinGW
-        run: src/ci/scripts/install-mingw.sh
-        if: success() && !env.SKIP_JOB
-      - name: install ninja
-        run: src/ci/scripts/install-ninja.sh
-        if: success() && !env.SKIP_JOB
-      - name: enable ipv6 on Docker
-        run: src/ci/scripts/enable-docker-ipv6.sh
-        if: success() && !env.SKIP_JOB
-      - name: disable git crlf conversion
-        run: src/ci/scripts/disable-git-crlf-conversion.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure line endings are correct
-        run: src/ci/scripts/verify-line-endings.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure backported commits are in upstream branches
-        run: src/ci/scripts/verify-backported-commits.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure the stable version number is correct
-        run: src/ci/scripts/verify-stable-version-number.sh
-        if: success() && !env.SKIP_JOB
-      - name: run the build
-        run: src/ci/scripts/run-build-from-ci.sh 2>&1
-        env:
-          AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
-          AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
-          TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
-        if: success() && !env.SKIP_JOB
-      - name: create github artifacts
-        run: src/ci/scripts/create-doc-artifacts.sh
-        if: success() && !env.SKIP_JOB
-      - name: upload artifacts to github
-        uses: actions/upload-artifact@v4
-        with:
-          name: "${{ env.DOC_ARTIFACT_NAME }}"
-          path: obj/artifacts/doc
-          if-no-files-found: ignore
-          retention-days: 5
-        if: success() && !env.SKIP_JOB
-      - name: upload artifacts to S3
-        run: src/ci/scripts/upload-artifacts.sh
-        env:
-          AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
-          AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
-        if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
-  auto:
-    name: "auto - ${{ matrix.name }}"
-    env:
-      CI_JOB_NAME: "${{ matrix.name }}"
-      CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
-      HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
-      DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-      SCCACHE_BUCKET: rust-lang-ci-sccache2
-      DEPLOY_BUCKET: rust-lang-ci2
-      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
-      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
-      TOOLSTATE_PUBLISH: 1
-      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
-      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
-      AWS_REGION: us-west-1
-      CACHE_DOMAIN: ci-caches.rust-lang.org
-    if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
-    strategy:
-      matrix:
-        include:
-          - name: aarch64-gnu
-            os:
-              - self-hosted
-              - ARM64
-              - linux
-          - name: arm-android
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: armhf-gnu
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-aarch64-linux
-            env:
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: ubuntu-20.04-8core-32gb
-          - name: dist-android
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-arm-linux
-            os: ubuntu-20.04-16core-64gb
-            env: {}
-          - name: dist-armhf-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-armv7-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-i586-gnu-i586-i686-musl
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-i686-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-loongarch64-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-ohos
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-powerpc-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-powerpc64-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-powerpc64le-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-riscv64-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-s390x-linux
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-various-1
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-various-2
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-x86_64-freebsd
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-x86_64-illumos
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: dist-x86_64-linux
-            env:
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: ubuntu-20.04-16core-64gb
-          - name: dist-x86_64-linux-alt
-            env:
-              IMAGE: dist-x86_64-linux
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: ubuntu-20.04-16core-64gb
-          - name: dist-x86_64-musl
-            env:
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: ubuntu-20.04-8core-32gb
-          - name: dist-x86_64-netbsd
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: i686-gnu
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: i686-gnu-nopt
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: mingw-check
-            os: ubuntu-20.04-4core-16gb
-            env: {}
-          - name: test-various
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: x86_64-gnu
-            os: ubuntu-20.04-4core-16gb
-            env: {}
-          - name: x86_64-gnu-stable
-            env:
-              IMAGE: x86_64-gnu
-              RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
-              CI_ONLY_WHEN_CHANNEL: nightly
-            os: ubuntu-20.04-4core-16gb
-          - name: x86_64-gnu-aux
-            os: ubuntu-20.04-4core-16gb
-            env: {}
-          - name: x86_64-gnu-integration
-            env:
-              CI_ONLY_WHEN_CHANNEL: nightly
-            os: ubuntu-20.04-8core-32gb
-          - name: x86_64-gnu-debug
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: x86_64-gnu-distcheck
-            os: ubuntu-20.04-8core-32gb
-            env: {}
-          - name: x86_64-gnu-llvm-18
-            env:
-              RUST_BACKTRACE: 1
-            os: ubuntu-20.04-8core-32gb
-          - name: x86_64-gnu-llvm-17
-            env:
-              RUST_BACKTRACE: 1
-            os: ubuntu-20.04-8core-32gb
-          - name: x86_64-gnu-nopt
-            os: ubuntu-20.04-4core-16gb
-            env: {}
-          - name: x86_64-gnu-tools
-            env:
-              DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
-            os: ubuntu-20.04-8core-32gb
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
-              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: macos-13
-          - name: dist-apple-various
-            env:
-              SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
-              RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-13
-          - name: x86_64-apple-1
-            env:
-              SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps"
-              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-13
-          - name: x86_64-apple-2
-            env:
-              SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
-              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-13
-          - name: dist-aarch64-apple
-            env:
-              SCRIPT: "./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin"
-              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              USE_XCODE_CLANG: 1
-              MACOSX_DEPLOYMENT_TARGET: 11.0
-              MACOSX_STD_DEPLOYMENT_TARGET: 11.0
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: macos-14
-          - name: aarch64-apple
-            env:
-              SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin"
-              RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              USE_XCODE_CLANG: 1
-              MACOSX_DEPLOYMENT_TARGET: 11.0
-              MACOSX_STD_DEPLOYMENT_TARGET: 11.0
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-14
-          - name: x86_64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
-              SCRIPT: make ci-msvc
-            os: windows-2019-8core-32gb
-          - name: i686-msvc
-            env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc"
-              SCRIPT: make ci-msvc
-            os: windows-2019-8core-32gb
-          - name: x86_64-msvc-ext
-            env:
-              SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
-              HOST_TARGET: x86_64-pc-windows-msvc
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json"
-              DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
-            os: windows-2019-8core-32gb
-          - name: i686-mingw
-            env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu"
-              SCRIPT: make ci-mingw
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-            os: windows-2019-8core-32gb
-          - name: x86_64-mingw
-            env:
-              SCRIPT: make ci-mingw
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler"
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-            os: windows-2019-8core-32gb
-          - name: dist-x86_64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.codegen-units=1"
-              SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: windows-2019-8core-32gb
-          - name: dist-i686-msvc
-            env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler"
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: windows-2019-8core-32gb
-          - name: dist-aarch64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: windows-2019-8core-32gb
-          - name: dist-i686-mingw
-            env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler"
-              NO_DOWNLOAD_CI_LLVM: 1
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              CUSTOM_MINGW: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: windows-2019-8core-32gb
-          - name: dist-x86_64-mingw
-            env:
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler"
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: windows-2019-8core-32gb
-          - name: dist-x86_64-msvc-alt
-            env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler"
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-            os: windows-2019-8core-32gb
-    defaults:
-      run:
-        shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}"
-    timeout-minutes: 600
-    runs-on: "${{ matrix.os }}"
-    steps:
-      - if: "contains(matrix.os, 'windows')"
-        uses: msys2/setup-msys2@v2.22.0
-        with:
-          msystem: "${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}"
-          update: false
-          release: true
-          path-type: inherit
-          install: "make dos2unix diffutils\n"
-      - name: disable git crlf conversion
-        run: git config --global core.autocrlf false
-      - name: checkout the source code
-        uses: actions/checkout@v4
-        with:
-          fetch-depth: 2
-      - name: configure the PR in which the error message will be posted
-        run: "echo \"[CI_PR_NUMBER=$num]\""
-        env:
-          num: "${{ github.event.number }}"
-        if: "success() && !env.SKIP_JOB && github.event_name == 'pull_request'"
-      - name: add extra environment variables
-        run: src/ci/scripts/setup-environment.sh
-        env:
-          EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
-        if: success() && !env.SKIP_JOB
-      - name: decide whether to skip this job
-        run: src/ci/scripts/should-skip-this.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure the channel matches the target branch
-        run: src/ci/scripts/verify-channel.sh
-        if: success() && !env.SKIP_JOB
-      - name: collect CPU statistics
-        run: src/ci/scripts/collect-cpu-stats.sh
-        if: success() && !env.SKIP_JOB
-      - name: show the current environment
-        run: src/ci/scripts/dump-environment.sh
-        if: success() && !env.SKIP_JOB
-      - name: install awscli
-        run: src/ci/scripts/install-awscli.sh
-        if: success() && !env.SKIP_JOB
-      - name: install sccache
-        run: src/ci/scripts/install-sccache.sh
-        if: success() && !env.SKIP_JOB
-      - name: select Xcode
-        run: src/ci/scripts/select-xcode.sh
-        if: success() && !env.SKIP_JOB
-      - name: install clang
-        run: src/ci/scripts/install-clang.sh
-        if: success() && !env.SKIP_JOB
-      - name: install tidy
-        run: src/ci/scripts/install-tidy.sh
-        if: success() && !env.SKIP_JOB
-      - name: install WIX
-        run: src/ci/scripts/install-wix.sh
-        if: success() && !env.SKIP_JOB
-      - name: disable git crlf conversion
-        run: src/ci/scripts/disable-git-crlf-conversion.sh
-        if: success() && !env.SKIP_JOB
-      - name: checkout submodules
-        run: src/ci/scripts/checkout-submodules.sh
-        if: success() && !env.SKIP_JOB
-      - name: install MSYS2
-        run: src/ci/scripts/install-msys2.sh
-        if: success() && !env.SKIP_JOB
-      - name: install MinGW
-        run: src/ci/scripts/install-mingw.sh
-        if: success() && !env.SKIP_JOB
-      - name: install ninja
-        run: src/ci/scripts/install-ninja.sh
-        if: success() && !env.SKIP_JOB
-      - name: enable ipv6 on Docker
-        run: src/ci/scripts/enable-docker-ipv6.sh
-        if: success() && !env.SKIP_JOB
-      - name: disable git crlf conversion
-        run: src/ci/scripts/disable-git-crlf-conversion.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure line endings are correct
-        run: src/ci/scripts/verify-line-endings.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure backported commits are in upstream branches
-        run: src/ci/scripts/verify-backported-commits.sh
-        if: success() && !env.SKIP_JOB
-      - name: ensure the stable version number is correct
-        run: src/ci/scripts/verify-stable-version-number.sh
-        if: success() && !env.SKIP_JOB
-      - name: run the build
-        run: src/ci/scripts/run-build-from-ci.sh 2>&1
-        env:
-          AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
-          AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
-          TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
-        if: success() && !env.SKIP_JOB
-      - name: create github artifacts
-        run: src/ci/scripts/create-doc-artifacts.sh
-        if: success() && !env.SKIP_JOB
-      - name: upload artifacts to github
-        uses: actions/upload-artifact@v4
-        with:
-          name: "${{ env.DOC_ARTIFACT_NAME }}"
-          path: obj/artifacts/doc
-          if-no-files-found: ignore
-          retention-days: 5
-        if: success() && !env.SKIP_JOB
-      - name: upload artifacts to S3
-        run: src/ci/scripts/upload-artifacts.sh
-        env:
-          AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
-          AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
-        if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
-  try:
-    name: "try - ${{ matrix.name }}"
-    env:
-      DIST_TRY_BUILD: 1
-      CI_JOB_NAME: "${{ matrix.name }}"
-      CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
-      HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
-      DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-      SCCACHE_BUCKET: rust-lang-ci-sccache2
-      DEPLOY_BUCKET: rust-lang-ci2
-      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
-      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
-      TOOLSTATE_PUBLISH: 1
-      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
-      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
-      AWS_REGION: us-west-1
-      CACHE_DOMAIN: ci-caches.rust-lang.org
-    if: "github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))"
-    strategy:
-      matrix:
-        include:
-          - name: dist-x86_64-linux
-            env:
-              CODEGEN_BACKENDS: "llvm,cranelift"
-            os: ubuntu-20.04-16core-64gb
+    if: "fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null"
     defaults:
       run:
         shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}"
@@ -755,7 +205,7 @@ jobs:
         if: success() && !env.SKIP_JOB
   try-success:
     needs:
-      - try
+      - job
     if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a success
@@ -765,7 +215,7 @@ jobs:
     runs-on: ubuntu-latest
   try-failure:
     needs:
-      - try
+      - job
     if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a failure
@@ -775,7 +225,7 @@ jobs:
     runs-on: ubuntu-latest
   auto-success:
     needs:
-      - auto
+      - job
     if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a success
@@ -785,7 +235,7 @@ jobs:
     runs-on: ubuntu-latest
   auto-failure:
     needs:
-      - auto
+      - job
     if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a failure
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index bddb50568d4..727c6bc82fe 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3112,6 +3112,7 @@ pub struct Delegation {
     /// Path resolution id.
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
+    pub rename: Option<Ident>,
     pub path: Path,
     pub body: Option<P<Block>>,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index c4e49d7dbea..7dbfb7c7364 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1149,10 +1149,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         }
         ItemKind::MacCall(m) => vis.visit_mac_call(m),
         ItemKind::MacroDef(def) => vis.visit_macro_def(def),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             vis.visit_id(id);
             vis.visit_qself(qself);
             vis.visit_path(path);
+            if let Some(rename) = rename {
+                vis.visit_ident(rename);
+            }
             if let Some(body) = body {
                 vis.visit_block(body);
             }
@@ -1195,10 +1198,13 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
         AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             visitor.visit_id(id);
             visitor.visit_qself(qself);
             visitor.visit_path(path);
+            if let Some(rename) = rename {
+                visitor.visit_ident(rename);
+            }
             if let Some(body) = body {
                 visitor.visit_block(body);
             }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 968d10ad487..d9740928f8d 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -382,11 +382,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu
         }
         ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
         ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
@@ -782,11 +783,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
         AssocItemKind::MacCall(mac) => {
             try_visit!(visitor.visit_mac_call(mac));
         }
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index a23e714ef01..73001c9990c 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign =
     .label = `_` not allowed here
 
 ast_lowering_use_angle_brackets = use angle brackets instead
+ast_lowering_yield_in_closure =
+    `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+    .suggestion = use `#[coroutine]` to make this closure a coroutine
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f4d5e71bade..a1e5c275c18 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -49,7 +49,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::ResolverAstLowering;
+use rustc_middle::ty::{Asyncness, ResolverAstLowering};
 use rustc_span::{symbol::Ident, Span};
 use rustc_target::spec::abi;
 use std::iter;
@@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return false;
         };
         if let Some(local_sig_id) = sig_id.as_local() {
-            self.resolver.has_self.contains(&local_sig_id)
+            self.resolver.delegation_fn_sigs[&local_sig_id].has_self
         } else {
             match self.tcx.def_kind(sig_id) {
                 DefKind::Fn => false,
@@ -82,13 +82,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         delegation: &Delegation,
         item_id: NodeId,
     ) -> DelegationResults<'hir> {
-        let span = delegation.path.segments.last().unwrap().ident.span;
+        let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
         let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
         match sig_id {
             Ok(sig_id) => {
-                let decl = self.lower_delegation_decl(sig_id, span);
-                let sig = self.lower_delegation_sig(span, decl);
-                let body_id = self.lower_delegation_body(sig.decl, delegation);
+                let (param_count, c_variadic) = self.param_count(sig_id);
+                let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
+                let sig = self.lower_delegation_sig(sig_id, decl, span);
+                let body_id = self.lower_delegation_body(delegation, param_count, span);
 
                 let generics = self.lower_delegation_generics(span);
                 DelegationResults { body_id, sig, generics }
@@ -123,34 +124,47 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    // Function parameter count, including C variadic `...` if present.
+    fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
+        if let Some(local_sig_id) = sig_id.as_local() {
+            // Map may be filled incorrectly due to recursive delegation.
+            // Error will be emmited later during HIR ty lowering.
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => (sig.param_count, sig.c_variadic),
+                None => (0, false),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            (sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
+        }
+    }
+
     fn lower_delegation_decl(
         &mut self,
         sig_id: DefId,
-        param_span: Span,
+        param_count: usize,
+        c_variadic: bool,
+        span: Span,
     ) -> &'hir hir::FnDecl<'hir> {
-        let args_count = if let Some(local_sig_id) = sig_id.as_local() {
-            // Map may be filled incorrectly due to recursive delegation.
-            // Error will be emitted later during HIR ty lowering.
-            self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
-        } else {
-            self.tcx.fn_arg_names(sig_id).len()
-        };
-        let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty {
+        // The last parameter in C variadic functions is skipped in the signature,
+        // like during regular lowering.
+        let decl_param_count = param_count - c_variadic as usize;
+        let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
-            span: self.lower_span(param_span),
+            span,
         }));
 
         let output = self.arena.alloc(hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
-            span: self.lower_span(param_span),
+            span,
         });
 
         self.arena.alloc(hir::FnDecl {
             inputs,
             output: hir::FnRetTy::Return(output),
-            c_variadic: false,
+            c_variadic,
             lifetime_elision_allowed: true,
             implicit_self: hir::ImplicitSelfKind::None,
         })
@@ -158,35 +172,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_delegation_sig(
         &mut self,
-        span: Span,
+        sig_id: DefId,
         decl: &'hir hir::FnDecl<'hir>,
+        span: Span,
     ) -> hir::FnSig<'hir> {
-        hir::FnSig {
-            decl,
-            header: hir::FnHeader {
-                unsafety: hir::Unsafety::Normal,
-                constness: hir::Constness::NotConst,
-                asyncness: hir::IsAsync::NotAsync,
-                abi: abi::Abi::Rust,
-            },
-            span: self.lower_span(span),
-        }
+        let header = if let Some(local_sig_id) = sig_id.as_local() {
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => self.lower_fn_header(sig.header),
+                None => self.generate_header_error(),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            let asyncness = match self.tcx.asyncness(sig_id) {
+                Asyncness::Yes => hir::IsAsync::Async(span),
+                Asyncness::No => hir::IsAsync::NotAsync,
+            };
+            hir::FnHeader {
+                unsafety: sig.unsafety,
+                constness: self.tcx.constness(sig_id),
+                asyncness,
+                abi: sig.abi,
+            }
+        };
+        hir::FnSig { decl, header, span }
     }
 
-    fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
+    fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) {
         let pat_node_id = self.next_node_id();
         let pat_id = self.lower_node_id(pat_node_id);
         let pat = self.arena.alloc(hir::Pat {
             hir_id: pat_id,
             kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
-            span: ty.span,
+            span,
             default_binding_modes: false,
         });
 
-        (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
+        (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
     }
 
-    fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
+    fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
         let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
             ident: Ident::empty(),
             hir_id: self.next_id(),
@@ -195,20 +219,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
             infer_args: false,
         }));
 
-        let path =
-            self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
+        let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
 
         hir::Expr {
             hir_id: self.next_id(),
             kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
-            span: ty.span,
+            span,
         }
     }
 
     fn lower_delegation_body(
         &mut self,
-        decl: &'hir hir::FnDecl<'hir>,
         delegation: &Delegation,
+        param_count: usize,
+        span: Span,
     ) -> BodyId {
         let path = self.lower_qpath(
             delegation.id,
@@ -224,8 +248,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let mut parameters: Vec<hir::Param<'_>> = Vec::new();
             let mut args: Vec<hir::Expr<'hir>> = Vec::new();
 
-            for (idx, param_ty) in decl.inputs.iter().enumerate() {
-                let (param, pat_node_id) = this.generate_param(param_ty);
+            for idx in 0..param_count {
+                let (param, pat_node_id) = this.generate_param(span);
                 parameters.push(param);
 
                 let arg = if let Some(block) = block
@@ -245,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 } else {
                     let pat_hir_id = this.lower_node_id(pat_node_id);
-                    this.generate_arg(param_ty, pat_hir_id)
+                    this.generate_arg(pat_hir_id, span)
                 };
                 args.push(arg);
             }
@@ -304,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             implicit_self: hir::ImplicitSelfKind::None,
         });
 
-        let sig = self.lower_delegation_sig(span, decl);
+        let header = self.generate_header_error();
+        let sig = hir::FnSig { decl, header, span };
+
         let body_id = self.lower_body(|this| {
             let expr =
                 hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
@@ -312,6 +338,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         });
         DelegationResults { generics, body_id, sig }
     }
+
+    fn generate_header_error(&self) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: hir::Unsafety::Normal,
+            constness: hir::Constness::NotConst,
+            asyncness: hir::IsAsync::NotAsync,
+            abi: abi::Abi::Rust,
+        }
+    }
 }
 
 struct SelfResolver<'a> {
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 6799513a323..6f70e135c72 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_yield_in_closure)]
+pub(crate) struct YieldInClosure {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
+    pub suggestion: Option<Span>,
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2305cc07795..5cc05d7336e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -8,6 +8,7 @@ use super::errors::{
 };
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use crate::errors::YieldInClosure;
 use crate::{FnDeclKind, ImplTraitPosition};
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
@@ -217,6 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         binder,
                         *capture_clause,
                         e.id,
+                        hir_id,
                         *constness,
                         *movability,
                         fn_decl,
@@ -955,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         constness: Const,
         movability: Movability,
         decl: &FnDecl,
@@ -965,8 +968,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
         let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
-            let mut coroutine_kind = None;
+            let mut coroutine_kind = if this
+                .attrs
+                .get(&closure_hir_id.local_id)
+                .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
+            {
+                Some(hir::CoroutineKind::Coroutine(Movability::Movable))
+            } else {
+                None
+            };
             let body_id = this.lower_fn_body(decl, |this| {
+                this.coroutine_kind = coroutine_kind;
                 let e = this.lower_expr_mut(body);
                 coroutine_kind = this.coroutine_kind;
                 e
@@ -1565,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     )
                     .emit();
                 }
+                let suggestion = self.current_item.map(|s| s.shrink_to_lo());
+                self.dcx().emit_err(YieldInClosure { span, suggestion });
                 self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
+
                 false
             }
         };
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e4c633aa324..dcce54d66c2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 body,
                 ..
             }) => {
-                self.with_new_scopes(ident.span, |this| {
+                self.with_new_scopes(*fn_sig_span, |this| {
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
@@ -1344,7 +1344,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
             hir::IsAsync::Async(span)
         } else {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 70a3ccb0f44..d86196cbaa9 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -556,7 +556,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         half_open_range_patterns_in_slices,
         "half-open range patterns in slices are unstable"
     );
-    gate_all!(inline_const, "inline-const is experimental");
     gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
     gate_all!(associated_const_equality, "associated const equality is incomplete");
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 4878da530b0..93ea8fb6979 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -347,7 +347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         mpi: MovePathIndex,
         err: &mut Diag<'tcx>,
         in_pattern: &mut bool,
-        move_spans: UseSpans<'_>,
+        move_spans: UseSpans<'tcx>,
     ) {
         let move_span = match move_spans {
             UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
@@ -491,11 +491,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     ..
                 } = move_spans
                 {
-                    self.suggest_cloning(err, ty, expr, None);
+                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 } else if self.suggest_hoisting_call_outside_loop(err, expr) {
                     // The place where the the type moves would be misleading to suggest clone.
                     // #121466
-                    self.suggest_cloning(err, ty, expr, None);
+                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 }
             }
             if let Some(pat) = finder.pat {
@@ -1085,6 +1085,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         ty: Ty<'tcx>,
         mut expr: &'cx hir::Expr<'cx>,
         mut other_expr: Option<&'cx hir::Expr<'cx>>,
+        use_spans: Option<UseSpans<'tcx>>,
     ) {
         if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
             // We have `S { foo: val, ..base }`. In `check_aggregate_rvalue` we have a single
@@ -1197,14 +1198,50 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     .all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
             })
         {
+            let ty_span = self.infcx.tcx.def_span(def.did());
+            let mut span: MultiSpan = ty_span.into();
+            span.push_span_label(ty_span, "consider implementing `Clone` for this type");
+            span.push_span_label(expr.span, "you could clone this value");
             err.span_note(
-                self.infcx.tcx.def_span(def.did()),
+                span,
+                format!("if `{ty}` implemented `Clone`, you could clone the value"),
+            );
+        } else if let ty::Param(param) = ty.kind()
+            && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
+            && let generics = self.infcx.tcx.generics_of(self.mir_def_id())
+            && let generic_param = generics.type_param(*param, self.infcx.tcx)
+            && let param_span = self.infcx.tcx.def_span(generic_param.def_id)
+            && if let Some(UseSpans::FnSelfUse { kind, .. }) = use_spans
+                && let CallKind::FnCall { fn_trait_id, self_ty } = kind
+                && let ty::Param(_) = self_ty.kind()
+                && ty == self_ty
+                && [
+                    self.infcx.tcx.lang_items().fn_once_trait(),
+                    self.infcx.tcx.lang_items().fn_mut_trait(),
+                    self.infcx.tcx.lang_items().fn_trait(),
+                ]
+                .contains(&Some(fn_trait_id))
+            {
+                // Do not suggest `F: FnOnce() + Clone`.
+                false
+            } else {
+                true
+            }
+        {
+            let mut span: MultiSpan = param_span.into();
+            span.push_span_label(
+                param_span,
+                "consider constraining this type parameter with `Clone`",
+            );
+            span.push_span_label(expr.span, "you could clone this value");
+            err.span_help(
+                span,
                 format!("if `{ty}` implemented `Clone`, you could clone the value"),
             );
         }
     }
 
-    fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
+    pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
         let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
         self.infcx
             .type_implements_trait(clone_trait_def, [ty], self.param_env)
@@ -1403,7 +1440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let Some(expr) = self.find_expr(borrow_span)
             && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
         {
-            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span));
+            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
         }
         self.buffer_error(err);
     }
@@ -1964,7 +2001,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> {
         let tcx = self.infcx.tcx;
         let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
-        let mut expr_finder = FindExprBySpan::new(span);
+        let mut expr_finder = FindExprBySpan::new(span, tcx);
         expr_finder.visit_expr(tcx.hir().body(body_id).value);
         expr_finder.result
     }
@@ -1998,14 +2035,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             };
 
             let mut expr_finder =
-                FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
+                FindExprBySpan::new(self.body.local_decls[*index1].source_info.span, tcx);
             expr_finder.visit_expr(hir.body(body_id).value);
             let Some(index1) = expr_finder.result else {
                 note_default_suggestion();
                 return;
             };
 
-            expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
+            expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span, tcx);
             expr_finder.visit_expr(hir.body(body_id).value);
             let Some(index2) = expr_finder.result else {
                 note_default_suggestion();
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 418eabe3ae2..5ebdb69050b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -76,7 +76,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 && let Some(body_id) = node.body_id()
             {
                 let body = tcx.hir().body(body_id);
-                let mut expr_finder = FindExprBySpan::new(span);
+                let mut expr_finder = FindExprBySpan::new(span, tcx);
                 expr_finder.visit_expr(body.value);
                 if let Some(mut expr) = expr_finder.result {
                     while let hir::ExprKind::AddrOf(_, _, inner)
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index bc02c5be93d..288b846daf5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -2,10 +2,13 @@
 #![allow(rustc::untranslatable_diagnostic)]
 
 use rustc_errors::{Applicability, Diag};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{CaptureBy, ExprKind, HirId, Node};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
 use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
+use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
 
 use crate::diagnostics::CapturedMessageOpt;
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
@@ -303,6 +306,121 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         self.cannot_move_out_of(span, &description)
     }
 
+    fn suggest_clone_of_captured_var_in_move_closure(
+        &self,
+        err: &mut Diag<'_>,
+        upvar_hir_id: HirId,
+        upvar_name: &str,
+        use_spans: Option<UseSpans<'tcx>>,
+    ) {
+        let tcx = self.infcx.tcx;
+        let typeck_results = tcx.typeck(self.mir_def_id());
+        let Some(use_spans) = use_spans else { return };
+        // We only care about the case where a closure captured a binding.
+        let UseSpans::ClosureUse { args_span, .. } = use_spans else { return };
+        let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
+        // Fetch the type of the expression corresponding to the closure-captured binding.
+        let Some(captured_ty) = typeck_results.node_type_opt(upvar_hir_id) else { return };
+        if !self.implements_clone(captured_ty) {
+            // We only suggest cloning the captured binding if the type can actually be cloned.
+            return;
+        };
+        // Find the closure that captured the binding.
+        let mut expr_finder = FindExprBySpan::new(args_span, tcx);
+        expr_finder.include_closures = true;
+        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        let Some(closure_expr) = expr_finder.result else { return };
+        let ExprKind::Closure(closure) = closure_expr.kind else { return };
+        // We'll only suggest cloning the binding if it's a `move` closure.
+        let CaptureBy::Value { .. } = closure.capture_clause else { return };
+        // Find the expression within the closure where the binding is consumed.
+        let mut suggested = false;
+        let use_span = use_spans.var_or_use();
+        let mut expr_finder = FindExprBySpan::new(use_span, tcx);
+        expr_finder.include_closures = true;
+        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        let Some(use_expr) = expr_finder.result else { return };
+        let parent = tcx.parent_hir_node(use_expr.hir_id);
+        if let Node::Expr(expr) = parent
+            && let ExprKind::Assign(lhs, ..) = expr.kind
+            && lhs.hir_id == use_expr.hir_id
+        {
+            // Cloning the value being assigned makes no sense:
+            //
+            // error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+            //   --> $DIR/option-content-move2.rs:11:9
+            //    |
+            // LL |     let mut var = None;
+            //    |         ------- captured outer variable
+            // LL |     func(|| {
+            //    |          -- captured by this `FnMut` closure
+            // LL |         // Shouldn't suggest `move ||.as_ref()` here
+            // LL |         move || {
+            //    |         ^^^^^^^ `var` is moved here
+            // LL |
+            // LL |             var = Some(NotCopyable);
+            //    |             ---
+            //    |             |
+            //    |             variable moved due to use in closure
+            //    |             move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
+            //    |
+            return;
+        }
+
+        // Search for an appropriate place for the structured `.clone()` suggestion to be applied.
+        // If we encounter a statement before the borrow error, we insert a statement there.
+        for (_, node) in tcx.hir().parent_iter(closure_expr.hir_id) {
+            if let Node::Stmt(stmt) = node {
+                let padding = tcx
+                    .sess
+                    .source_map()
+                    .indentation_before(stmt.span)
+                    .unwrap_or_else(|| "    ".to_string());
+                err.multipart_suggestion_verbose(
+                    "clone the value before moving it into the closure",
+                    vec![
+                        (
+                            stmt.span.shrink_to_lo(),
+                            format!("let value = {upvar_name}.clone();\n{padding}"),
+                        ),
+                        (use_span, "value".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+                suggested = true;
+                break;
+            } else if let Node::Expr(expr) = node
+                && let ExprKind::Closure(_) = expr.kind
+            {
+                // We want to suggest cloning only on the first closure, not
+                // subsequent ones (like `ui/suggestions/option-content-move2.rs`).
+                break;
+            }
+        }
+        if !suggested {
+            // If we couldn't find a statement for us to insert a new `.clone()` statement before,
+            // we have a bare expression, so we suggest the creation of a new block inline to go
+            // from `move || val` to `{ let value = val.clone(); move || value }`.
+            let padding = tcx
+                .sess
+                .source_map()
+                .indentation_before(closure_expr.span)
+                .unwrap_or_else(|| "    ".to_string());
+            err.multipart_suggestion_verbose(
+                "clone the value before moving it into the closure",
+                vec![
+                    (
+                        closure_expr.span.shrink_to_lo(),
+                        format!("{{\n{padding}let value = {upvar_name}.clone();\n{padding}"),
+                    ),
+                    (use_spans.var_or_use(), "value".to_string()),
+                    (closure_expr.span.shrink_to_hi(), format!("\n{padding}}}")),
+                ],
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     fn report_cannot_move_from_borrowed_content(
         &mut self,
         move_place: Place<'tcx>,
@@ -310,10 +428,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         span: Span,
         use_spans: Option<UseSpans<'tcx>>,
     ) -> Diag<'tcx> {
+        let tcx = self.infcx.tcx;
         // Inspect the type of the content behind the
         // borrow to provide feedback about why this
         // was a move rather than a copy.
-        let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty;
+        let ty = deref_target_place.ty(self.body, tcx).ty;
         let upvar_field = self
             .prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
@@ -363,8 +482,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
                 let upvar = &self.upvars[upvar_field.unwrap().index()];
                 let upvar_hir_id = upvar.get_root_variable();
-                let upvar_name = upvar.to_string(self.infcx.tcx);
-                let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
+                let upvar_name = upvar.to_string(tcx);
+                let upvar_span = tcx.hir().span(upvar_hir_id);
 
                 let place_name = self.describe_any_place(move_place.as_ref());
 
@@ -380,12 +499,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     closure_kind_ty, closure_kind, place_description,
                 );
 
-                self.cannot_move_out_of(span, &place_description)
+                let closure_span = tcx.def_span(def_id);
+                let mut err = self
+                    .cannot_move_out_of(span, &place_description)
                     .with_span_label(upvar_span, "captured outer variable")
                     .with_span_label(
-                        self.infcx.tcx.def_span(def_id),
+                        closure_span,
                         format!("captured by this `{closure_kind}` closure"),
-                    )
+                    );
+                self.suggest_clone_of_captured_var_in_move_closure(
+                    &mut err,
+                    upvar_hir_id,
+                    &upvar_name,
+                    use_spans,
+                );
+                err
             }
             _ => {
                 let source = self.borrowed_content_source(deref_base);
@@ -415,7 +543,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ),
                     (_, _, _) => self.cannot_move_out_of(
                         span,
-                        &source.describe_for_unnamed_place(self.infcx.tcx),
+                        &source.describe_for_unnamed_place(tcx),
                     ),
                 }
             }
@@ -447,7 +575,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     };
 
                     if let Some(expr) = self.find_expr(span) {
-                        self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span));
+                        self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None);
                     }
 
                     err.subdiagnostic(
@@ -482,7 +610,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 };
 
                 if let Some(expr) = self.find_expr(use_span) {
-                    self.suggest_cloning(err, place_ty, expr, self.find_expr(span));
+                    self.suggest_cloning(
+                        err,
+                        place_ty,
+                        expr,
+                        self.find_expr(span),
+                        Some(use_spans),
+                    );
                 }
 
                 err.subdiagnostic(
@@ -595,7 +729,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
 
                 if let Some(expr) = self.find_expr(binding_span) {
-                    self.suggest_cloning(err, bind_to.ty, expr, None);
+                    self.suggest_cloning(err, bind_to.ty, expr, None, None);
                 }
 
                 err.subdiagnostic(
diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
index c965b34e13b..407da94c0f0 100644
--- a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
+++ b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
@@ -8,7 +8,8 @@ fn main() {
 }
 
 fn run_coroutine<T>() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine]
+    || {
         yield;
         return;
     };
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 0205de55622..90d4ab721da 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -1,6 +1,7 @@
 #![feature(
     core_intrinsics,
     coroutines,
+    stmt_expr_attributes,
     coroutine_trait,
     is_sorted,
     repr_simd,
@@ -123,9 +124,12 @@ fn main() {
         test_simd();
     }
 
-    Box::pin(move |mut _task_context| {
-        yield ();
-    })
+    Box::pin(
+        #[coroutine]
+        move |mut _task_context| {
+            yield ();
+        },
+    )
     .as_mut()
     .resume(0);
 
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index ad69409eb65..8ab8fcc525e 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -1,5 +1,5 @@
 #![allow(internal_features)]
-#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
+#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
 
 #[cfg(feature="master")]
 #[cfg(target_arch="x86_64")]
@@ -103,7 +103,7 @@ fn main() {
         test_simd();
     }
 
-    Box::pin(move |mut _task_context| {
+    Box::pin(#[coroutine] move |mut _task_context| {
         yield ();
     }).as_mut().resume(0);
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index d353704fb75..23a5e5ff873 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -898,26 +898,20 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.gcc_checked_binop(oop, typ, lhs, rhs)
     }
 
-    fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
-        // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
-        // Ideally, we shouldn't need to do this check.
-        let aligned_type = if ty == self.cx.u128_type || ty == self.cx.i128_type {
-            ty
-        } else {
-            ty.get_aligned(align.bytes())
-        };
+    fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> {
+        let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes());
         // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.
         self.stack_var_count.set(self.stack_var_count.get() + 1);
         self.current_func()
             .new_local(
                 self.location,
-                aligned_type,
+                ty,
                 &format!("stack_var_{}", self.stack_var_count.get()),
             )
             .get_address(self.location)
     }
 
-    fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
+    fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index bee6bda007c..b7aec97ad8c 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -531,7 +531,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 // We instead thus allocate some scratch space...
                 let scratch_size = cast.size(bx);
                 let scratch_align = cast.align(bx);
-                let llscratch = bx.alloca(cast.gcc_type(bx), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
 
                 // ... where we first store the value...
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 6039a4aaf01..0c7cffbe730 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -18,7 +18,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::abi::Align;
+use rustc_target::abi::{Align, Size};
 
 use crate::builder::Builder;
 #[cfg(not(feature = "master"))]
@@ -558,7 +558,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 let ze = bx.zext(result, bx.type_ix(expected_bytes * 8));
 
                 // Convert the integer to a byte array
-                let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
+                let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
                 bx.store(ze, ptr, Align::ONE);
                 let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
                 let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index c0b43b77897..aec11e9905f 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -227,7 +227,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 //   when passed by value, making it larger.
                 let copy_bytes = cmp::min(scratch_size.bytes(), self.layout.size.bytes());
                 // Allocate some scratch space...
-                let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
                 // ...store the value...
                 bx.store(val, llscratch, scratch_align);
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 4c2bdb2f5ec..f7546039540 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -468,9 +468,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         val
     }
 
-    fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
+    fn alloca(&mut self, size: Size, align: Align) -> &'ll Value {
         let mut bx = Builder::with_cx(self.cx);
         bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
+        let ty = self.cx().type_array(self.cx().type_i8(), size.bytes());
         unsafe {
             let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
@@ -478,10 +479,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn byte_array_alloca(&mut self, len: &'ll Value, align: Align) -> &'ll Value {
+    fn dynamic_alloca(&mut self, size: &'ll Value, align: Align) -> &'ll Value {
         unsafe {
             let alloca =
-                llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, UNNAMED);
+                llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
             alloca
         }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index ab9f20fdf63..41347333ea6 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
+use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 
 use std::cmp::Ordering;
@@ -649,8 +649,9 @@ fn codegen_msvc_try<'ll>(
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
+        let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(bx.type_ptr(), ptr_align);
+        let slot = bx.alloca(ptr_size, ptr_align);
         let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
         bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
 
@@ -920,15 +921,14 @@ fn codegen_emcc_try<'ll>(
 
         // We need to pass two values to catch_func (ptr and is_rust_panic), so
         // create an alloca and pass a pointer to that.
+        let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let i8_align = bx.tcx().data_layout.i8_align.abi;
-        let catch_data_type = bx.type_struct(&[bx.type_ptr(), bx.type_bool()], false);
-        let catch_data = bx.alloca(catch_data_type, ptr_align);
-        let catch_data_0 =
-            bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
-        bx.store(ptr, catch_data_0, ptr_align);
-        let catch_data_1 =
-            bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
+        // Required in order for there to be no padding between the fields.
+        assert!(i8_align <= ptr_align);
+        let catch_data = bx.alloca(2 * ptr_size, ptr_align);
+        bx.store(ptr, catch_data, ptr_align);
+        let catch_data_1 = bx.inbounds_ptradd(catch_data, bx.const_usize(ptr_size.bytes()));
         bx.store(is_rust_panic, catch_data_1, i8_align);
 
         let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
@@ -1374,7 +1374,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
 
                 // Convert the integer to a byte array
-                let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
+                let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
                 bx.store(ze, ptr, Align::ONE);
                 let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
                 return Ok(bx.load(array_ty, ptr, Align::ONE));
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 930b9b8c0db..ae7c0f24b40 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -508,7 +508,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let ptr_size = bx.tcx().data_layout.pointer_size;
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let arg_argc = bx.const_int(cx.type_isize(), 2);
-        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align);
+        let arg_argv = bx.alloca(2 * ptr_size, ptr_align);
         bx.store(param_handle, arg_argv, ptr_align);
         let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes()));
         bx.store(param_system_table, arg_argv_el1, ptr_align);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 64c13fa7c1f..d4d172c000f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1517,7 +1517,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 //   when passed by value, making it larger.
                 let copy_bytes = cmp::min(scratch_size.bytes(), arg.layout.size.bytes());
                 // Allocate some scratch space...
-                let llscratch = bx.alloca(bx.cast_backend_type(cast), scratch_align);
+                let llscratch = bx.alloca(scratch_size, scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
                 // ...memcpy the value...
                 bx.memcpy(
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9cf64e2d676..e5fd59657a4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -327,7 +327,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 let llfield_ty = bx.cx().backend_type(field);
 
                 // Can't bitcast an aggregate, so round trip through memory.
-                let llptr = bx.alloca(llfield_ty, field.align.abi);
+                let llptr = bx.alloca(field.size, field.align.abi);
                 bx.store(*llval, llptr, field.align.abi);
                 *llval = bx.load(llfield_ty, llptr, field.align.abi);
             }
@@ -470,7 +470,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
         let align_minus_1 = bx.sub(align, one);
         let size_extra = bx.add(size, align_minus_1);
         let min_align = Align::ONE;
-        let alloca = bx.byte_array_alloca(size_extra, min_align);
+        let alloca = bx.dynamic_alloca(size_extra, min_align);
         let address = bx.ptrtoint(alloca, bx.type_isize());
         let neg_address = bx.neg(address);
         let offset = bx.and(neg_address, align_minus_1);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 90627da579e..b23d0894da6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -81,7 +81,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         align: Align,
     ) -> Self {
         assert!(layout.is_sized(), "tried to statically allocate unsized place");
-        let tmp = bx.alloca(bx.cx().backend_type(layout), align);
+        let tmp = bx.alloca(layout.size, align);
         Self::new_sized_aligned(tmp, layout, align)
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 9191618c064..51b22bfaf25 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -144,8 +144,8 @@ pub trait BuilderMethods<'a, 'tcx>:
     }
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
 
-    fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
-    fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value;
+    fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
+    fn dynamic_alloca(&mut self, size: Self::Value, align: Align) -> Self::Value;
 
     fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
     fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
diff --git a/compiler/rustc_error_codes/src/error_codes/E0626.md b/compiler/rustc_error_codes/src/error_codes/E0626.md
index e2534415d83..28d543350ff 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0626.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0626.md
@@ -4,10 +4,10 @@ yield point.
 Erroneous code example:
 
 ```compile_fail,E0626
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
     let a = &String::new(); // <-- This borrow...
     yield (); // ...is still in scope here, when the yield occurs.
     println!("{}", a);
@@ -23,10 +23,10 @@ resolve the previous example by removing the borrow and just storing
 the integer by value:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
     let a = 3;
     yield ();
     println!("{}", a);
@@ -41,10 +41,10 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
 This error also frequently arises with iteration:
 
 ```compile_fail,E0626
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   for &x in &v { // <-- borrow of `v` is still in scope...
     yield x; // ...when this yield occurs.
@@ -57,10 +57,10 @@ Such cases can sometimes be resolved by iterating "by value" (or using
 `into_iter()`) to avoid borrowing:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   for x in v { // <-- Take ownership of the values instead!
     yield x; // <-- Now yield is OK.
@@ -72,10 +72,10 @@ Pin::new(&mut b).resume(());
 If taking ownership is not an option, using indices can work too:
 
 ```
-# #![feature(coroutines, coroutine_trait, pin)]
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
-let mut b = || {
+let mut b = #[coroutine] || {
   let v = vec![1,2,3];
   let len = v.len(); // (*)
   for i in 0..len {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0627.md b/compiler/rustc_error_codes/src/error_codes/E0627.md
index 5d366f78fc5..da2e2d355a1 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0627.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0627.md
@@ -3,7 +3,7 @@ A yield expression was used outside of the coroutine literal.
 Erroneous code example:
 
 ```compile_fail,E0627
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn fake_coroutine() -> &'static str {
     yield 1;
@@ -19,10 +19,10 @@ The error occurs because keyword `yield` can only be used inside the coroutine
 literal. This can be fixed by constructing the coroutine correctly.
 
 ```
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
diff --git a/compiler/rustc_error_codes/src/error_codes/E0628.md b/compiler/rustc_error_codes/src/error_codes/E0628.md
index ce19bcd56cc..d0d387cf6c7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0628.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0628.md
@@ -3,10 +3,10 @@ More than one parameter was used for a coroutine.
 Erroneous code example:
 
 ```compile_fail,E0628
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = |a: i32, b: i32| {
+    let coroutine = #[coroutine] |a: i32, b: i32| {
         // error: too many parameters for a coroutine
         // Allowed only 0 or 1 parameter
         yield a;
@@ -20,10 +20,10 @@ at most 1 parameter for the coroutine. For example, we might resolve
 the previous example by passing only one parameter.
 
 ```
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = |a: i32| {
+    let coroutine = #[coroutine] |a: i32| {
         yield a;
     };
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0727.md b/compiler/rustc_error_codes/src/error_codes/E0727.md
index fde35885c92..7754186508f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0727.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0727.md
@@ -3,10 +3,10 @@ A `yield` clause was used in an `async` context.
 Erroneous code example:
 
 ```compile_fail,E0727,edition2018
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = || {
+    let coroutine = #[coroutine] || {
         async {
             yield;
         }
@@ -20,10 +20,10 @@ which is not yet supported.
 To fix this error, you have to move `yield` out of the `async` block:
 
 ```edition2018
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let coroutine = || {
+    let coroutine = #[coroutine] || {
         yield;
     };
 }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 1eee11604ce..c0e664f6eed 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -211,6 +211,8 @@ declare_features! (
     (accepted, inclusive_range_syntax, "1.26.0", Some(28237)),
     /// Allows inferring outlives requirements (RFC 2093).
     (accepted, infer_outlives_requirements, "1.30.0", Some(44493)),
+    /// Allow anonymous constants from an inline `const` block
+    (accepted, inline_const, "CURRENT_RUSTC_VERSION", Some(76001)),
     /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
     (accepted, irrefutable_let_patterns, "1.33.0", Some(44495)),
     /// Allows `#[instruction_set(_)]` attribute.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 23b3f31b437..647cd8d06f2 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -534,6 +534,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::Yes, experimental!(cfi_encoding)
     ),
 
+    // `#[coroutine]` attribute to be applied to closures to make them coroutines instead
+    gated!(
+        coroutine, Normal, template!(Word), ErrorFollowing,
+        EncodeCrossCrate::No, coroutines, experimental!(coroutines)
+    ),
+
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 9641d336c3f..2647f09c8c9 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -501,8 +501,6 @@ declare_features! (
     (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995)),
-    /// Allow anonymous constants from an inline `const` block
-    (unstable, inline_const, "1.49.0", Some(76001)),
     /// Allow anonymous constants from an inline `const` block in pattern position
     (unstable, inline_const_pat, "1.58.0", Some(76001)),
     /// Allows using `pointer` and `reference` in intra-doc links
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 3359fef8c1c..d376c24cb58 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -1,5 +1,3 @@
-#![feature(absolute_path)]
-
 use std::ffi::CString;
 use std::fs;
 use std::io;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 4a0df6cf7b8..63da27246a2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1964,11 +1964,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("recursive delegation");
         }
 
-        let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
-        if sig.output().has_opaque_types() {
-            try_emit("delegation to a function with opaque type");
-        }
-
         let sig_generics = self.tcx().generics_of(sig_id);
         let parent = self.tcx().parent(self.item_def_id());
         let parent_generics = self.tcx().generics_of(parent);
@@ -1991,29 +1986,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("delegation to a trait method from a free function");
         }
 
-        if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
-            try_emit("delegation to async functions");
-        }
-
-        if self.tcx().constness(sig_id) == hir::Constness::Const {
-            try_emit("delegation to const functions");
-        }
-
-        if sig.c_variadic() {
-            try_emit("delegation to variadic functions");
-            // variadic functions are also `unsafe` and `extern "C"`.
-            // Do not emit same error multiple times.
-            return error_occured;
-        }
-
-        if let hir::Unsafety::Unsafe = sig.unsafety() {
-            try_emit("delegation to unsafe functions");
-        }
-
-        if abi::Abi::Rust != sig.abi() {
-            try_emit("delegation to non Rust ABI functions");
-        }
-
         error_occured
     }
 
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 9ebb5f95f05..4165fa7f07d 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1139,7 +1139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // are the same function and their parameters have a LUB.
                         match self.commit_if_ok(|_| {
                             self.at(cause, self.param_env).lub(
-                                DefineOpaqueTypes::No,
+                                DefineOpaqueTypes::Yes,
                                 prev_ty,
                                 new_ty,
                             )
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index c4ab4eb2657..fd42c9c1faa 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1260,30 +1260,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         id: DefIndex,
         sess: &'a Session,
     ) -> impl Iterator<Item = ModChild> + 'a {
-        iter::from_coroutine(move || {
-            if let Some(data) = &self.root.proc_macro_data {
-                // If we are loading as a proc macro, we want to return
-                // the view of this crate as a proc macro crate.
-                if id == CRATE_DEF_INDEX {
-                    for child_index in data.macros.decode(self) {
+        iter::from_coroutine(
+            #[cfg_attr(not(bootstrap), coroutine)]
+            move || {
+                if let Some(data) = &self.root.proc_macro_data {
+                    // If we are loading as a proc macro, we want to return
+                    // the view of this crate as a proc macro crate.
+                    if id == CRATE_DEF_INDEX {
+                        for child_index in data.macros.decode(self) {
+                            yield self.get_mod_child(child_index, sess);
+                        }
+                    }
+                } else {
+                    // Iterate over all children.
+                    let non_reexports =
+                        self.root.tables.module_children_non_reexports.get(self, id);
+                    for child_index in non_reexports.unwrap().decode(self) {
                         yield self.get_mod_child(child_index, sess);
                     }
-                }
-            } else {
-                // Iterate over all children.
-                let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
-                for child_index in non_reexports.unwrap().decode(self) {
-                    yield self.get_mod_child(child_index, sess);
-                }
 
-                let reexports = self.root.tables.module_children_reexports.get(self, id);
-                if !reexports.is_default() {
-                    for reexport in reexports.decode((self, sess)) {
-                        yield reexport;
+                    let reexports = self.root.tables.module_children_reexports.get(self, id);
+                    if !reexports.is_default() {
+                        for reexport in reexports.decode((self, sess)) {
+                            yield reexport;
+                        }
                     }
                 }
-            }
-        })
+            },
+        )
     }
 
     fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index aadaca18326..501052b7411 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -35,8 +35,9 @@
 #![feature(const_type_name)]
 #![feature(discriminant_kind)]
 #![feature(coroutines)]
+#![feature(stmt_expr_attributes)]
 #![feature(if_let_guard)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(iter_from_coroutine)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 11167515b7c..b66c664e6ae 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -422,49 +422,53 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>(
     child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
     mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T,
 ) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> {
-    std::iter::from_coroutine(move || {
-        let mut child_captures = child_captures.into_iter().enumerate().peekable();
-
-        // One parent capture may correspond to several child captures if we end up
-        // refining the set of captures via edition-2021 precise captures. We want to
-        // match up any number of child captures with one parent capture, so we keep
-        // peeking off this `Peekable` until the child doesn't match anymore.
-        for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
-            // Make sure we use every field at least once, b/c why are we capturing something
-            // if it's not used in the inner coroutine.
-            let mut field_used_at_least_once = false;
-
-            // A parent matches a child if they share the same prefix of projections.
-            // The child may have more, if it is capturing sub-fields out of
-            // something that is captured by-move in the parent closure.
-            while child_captures.peek().map_or(false, |(_, child_capture)| {
-                child_prefix_matches_parent_projections(parent_capture, child_capture)
-            }) {
-                let (child_field_idx, child_capture) = child_captures.next().unwrap();
-                // This analysis only makes sense if the parent capture is a
-                // prefix of the child capture.
-                assert!(
-                    child_capture.place.projections.len() >= parent_capture.place.projections.len(),
-                    "parent capture ({parent_capture:#?}) expected to be prefix of \
+    std::iter::from_coroutine(
+        #[cfg_attr(not(bootstrap), coroutine)]
+        move || {
+            let mut child_captures = child_captures.into_iter().enumerate().peekable();
+
+            // One parent capture may correspond to several child captures if we end up
+            // refining the set of captures via edition-2021 precise captures. We want to
+            // match up any number of child captures with one parent capture, so we keep
+            // peeking off this `Peekable` until the child doesn't match anymore.
+            for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
+                // Make sure we use every field at least once, b/c why are we capturing something
+                // if it's not used in the inner coroutine.
+                let mut field_used_at_least_once = false;
+
+                // A parent matches a child if they share the same prefix of projections.
+                // The child may have more, if it is capturing sub-fields out of
+                // something that is captured by-move in the parent closure.
+                while child_captures.peek().map_or(false, |(_, child_capture)| {
+                    child_prefix_matches_parent_projections(parent_capture, child_capture)
+                }) {
+                    let (child_field_idx, child_capture) = child_captures.next().unwrap();
+                    // This analysis only makes sense if the parent capture is a
+                    // prefix of the child capture.
+                    assert!(
+                        child_capture.place.projections.len()
+                            >= parent_capture.place.projections.len(),
+                        "parent capture ({parent_capture:#?}) expected to be prefix of \
                     child capture ({child_capture:#?})"
-                );
+                    );
 
-                yield for_each(
-                    (parent_field_idx, parent_capture),
-                    (child_field_idx, child_capture),
-                );
+                    yield for_each(
+                        (parent_field_idx, parent_capture),
+                        (child_field_idx, child_capture),
+                    );
 
-                field_used_at_least_once = true;
-            }
+                    field_used_at_least_once = true;
+                }
 
-            // Make sure the field was used at least once.
-            assert!(
-                field_used_at_least_once,
-                "we captured {parent_capture:#?} but it was not used in the child coroutine?"
-            );
-        }
-        assert_eq!(child_captures.next(), None, "leftover child captures?");
-    })
+                // Make sure the field was used at least once.
+                assert!(
+                    field_used_at_least_once,
+                    "we captured {parent_capture:#?} but it was not used in the child coroutine?"
+                );
+            }
+            assert_eq!(child_captures.next(), None, "leftover child captures?");
+        },
+    )
 }
 
 fn child_prefix_matches_parent_projections(
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 7dbe59e132d..45fa5e8f7ca 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1284,20 +1284,23 @@ impl<'tcx> TyCtxt<'tcx> {
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
         let definitions = &self.untracked.definitions;
-        std::iter::from_coroutine(|| {
-            let mut i = 0;
-
-            // Recompute the number of definitions each time, because our caller may be creating
-            // new ones.
-            while i < { definitions.read().num_definitions() } {
-                let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
-                yield LocalDefId { local_def_index };
-                i += 1;
-            }
+        std::iter::from_coroutine(
+            #[cfg_attr(not(bootstrap), coroutine)]
+            || {
+                let mut i = 0;
+
+                // Recompute the number of definitions each time, because our caller may be creating
+                // new ones.
+                while i < { definitions.read().num_definitions() } {
+                    let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
+                    yield LocalDefId { local_def_index };
+                    i += 1;
+                }
 
-            // Freeze definitions once we finish iterating on them, to prevent adding new ones.
-            definitions.freeze();
-        })
+                // Freeze definitions once we finish iterating on them, to prevent adding new ones.
+                definitions.freeze();
+            },
+        )
     }
 
     pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index cc026e349d7..cda332aee56 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -45,7 +45,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_index::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
@@ -224,8 +224,15 @@ pub struct ResolverAstLowering {
     pub lint_buffer: Steal<LintBuffer>,
 
     /// Information about functions signatures for delegation items expansion
-    pub has_self: LocalDefIdSet,
-    pub fn_parameter_counts: LocalDefIdMap<usize>,
+    pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
+}
+
+#[derive(Debug)]
+pub struct DelegationFnSig {
+    pub header: ast::FnHeader,
+    pub param_count: usize,
+    pub has_self: bool,
+    pub c_variadic: bool,
 }
 
 #[derive(Clone, Copy, Debug)]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index b308a80f7ba..e42755ca7bf 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -4,7 +4,7 @@
 #![feature(cow_is_borrowed)]
 #![feature(decl_macro)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(map_try_insert)]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 84ecd0a0de5..ed51710564a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -686,6 +686,8 @@ impl<'a> Parser<'a> {
             (None, self.parse_path(PathStyle::Expr)?)
         };
 
+        let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
+
         let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
             Some(self.parse_block()?)
         } else {
@@ -695,11 +697,9 @@ impl<'a> Parser<'a> {
         let span = span.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::fn_delegation, span);
 
-        let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
-        Ok((
-            ident,
-            ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })),
-        ))
+        let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
+        let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
+        Ok((ident, ItemKind::Delegation(Box::new(deleg))))
     }
 
     fn parse_item_list<T>(
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 742f4bd3c83..7486da33b21 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1252,8 +1252,6 @@ impl<'a> Parser<'a> {
     fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
         if pat {
             self.psess.gated_spans.gate(sym::inline_const_pat, span);
-        } else {
-            self.psess.gated_spans.gate(sym::inline_const, span);
         }
         self.eat_keyword(kw::Const);
         let (attrs, blk) = self.parse_inner_attrs_and_block()?;
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c877ae5e21f..292af43b602 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
+use rustc_middle::ty::DelegationFnSig;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
 use rustc_session::lint;
@@ -4749,12 +4750,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> {
 
 impl ItemInfoCollector<'_, '_, '_> {
     fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
-        let def_id = self.r.local_def_id(id);
-        self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
-
-        if sig.decl.has_self() {
-            self.r.has_self.insert(def_id);
-        }
+        let sig = DelegationFnSig {
+            header: sig.header,
+            param_count: sig.decl.inputs.len(),
+            has_self: sig.decl.has_self(),
+            c_variadic: sig.decl.c_variadic(),
+        };
+        self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d79c638fa07..64451030adf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2039,7 +2039,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
                         ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
                         ast::AssocItemKind::Delegation(..)
-                            if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
+                            if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
+                                .has_self =>
                         {
                             AssocSuggestion::MethodWithSelf { called }
                         }
@@ -2062,7 +2063,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 if filter_fn(res) {
                     let def_id = res.def_id();
                     let has_self = match def_id.as_local() {
-                        Some(def_id) => self.r.has_self.contains(&def_id),
+                        Some(def_id) => {
+                            self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
+                        }
                         None => self
                             .r
                             .tcx
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b5b6d899cc5..e07c3247d07 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::NonMacroAttrKind;
 use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_index::IndexVec;
@@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed};
-use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs};
+use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools};
+use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
@@ -992,7 +992,6 @@ pub struct Resolver<'a, 'tcx> {
     extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
 
     /// N.B., this is used only for better diagnostics, not name resolution itself.
-    has_self: LocalDefIdSet,
     field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
 
     /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
@@ -1149,8 +1148,7 @@ pub struct Resolver<'a, 'tcx> {
     legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
     /// Amount of lifetime parameters for each item in the crate.
     item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
-    /// Amount of parameters for each function in the crate.
-    fn_parameter_counts: LocalDefIdMap<usize>,
+    delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
 
     main_def: Option<MainDefinition>,
     trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -1399,7 +1397,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             prelude: None,
             extern_prelude,
 
-            has_self: Default::default(),
             field_def_ids: Default::default(),
             field_visibility_spans: FxHashMap::default(),
 
@@ -1508,7 +1505,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             doc_link_resolutions: Default::default(),
             doc_link_traits_in_scope: Default::default(),
             all_macro_rules: Default::default(),
-            fn_parameter_counts: Default::default(),
+            delegation_fn_sigs: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1621,8 +1618,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
-            has_self: self.has_self,
-            fn_parameter_counts: self.fn_parameter_counts,
+            delegation_fn_sigs: self.delegation_fn_sigs,
         };
         ResolverOutputs { global_ctxt, ast_lowering }
     }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 3e1d8f3828b..19f4e6994ac 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -11,7 +11,7 @@
 #![cfg_attr(bootstrap, feature(associated_type_bounds))]
 #![feature(const_option)]
 #![feature(core_intrinsics)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(ptr_sub_ptr)]
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 07c11663173..4f259960ac3 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1888,9 +1888,12 @@ fn collect_print_requests(
                 let prints =
                     PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
                 let prints = prints.join(", ");
-                early_dcx.early_fatal(format!(
-                    "unknown print request `{req}`. Valid print requests are: {prints}"
-                ));
+
+                let mut diag =
+                    early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
+                #[allow(rustc::diagnostic_outside_of_impl)]
+                diag.help(format!("valid print requests are: {prints}"));
+                diag.emit()
             }
         };
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8abf42e2c13..99591b5e144 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -192,6 +192,7 @@ symbols! {
         Duration,
         Encodable,
         Encoder,
+        Enumerate,
         Eq,
         Equal,
         Err,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 837b784f272..e50edfdc656 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -50,22 +50,38 @@ pub struct FindExprBySpan<'hir> {
     pub span: Span,
     pub result: Option<&'hir hir::Expr<'hir>>,
     pub ty_result: Option<&'hir hir::Ty<'hir>>,
+    pub include_closures: bool,
+    pub tcx: TyCtxt<'hir>,
 }
 
 impl<'hir> FindExprBySpan<'hir> {
-    pub fn new(span: Span) -> Self {
-        Self { span, result: None, ty_result: None }
+    pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self {
+        Self { span, result: None, ty_result: None, tcx, include_closures: false }
     }
 }
 
 impl<'v> Visitor<'v> for FindExprBySpan<'v> {
+    type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+
     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
         if self.span == ex.span {
             self.result = Some(ex);
         } else {
+            if let hir::ExprKind::Closure(..) = ex.kind
+                && self.include_closures
+                && let closure_header_sp = self.span.with_hi(ex.span.hi())
+                && closure_header_sp == ex.span
+            {
+                self.result = Some(ex);
+            }
             hir::intravisit::walk_expr(self, ex);
         }
     }
+
     fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         if self.span == ty.span {
             self.ty_result = Some(ty);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 9d3caaa01ab..cc879c42ce9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -901,7 +901,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // Remove all the desugaring and macro contexts.
             span.remove_mark();
         }
-        let mut expr_finder = FindExprBySpan::new(span);
+        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
         let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
             return;
         };
@@ -1367,7 +1367,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             return false;
                         };
                         let body = self.tcx.hir().body(body_id);
-                        let mut expr_finder = FindExprBySpan::new(span);
+                        let mut expr_finder = FindExprBySpan::new(span, self.tcx);
                         expr_finder.visit_expr(body.value);
                         let Some(expr) = expr_finder.result else {
                             return false;
@@ -1469,7 +1469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // Remove all the hir desugaring contexts while maintaining the macro contexts.
             span.remove_mark();
         }
-        let mut expr_finder = super::FindExprBySpan::new(span);
+        let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
         let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
             return false;
         };
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 0e309689680..1971136e54c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -2457,7 +2457,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     && let Some(body_id) =
                         self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
                 {
-                    let mut expr_finder = FindExprBySpan::new(span);
+                    let mut expr_finder = FindExprBySpan::new(span, self.tcx);
                     expr_finder.visit_expr(self.tcx.hir().body(body_id).value);
 
                     if let Some(hir::Expr {
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 3be0be83e09..3924b371bbc 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -183,7 +183,7 @@ pub enum TyKind<I: Interner> {
     ///
     /// ```
     /// #![feature(coroutines)]
-    /// static |a| {
+    /// #[coroutine] static |a| {
     ///     let x = &vec![3];
     ///     yield a;
     ///     yield x[0];
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index c54f0062824..846b9a1404d 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -31,7 +31,7 @@
 //! // instead of a max-heap.
 //! impl Ord for State {
 //!     fn cmp(&self, other: &Self) -> Ordering {
-//!         // Notice that the we flip the ordering on costs.
+//!         // Notice that we flip the ordering on costs.
 //!         // In case of a tie we compare positions - this step is necessary
 //!         // to make implementations of `PartialEq` and `Ord` consistent.
 //!         other.cost.cmp(&self.cost)
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 88faf5a9c7d..b417513aaa2 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -128,7 +128,6 @@
 #![feature(fn_traits)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hint_assert_unchecked)]
-#![feature(inline_const)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
@@ -169,6 +168,7 @@
 // Language features:
 // tidy-alphabetical-start
 #![cfg_attr(bootstrap, feature(associated_type_bounds))]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
 #![cfg_attr(not(test), feature(coroutine_trait))]
 #![cfg_attr(test, feature(panic_update_hook))]
diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs
index ef46040f0a7..7adbabf69e4 100644
--- a/library/core/src/iter/adapters/enumerate.rs
+++ b/library/core/src/iter/adapters/enumerate.rs
@@ -15,6 +15,7 @@ use crate::ops::Try;
 #[derive(Clone, Debug)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")]
 pub struct Enumerate<I> {
     iter: I,
     count: usize,
diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs
index bf413b24d41..9bac9037a02 100644
--- a/library/core/src/iter/sources/from_coroutine.rs
+++ b/library/core/src/iter/sources/from_coroutine.rs
@@ -14,7 +14,7 @@ use crate::pin::Pin;
 /// #![feature(coroutines)]
 /// #![feature(iter_from_coroutine)]
 ///
-/// let it = std::iter::from_coroutine(|| {
+/// let it = std::iter::from_coroutine(#[cfg_attr(not(bootstrap), coroutine)] || {
 ///     yield 1;
 ///     yield 2;
 ///     yield 3;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 154565b6fee..6925a7d1da1 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -201,6 +201,7 @@
 //
 // Language features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
@@ -231,7 +232,6 @@
 #![feature(fundamental)]
 #![feature(generic_arg_infer)]
 #![feature(if_let_guard)]
-#![feature(inline_const)]
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index 6e067f95da9..5250be15fe4 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -40,12 +40,13 @@ pub enum CoroutineState<Y, R> {
 /// ```rust
 /// #![feature(coroutines)]
 /// #![feature(coroutine_trait)]
+/// #![feature(stmt_expr_attributes)]
 ///
 /// use std::ops::{Coroutine, CoroutineState};
 /// use std::pin::Pin;
 ///
 /// fn main() {
-///     let mut coroutine = || {
+///     let mut coroutine = #[cfg_attr(not(bootstrap), coroutine)] || {
 ///         yield 1;
 ///         "foo"
 ///     };
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index efd525aeb3b..a11c6c742d7 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1809,7 +1809,7 @@ impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U>
 /// fn coroutine_fn() -> impl Coroutine<Yield = usize, Return = ()> /* not Unpin */ {
 ///  // Allow coroutine to be self-referential (not `Unpin`)
 ///  // vvvvvv        so that locals can cross yield points.
-///     static || {
+///     #[cfg_attr(not(bootstrap), coroutine)] static || {
 ///         let foo = String::from("foo");
 ///         let foo_ref = &foo; // ------+
 ///         yield 0;                  // | <- crosses yield point!
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index c8fd997a5da..073459fcb00 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -511,7 +511,8 @@ impl AtomicBool {
     /// # Examples
     ///
     /// ```
-    /// #![feature(atomic_from_mut, inline_const)]
+    /// #![feature(atomic_from_mut)]
+    /// # #![cfg_attr(bootstrap, feature(inline_const))]
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
     /// let mut some_bools = [const { AtomicBool::new(false) }; 10];
@@ -1313,7 +1314,8 @@ impl<T> AtomicPtr<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(atomic_from_mut, inline_const)]
+    /// #![feature(atomic_from_mut)]
+    /// # #![cfg_attr(bootstrap, feature(inline_const))]
     /// use std::ptr::null_mut;
     /// use std::sync::atomic::{AtomicPtr, Ordering};
     ///
@@ -2303,7 +2305,8 @@ macro_rules! atomic_int {
             /// # Examples
             ///
             /// ```
-            /// #![feature(atomic_from_mut, inline_const)]
+            /// #![feature(atomic_from_mut)]
+            /// # #![cfg_attr(bootstrap, feature(inline_const))]
             #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
             ///
             #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")]
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 7bd962fa260..d6e705a37a7 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -46,7 +46,7 @@
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
 #![feature(try_find)]
-#![feature(inline_const)]
+#![cfg_attr(bootstrap, feature(inline_const))]
 #![feature(is_sorted)]
 #![feature(layout_for_ptr)]
 #![feature(pattern)]
diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs
index 48514e52587..331b6626249 100644
--- a/library/portable-simd/crates/core_simd/src/lib.rs
+++ b/library/portable-simd/crates/core_simd/src/lib.rs
@@ -7,7 +7,6 @@
     convert_float_to_int,
     core_intrinsics,
     decl_macro,
-    inline_const,
     intra_doc_pointers,
     repr_simd,
     simd_ffi,
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 0636f55771e..1c58671a0cf 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3332,7 +3332,6 @@ impl Error for StripPrefixError {
 /// ## Posix paths
 ///
 /// ```
-/// #![feature(absolute_path)]
 /// # #[cfg(unix)]
 /// fn main() -> std::io::Result<()> {
 ///   use std::path::{self, Path};
@@ -3357,7 +3356,6 @@ impl Error for StripPrefixError {
 /// ## Windows paths
 ///
 /// ```
-/// #![feature(absolute_path)]
 /// # #[cfg(windows)]
 /// fn main() -> std::io::Result<()> {
 ///   use std::path::{self, Path};
@@ -3382,7 +3380,7 @@ impl Error for StripPrefixError {
 ///
 /// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
 /// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
-#[unstable(feature = "absolute_path", issue = "92750")]
+#[stable(feature = "absolute_path", since = "CURRENT_RUSTC_VERSION")]
 pub fn absolute<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
     let path = path.as_ref();
     if path.as_os_str().is_empty() {
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index b49585599cb..ff41f6e77be 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -201,14 +201,21 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
 // currently reside in the buffer. This function is an abstraction over these
 // functions by making them easier to call.
 //
-// The first callback, `f1`, is yielded a (pointer, len) pair which can be
+// The first callback, `f1`, is passed a (pointer, len) pair which can be
 // passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
-// The closure is expected to return what the syscall returns which will be
-// interpreted by this function to determine if the syscall needs to be invoked
-// again (with more buffer space).
+// The closure is expected to:
+// - On success, return the actual length of the written data *without* the null terminator.
+//   This can be 0. In this case the last_error must be left unchanged.
+// - On insufficient buffer space,
+//   - either return the required length *with* the null terminator,
+//   - or set the last-error to ERROR_INSUFFICIENT_BUFFER and return `len`.
+// - On other failure, return 0 and set last_error.
+//
+// This is how most but not all syscalls indicate the required buffer space.
+// Other syscalls may need translation to match this protocol.
 //
 // Once the syscall has completed (errors bail out early) the second closure is
-// yielded the data which has been read from the syscall. The return value
+// passed the data which has been read from the syscall. The return value
 // from this closure is then the return value of the function.
 pub fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
 where
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 374c9845ea4..64d8b72aed2 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -326,6 +326,8 @@ fn home_dir_crt() -> Option<PathBuf> {
 
         super::fill_utf16_buf(
             |buf, mut sz| {
+                // GetUserProfileDirectoryW does not quite use the usual protocol for
+                // negotiating the buffer size, so we have to translate.
                 match c::GetUserProfileDirectoryW(
                     ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
                     buf,
diff --git a/library/std/src/sys/pal/windows/thread_local_key.rs b/library/std/src/sys/pal/windows/thread_local_key.rs
index 4c00860dae3..e5ba619fc6b 100644
--- a/library/std/src/sys/pal/windows/thread_local_key.rs
+++ b/library/std/src/sys/pal/windows/thread_local_key.rs
@@ -141,9 +141,15 @@ impl StaticKey {
                     panic!("out of TLS indexes");
                 }
 
-                self.key.store(key + 1, Release);
                 register_dtor(self);
 
+                // Release-storing the key needs to be the last thing we do.
+                // This is because in `fn key()`, other threads will do an acquire load of the key,
+                // and if that sees this write then it will entirely bypass the `InitOnce`. We thus
+                // need to establish synchronization through `key`. In particular that acquire load
+                // must happen-after the register_dtor above, to ensure the dtor actually runs!
+                self.key.store(key + 1, Release);
+
                 let r = c::InitOnceComplete(self.once.get(), 0, ptr::null_mut());
                 debug_assert_eq!(r, c::TRUE);
 
@@ -313,8 +319,22 @@ unsafe fn run_dtors() {
         // Use acquire ordering to observe key initialization.
         let mut cur = DTORS.load(Acquire);
         while !cur.is_null() {
-            let key = (*cur).key.load(Relaxed) - 1;
+            let pre_key = (*cur).key.load(Acquire);
             let dtor = (*cur).dtor.unwrap();
+            cur = (*cur).next.load(Relaxed);
+
+            // In StaticKey::init, we register the dtor before setting `key`.
+            // So if one thread's `run_dtors` races with another thread executing `init` on the same
+            // `StaticKey`, we can encounter a key of 0 here. That means this key was never
+            // initialized in this thread so we can safely skip it.
+            if pre_key == 0 {
+                continue;
+            }
+            // If this is non-zero, then via the `Acquire` load above we synchronized with
+            // everything relevant for this key. (It's not clear that this is needed, since the
+            // release-acquire pair on DTORS also establishes synchronization, but better safe than
+            // sorry.)
+            let key = pre_key - 1;
 
             let ptr = c::TlsGetValue(key);
             if !ptr.is_null() {
@@ -322,8 +342,6 @@ unsafe fn run_dtors() {
                 dtor(ptr as *mut _);
                 any_run = true;
             }
-
-            cur = (*cur).next.load(Relaxed);
         }
 
         if !any_run {
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
index d6de992913b..9cc508fe928 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
@@ -5,7 +5,7 @@
 
 set -euf -o pipefail
 
-INTEGRATION_SHA=56310bca298872ffb5ea02e665956d9b6dc41171
+INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
 PICK_REFS=()
 
 checkout=fuchsia
diff --git a/src/ci/docker/scripts/build-fuchsia-toolchain.sh b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
index beea2f522fd..7a0d4fcffc1 100755
--- a/src/ci/docker/scripts/build-fuchsia-toolchain.sh
+++ b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
@@ -4,13 +4,13 @@ set -ex
 source shared.sh
 
 FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
-FUCHSIA_SDK_ID=MrhQwtmP8CpZre-i_PNOREcThbUcrX3bA-45d6WQr-cC
-FUCHSIA_SDK_SHA256=32b850c2d98ff02a59adefa2fcf34e44471385b51cad7ddb03ee3977a590afe7
+FUCHSIA_SDK_ID=version:20.20240412.3.1
+FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
 FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
 CLANG_DOWNLOAD_URL=\
 https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
-CLANG_DOWNLOAD_ID=Tpc85d1ZwSlZ6UKl2d96GRUBGNA5JKholOKe24sRDr0C
-CLANG_DOWNLOAD_SHA256=4e973ce5dd59c12959e942a5d9df7a19150118d03924a86894e29edb8b110ebd
+CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
+CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844
 
 install_clang() {
   mkdir -p clang_download
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 437b51641fc..8ac00a8863f 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -280,7 +280,7 @@ class TestEnvironment:
         # Look up the product bundle transfer manifest.
         self.log_info("Looking up the product bundle transfer manifest...")
         product_name = "minimal." + self.triple_to_arch(self.target)
-        fuchsia_version = "14.20230811.2.1"
+        fuchsia_version = "20.20240412.3.1"
 
         # FIXME: We should be able to replace this with the machine parsable
         # `ffx --machine json product lookup ...` once F15 is released.
diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py
new file mode 100755
index 00000000000..c24cefa8d89
--- /dev/null
+++ b/src/ci/github-actions/calculate-job-matrix.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+
+"""
+This script serves for generating a matrix of jobs that should
+be executed on CI.
+
+It reads job definitions from `src/ci/github-actions/jobs.yml`
+and filters them based on the event that happened on CI.
+"""
+import dataclasses
+import enum
+import json
+import logging
+import os
+from pathlib import Path
+from typing import List, Dict, Any, Optional
+
+import yaml
+
+JOBS_YAML_PATH = Path(__file__).absolute().parent / "jobs.yml"
+
+
+def name_jobs(jobs: List[Dict], prefix: str) -> List[Dict]:
+    """
+    Add a `name` attribute to each job, based on its image and the given `prefix`.
+    """
+    for job in jobs:
+        job["name"] = f"{prefix} - {job['image']}"
+    return jobs
+
+
+def add_base_env(jobs: List[Dict], environment: Dict[str, str]) -> List[Dict]:
+    """
+    Prepends `environment` to the `env` attribute of each job.
+    The `env` of each job has higher precedence than `environment`.
+    """
+    for job in jobs:
+        env = environment.copy()
+        env.update(job.get("env", {}))
+        job["env"] = env
+    return jobs
+
+
+class JobType(enum.Enum):
+    PR = enum.auto()
+    Try = enum.auto()
+    Auto = enum.auto()
+
+
+@dataclasses.dataclass
+class GitHubCtx:
+    event_name: str
+    ref: str
+    repository: str
+
+
+def find_job_type(ctx: GitHubCtx) -> Optional[JobType]:
+    if ctx.event_name == "pull_request":
+        return JobType.PR
+    elif ctx.event_name == "push":
+        old_bors_try_build = (
+            ctx.ref in ("refs/heads/try", "refs/heads/try-perf") and
+            ctx.repository == "rust-lang-ci/rust"
+        )
+        new_bors_try_build = (
+            ctx.ref == "refs/heads/automation/bors/try" and
+            ctx.repository == "rust-lang/rust"
+        )
+        try_build = old_bors_try_build or new_bors_try_build
+
+        if try_build:
+            return JobType.Try
+
+        if ctx.ref == "refs/heads/auto" and ctx.repository == "rust-lang-ci/rust":
+            return JobType.Auto
+
+    return None
+
+
+def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str, Any]]:
+    if job_type == JobType.PR:
+        return add_base_env(name_jobs(job_data["pr"], "PR"), job_data["envs"]["pr"])
+    elif job_type == JobType.Try:
+        return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["try"])
+    elif job_type == JobType.Auto:
+        return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"])
+
+    return []
+
+
+def get_github_ctx() -> GitHubCtx:
+    return GitHubCtx(
+        event_name=os.environ["GITHUB_EVENT_NAME"],
+        ref=os.environ["GITHUB_REF"],
+        repository=os.environ["GITHUB_REPOSITORY"]
+    )
+
+
+if __name__ == "__main__":
+    logging.basicConfig(level=logging.INFO)
+
+    with open(JOBS_YAML_PATH) as f:
+        data = yaml.safe_load(f)
+
+    github_ctx = get_github_ctx()
+
+    job_type = find_job_type(github_ctx)
+    logging.info(f"Job type: {job_type}")
+
+    jobs = []
+    if job_type is not None:
+        jobs = calculate_jobs(job_type, data)
+
+    logging.info(f"Output:\n{yaml.dump(jobs, indent=4)}")
+    print(f"jobs={json.dumps(jobs)}")
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index de71b9f874f..19d6b517552 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -342,6 +342,8 @@ concurrency:
 
 jobs:
   # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml.
+  # It calculates which jobs should be executed, based on the data of the ${{ github }} context.
+  # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml.
   calculate_matrix:
     name: Calculate job matrix
     runs-on: ubuntu-latest
@@ -351,422 +353,34 @@ jobs:
       - name: Checkout the source code
         uses: actions/checkout@v4
       - name: Calculate the CI job matrix
-        run: python3 src/ci/scripts/calculate-job-matrix.py >> $GITHUB_OUTPUT
+        run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT
         id: jobs
-  pr:
+  job:
     <<: *base-ci-job
-    name: PR - ${{ matrix.name }}
+    name: ${{ matrix.name }}
     needs: [ calculate_matrix ]
     env:
-      <<: [*shared-ci-variables, *public-variables]
-      PR_CI_JOB: 1
-    if: github.event_name == 'pull_request'
-    continue-on-error: ${{ matrix.name == 'mingw-check-tidy' }}
+      CI_JOB_NAME: ${{ matrix.image }}
+      CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
+      # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
+      HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
+      DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      SCCACHE_BUCKET: rust-lang-ci-sccache2
+      TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate
+      CACHE_DOMAIN: ci-caches.rust-lang.org
+    continue-on-error: ${{ matrix.continue_on_error || false }}
     strategy:
       matrix:
         # Check the `calculate_matrix` job to see how is the matrix defined.
         include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}
-
-  auto:
-    <<: *base-ci-job
-    name: auto - ${{ matrix.name }}
-    env:
-      <<: [*shared-ci-variables, *prod-variables]
-    if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'
-    strategy:
-      matrix:
-        include:
-          #############################
-          #   Linux/Docker builders   #
-          #############################
-
-          - name: aarch64-gnu
-            <<: *job-aarch64-linux
-
-          - name: arm-android
-            <<: *job-linux-8c
-
-          - name: armhf-gnu
-            <<: *job-linux-8c
-
-          - name: dist-aarch64-linux
-            env:
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-linux-8c
-
-          - name: dist-android
-            <<: *job-linux-8c
-
-          - name: dist-arm-linux
-            <<: *job-linux-16c
-
-          - name: dist-armhf-linux
-            <<: *job-linux-8c
-
-          - name: dist-armv7-linux
-            <<: *job-linux-8c
-
-          - name: dist-i586-gnu-i586-i686-musl
-            <<: *job-linux-8c
-
-          - name: dist-i686-linux
-            <<: *job-linux-8c
-
-          - name: dist-loongarch64-linux
-            <<: *job-linux-8c
-
-          - name: dist-ohos
-            <<: *job-linux-8c
-
-          - name: dist-powerpc-linux
-            <<: *job-linux-8c
-
-          - name: dist-powerpc64-linux
-            <<: *job-linux-8c
-
-          - name: dist-powerpc64le-linux
-            <<: *job-linux-8c
-
-          - name: dist-riscv64-linux
-            <<: *job-linux-8c
-
-          - name: dist-s390x-linux
-            <<: *job-linux-8c
-
-          - name: dist-various-1
-            <<: *job-linux-8c
-
-          - name: dist-various-2
-            <<: *job-linux-8c
-
-          - name: dist-x86_64-freebsd
-            <<: *job-linux-8c
-
-          - name: dist-x86_64-illumos
-            <<: *job-linux-8c
-
-          - &dist-x86_64-linux
-            name: dist-x86_64-linux
-            env:
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-linux-16c
-
-          - name: dist-x86_64-linux-alt
-            env:
-              IMAGE: dist-x86_64-linux
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-linux-16c
-
-          - name: dist-x86_64-musl
-            env:
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-linux-8c
-
-          - name: dist-x86_64-netbsd
-            <<: *job-linux-8c
-
-          - name: i686-gnu
-            <<: *job-linux-8c
-
-          - name: i686-gnu-nopt
-            <<: *job-linux-8c
-
-          - name: mingw-check
-            <<: *job-linux-4c
-
-          - name: test-various
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu
-            <<: *job-linux-4c
-
-          # This job ensures commits landing on nightly still pass the full
-          # test suite on the stable channel. There are some UI tests that
-          # depend on the channel being built (for example if they include the
-          # channel name on the output), and this builder prevents landing
-          # changes that would result in broken builds after a promotion.
-          - name: x86_64-gnu-stable
-            env:
-              IMAGE: x86_64-gnu
-              RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
-              # Only run this job on the nightly channel. Running this on beta
-              # could cause failures when `dev: 1` in `stage0.txt`, and running
-              # this on stable is useless.
-              CI_ONLY_WHEN_CHANNEL: nightly
-            <<: *job-linux-4c
-
-          - name: x86_64-gnu-aux
-            <<: *job-linux-4c
-
-          - name: x86_64-gnu-integration
-            env:
-              # Only run this job on the nightly channel. Fuchsia requires
-              # nightly features to compile, and this job would fail if
-              # executed on beta and stable.
-              CI_ONLY_WHEN_CHANNEL: nightly
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu-debug
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu-distcheck
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu-llvm-18
-            env:
-              RUST_BACKTRACE: 1
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu-llvm-17
-            env:
-              RUST_BACKTRACE: 1
-            <<: *job-linux-8c
-
-          - name: x86_64-gnu-nopt
-            <<: *job-linux-4c
-
-          - name: x86_64-gnu-tools
-            env:
-              DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
-            <<: *job-linux-8c
-
-          ####################
-          #  macOS Builders  #
-          ####################
-
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
-              RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-macos-xl
-
-          - name: dist-apple-various
-            env:
-              SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim
-              RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            <<: *job-macos-xl
-
-          - name: x86_64-apple-1
-            env: &env-x86_64-apple-tests
-              SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps
-              RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.12
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.12
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            <<: *job-macos-xl
-
-          - name: x86_64-apple-2
-            env:
-              SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps
-              <<: *env-x86_64-apple-tests
-            <<: *job-macos-xl
-
-          # This target only needs to support 11.0 and up as nothing else supports the hardware
-          - name: dist-aarch64-apple
-            env:
-              SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin
-              RUST_CONFIGURE_ARGS: >-
-                --enable-full-tools
-                --enable-sanitizers
-                --enable-profiler
-                --set rust.jemalloc
-                --set llvm.ninja=false
-                --set rust.lto=thin
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              USE_XCODE_CLANG: 1
-              MACOSX_DEPLOYMENT_TARGET: 11.0
-              MACOSX_STD_DEPLOYMENT_TARGET: 11.0
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-macos-m1
-
-          # This target only needs to support 11.0 and up as nothing else supports the hardware
-          - name: aarch64-apple
-            env:
-              SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
-              RUST_CONFIGURE_ARGS: >-
-                --enable-sanitizers
-                --enable-profiler
-                --set rust.jemalloc
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              SELECT_XCODE: /Applications/Xcode_14.3.1.app
-              USE_XCODE_CLANG: 1
-              MACOSX_DEPLOYMENT_TARGET: 11.0
-              MACOSX_STD_DEPLOYMENT_TARGET: 11.0
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            <<: *job-macos-m1
-
-          ######################
-          #  Windows Builders  #
-          ######################
-
-          - name: x86_64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
-              SCRIPT: make ci-msvc
-            <<: *job-windows-8c
-
-          - name: i686-msvc
-            env:
-              RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
-              SCRIPT: make ci-msvc
-            <<: *job-windows-8c
-
-          - name: x86_64-msvc-ext
-            env:
-              SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
-              HOST_TARGET: x86_64-pc-windows-msvc
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json
-              DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
-            <<: *job-windows-8c
-
-          # 32/64-bit MinGW builds.
-          #
-          # We are using MinGW with POSIX threads since LLVM requires
-          # C++'s std::thread which is disabled in libstdc++ with win32 threads.
-          # FIXME: Libc++ doesn't have this limitation so we can avoid
-          # winpthreads if we switch to it.
-          #
-          # Instead of relying on the MinGW version installed on CI we download
-          # and install one ourselves so we won't be surprised by changes to CI's
-          # build image.
-          #
-          # Finally, note that the downloads below are all in the `rust-lang-ci` S3
-          # bucket, but they clearly didn't originate there! The downloads originally
-          # came from the mingw-w64 SourceForge download site. Unfortunately
-          # SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
-
-          - name: i686-mingw
-            env:
-              RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
-              SCRIPT: make ci-mingw
-              # We are intentionally allowing an old toolchain on this builder (and that's
-              # incompatible with LLVM downloads today).
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-            <<: *job-windows-8c
-
-          - name: x86_64-mingw
-            env:
-              SCRIPT: make ci-mingw
-              RUST_CONFIGURE_ARGS: >-
-                --build=x86_64-pc-windows-gnu
-                --enable-profiler
-              # We are intentionally allowing an old toolchain on this builder (and that's
-              # incompatible with LLVM downloads today).
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-            <<: *job-windows-8c
-
-          - name: dist-x86_64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: >-
-                --build=x86_64-pc-windows-msvc
-                --host=x86_64-pc-windows-msvc
-                --target=x86_64-pc-windows-msvc
-                --enable-full-tools
-                --enable-profiler
-                --set rust.codegen-units=1
-              SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-windows-8c
-
-          - name: dist-i686-msvc
-            env:
-              RUST_CONFIGURE_ARGS: >-
-                --build=i686-pc-windows-msvc
-                --host=i686-pc-windows-msvc
-                --target=i686-pc-windows-msvc,i586-pc-windows-msvc
-                --enable-full-tools
-                --enable-profiler
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-windows-8c
-
-          - name: dist-aarch64-msvc
-            env:
-              RUST_CONFIGURE_ARGS: >-
-                --build=x86_64-pc-windows-msvc
-                --host=aarch64-pc-windows-msvc
-                --enable-full-tools
-                --enable-profiler
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-windows-8c
-
-          - name: dist-i686-mingw
-            env:
-              RUST_CONFIGURE_ARGS: >-
-                --build=i686-pc-windows-gnu
-                --enable-full-tools
-                --enable-profiler
-              # We are intentionally allowing an old toolchain on this builder (and that's
-              # incompatible with LLVM downloads today).
-              NO_DOWNLOAD_CI_LLVM: 1
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              CUSTOM_MINGW: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-windows-8c
-
-          - name: dist-x86_64-mingw
-            env:
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-              RUST_CONFIGURE_ARGS: >-
-                --build=x86_64-pc-windows-gnu
-                --enable-full-tools
-                --enable-profiler
-              # We are intentionally allowing an old toolchain on this builder (and that's
-              # incompatible with LLVM downloads today).
-              NO_DOWNLOAD_CI_LLVM: 1
-              CUSTOM_MINGW: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-windows-8c
-
-          - name: dist-x86_64-msvc-alt
-            env:
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
-              SCRIPT: python x.py dist bootstrap --include-default-paths
-            <<: *job-windows-8c
-
-  try:
-    <<: *base-ci-job
-    name: try - ${{ matrix.name }}
-    env:
-      DIST_TRY_BUILD: 1
-      <<: [*shared-ci-variables, *prod-variables]
-    if: github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))
-    strategy:
-      matrix:
-        include:
-          - &dist-x86_64-linux
-            name: dist-x86_64-linux
-            env:
-              CODEGEN_BACKENDS: llvm,cranelift
-            <<: *job-linux-16c
-
+    # GitHub Actions fails the workflow if an empty list of jobs is provided to
+    # the workflow, so we need to skip this job if nothing was produced by
+    # the Python script.
+    #
+    # Unfortunately checking whether a list is empty is not possible in a nice
+    # way due to GitHub Actions expressions limits.
+    # This hack is taken from https://github.com/ferrocene/ferrocene/blob/d43edc6b7697cf1719ec1c17c54904ab94825763/.github/workflows/release.yml#L75-L82
+    if: fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null
 
   master:
     name: master
@@ -791,18 +405,18 @@ jobs:
   # build completed, as there is no practical way to detect when a workflow is
   # successful listening to webhooks only.
   try-success:
-    needs: [try]
+    needs: [ job ]
     if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     <<: *base-success-job
   try-failure:
-    needs: [try]
+    needs: [ job ]
     if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     <<: *base-failure-job
   auto-success:
-    needs: [auto]
+    needs: [ job ]
     if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
     <<: *base-success-job
   auto-failure:
-    needs: [auto]
+    needs: [ job ]
     if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
     <<: *base-failure-job
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 7e89eef2670..ec58bd0924e 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -2,7 +2,7 @@
 # dynamically in CI from ci.yml.
 # You *do not* need to re-run `src/tools/expand-yaml-anchors` when you
 # modify this file.
-shared_defs:
+runners:
   - &base-job
     env: { }
 
@@ -37,14 +37,430 @@ shared_defs:
   - &job-aarch64-linux
     os: [ self-hosted, ARM64, linux ]
 
+envs:
+  production:
+    &production
+    DEPLOY_BUCKET: rust-lang-ci2
+    TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues
+    TOOLSTATE_PUBLISH: 1
+    # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named
+    # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to
+    # rotate them in a single branch while keeping the old key in another
+    # branch, which wouldn't be possible if the key was named with the kind
+    # (caches, artifacts...).
+    CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+    ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+    AWS_REGION: us-west-1
+
+  try:
+    <<: *production
+    DIST_TRY_BUILD: 1
+
+  auto:
+    <<: *production
+
+  pr:
+    PR_CI_JOB: 1
+
+# Jobs that run on each push to a pull request (PR)
+# These jobs automatically inherit envs.pr, to avoid repeating
+# it in each job definition.
 pr:
-  - name: mingw-check
+  - image: mingw-check
     <<: *job-linux-4c
-  - name: mingw-check-tidy
+  - image: mingw-check-tidy
+    continue_on_error: true
     <<: *job-linux-4c
-  - name: x86_64-gnu-llvm-17
+  - image: x86_64-gnu-llvm-17
     env:
       ENABLE_GCC_CODEGEN: "1"
     <<: *job-linux-16c
-  - name: x86_64-gnu-tools
+  - image: x86_64-gnu-tools
+    <<: *job-linux-16c
+
+# Jobs that run when you perform a try build (@bors try)
+# These jobs automatically inherit envs.production, to avoid repeating
+# it in each job definition.
+try:
+  - image: dist-x86_64-linux
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-16c
+
+# Main CI jobs that have to be green to merge a commit into master
+# These jobs automatically inherit envs.production, to avoid repeating
+# it in each job definition.
+auto:
+  #############################
+  #   Linux/Docker builders   #
+  #############################
+
+  - image: aarch64-gnu
+    <<: *job-aarch64-linux
+
+  - image: arm-android
+    <<: *job-linux-8c
+
+  - image: armhf-gnu
+    <<: *job-linux-8c
+
+  - image: dist-aarch64-linux
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-8c
+
+  - image: dist-android
+    <<: *job-linux-8c
+
+  - image: dist-arm-linux
+    <<: *job-linux-16c
+
+  - image: dist-armhf-linux
+    <<: *job-linux-8c
+
+  - image: dist-armv7-linux
+    <<: *job-linux-8c
+
+  - image: dist-i586-gnu-i586-i686-musl
+    <<: *job-linux-8c
+
+  - image: dist-i686-linux
+    <<: *job-linux-8c
+
+  - image: dist-loongarch64-linux
+    <<: *job-linux-8c
+
+  - image: dist-ohos
+    <<: *job-linux-8c
+
+  - image: dist-powerpc-linux
+    <<: *job-linux-8c
+
+  - image: dist-powerpc64-linux
+    <<: *job-linux-8c
+
+  - image: dist-powerpc64le-linux
+    <<: *job-linux-8c
+
+  - image: dist-riscv64-linux
+    <<: *job-linux-8c
+
+  - image: dist-s390x-linux
+    <<: *job-linux-8c
+
+  - image: dist-various-1
+    <<: *job-linux-8c
+
+  - image: dist-various-2
+    <<: *job-linux-8c
+
+  - image: dist-x86_64-freebsd
+    <<: *job-linux-8c
+
+  - image: dist-x86_64-illumos
+    <<: *job-linux-8c
+
+  - image: dist-x86_64-linux
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-16c
+
+  - image: dist-x86_64-linux-alt
+    env:
+      IMAGE: dist-x86_64-linux
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-linux-16c
+
+  - image: dist-x86_64-musl
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-8c
+
+  - image: dist-x86_64-netbsd
+    <<: *job-linux-8c
+
+  - image: i686-gnu
+    <<: *job-linux-8c
+
+  - image: i686-gnu-nopt
+    <<: *job-linux-8c
+
+  - image: mingw-check
+    <<: *job-linux-4c
+
+  - image: test-various
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu
+    <<: *job-linux-4c
+
+  # This job ensures commits landing on nightly still pass the full
+  # test suite on the stable channel. There are some UI tests that
+  # depend on the channel being built (for example if they include the
+  # channel name on the output), and this builder prevents landing
+  # changes that would result in broken builds after a promotion.
+  - image: x86_64-gnu-stable
+    env:
+      IMAGE: x86_64-gnu
+      RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
+      # Only run this job on the nightly channel. Running this on beta
+      # could cause failures when `dev: 1` in `stage0.txt`, and running
+      # this on stable is useless.
+      CI_ONLY_WHEN_CHANNEL: nightly
+    <<: *job-linux-4c
+
+  - image: x86_64-gnu-aux
+    <<: *job-linux-4c
+
+  - image: x86_64-gnu-integration
+    env:
+      # Only run this job on the nightly channel. Fuchsia requires
+      # nightly features to compile, and this job would fail if
+      # executed on beta and stable.
+      CI_ONLY_WHEN_CHANNEL: nightly
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu-debug
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu-distcheck
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu-llvm-18
+    env:
+      RUST_BACKTRACE: 1
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu-llvm-17
+    env:
+      RUST_BACKTRACE: 1
+    <<: *job-linux-8c
+
+  - image: x86_64-gnu-nopt
+    <<: *job-linux-4c
+
+  - image: x86_64-gnu-tools
+    env:
+      DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
+    <<: *job-linux-8c
+
+  ####################
+  #  macOS Builders  #
+  ####################
+
+  - image: dist-x86_64-apple
+    env:
+      SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
+      RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      MACOSX_DEPLOYMENT_TARGET: 10.12
+      SELECT_XCODE: /Applications/Xcode_14.3.1.app
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+      DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-macos-xl
+
+  - image: dist-apple-various
+    env:
+      SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim
+      RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      MACOSX_DEPLOYMENT_TARGET: 10.12
+      SELECT_XCODE: /Applications/Xcode_14.3.1.app
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+    <<: *job-macos-xl
+
+  - image: x86_64-apple-1
+    env: &env-x86_64-apple-tests
+      SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps
+      RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      MACOSX_DEPLOYMENT_TARGET: 10.12
+      MACOSX_STD_DEPLOYMENT_TARGET: 10.12
+      SELECT_XCODE: /Applications/Xcode_14.3.1.app
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+    <<: *job-macos-xl
+
+  - image: x86_64-apple-2
+    env:
+      SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps
+      <<: *env-x86_64-apple-tests
+    <<: *job-macos-xl
+
+  # This target only needs to support 11.0 and up as nothing else supports the hardware
+  - image: dist-aarch64-apple
+    env:
+      SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+      RUST_CONFIGURE_ARGS: >-
+        --enable-full-tools
+        --enable-sanitizers
+        --enable-profiler
+        --set rust.jemalloc
+        --set llvm.ninja=false
+        --set rust.lto=thin
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      SELECT_XCODE: /Applications/Xcode_14.3.1.app
+      USE_XCODE_CLANG: 1
+      MACOSX_DEPLOYMENT_TARGET: 11.0
+      MACOSX_STD_DEPLOYMENT_TARGET: 11.0
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-macos-m1
+
+  # This target only needs to support 11.0 and up as nothing else supports the hardware
+  - image: aarch64-apple
+    env:
+      SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+      RUST_CONFIGURE_ARGS: >-
+        --enable-sanitizers
+        --enable-profiler
+        --set rust.jemalloc
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      SELECT_XCODE: /Applications/Xcode_14.3.1.app
+      USE_XCODE_CLANG: 1
+      MACOSX_DEPLOYMENT_TARGET: 11.0
+      MACOSX_STD_DEPLOYMENT_TARGET: 11.0
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+    <<: *job-macos-m1
+
+  ######################
+  #  Windows Builders  #
+  ######################
+
+  - image: x86_64-msvc
+    env:
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
+      SCRIPT: make ci-msvc
+    <<: *job-windows-8c
+
+  - image: i686-msvc
+    env:
+      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
+      SCRIPT: make ci-msvc
+    <<: *job-windows-8c
+
+  - image: x86_64-msvc-ext
+    env:
+      SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
+      HOST_TARGET: x86_64-pc-windows-msvc
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json
+      DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
+    <<: *job-windows-8c
+
+  # 32/64-bit MinGW builds.
+  #
+  # We are using MinGW with POSIX threads since LLVM requires
+  # C++'s std::thread which is disabled in libstdc++ with win32 threads.
+  # FIXME: Libc++ doesn't have this limitation so we can avoid
+  # winpthreads if we switch to it.
+  #
+  # Instead of relying on the MinGW version installed on CI we download
+  # and install one ourselves so we won't be surprised by changes to CI's
+  # build image.
+  #
+  # Finally, note that the downloads below are all in the `rust-lang-ci` S3
+  # bucket, but they clearly didn't originate there! The downloads originally
+  # came from the mingw-w64 SourceForge download site. Unfortunately
+  # SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
+
+  - image: i686-mingw
+    env:
+      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
+      SCRIPT: make ci-mingw
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+      CUSTOM_MINGW: 1
+    <<: *job-windows-8c
+
+  - image: x86_64-mingw
+    env:
+      SCRIPT: make ci-mingw
+      RUST_CONFIGURE_ARGS: >-
+        --build=x86_64-pc-windows-gnu
+        --enable-profiler
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+      CUSTOM_MINGW: 1
+    <<: *job-windows-8c
+
+  - image: dist-x86_64-msvc
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=x86_64-pc-windows-msvc
+        --host=x86_64-pc-windows-msvc
+        --target=x86_64-pc-windows-msvc
+        --enable-full-tools
+        --enable-profiler
+        --set rust.codegen-units=1
+      SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-windows-8c
+
+  - image: dist-i686-msvc
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=i686-pc-windows-msvc
+        --host=i686-pc-windows-msvc
+        --target=i686-pc-windows-msvc,i586-pc-windows-msvc
+        --enable-full-tools
+        --enable-profiler
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-windows-8c
+
+  - image: dist-aarch64-msvc
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=x86_64-pc-windows-msvc
+        --host=aarch64-pc-windows-msvc
+        --enable-full-tools
+        --enable-profiler
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-windows-8c
+
+  - image: dist-i686-mingw
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=i686-pc-windows-gnu
+        --enable-full-tools
+        --enable-profiler
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      CUSTOM_MINGW: 1
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-windows-8c
+
+  - image: dist-x86_64-mingw
+    env:
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      RUST_CONFIGURE_ARGS: >-
+        --build=x86_64-pc-windows-gnu
+        --enable-full-tools
+        --enable-profiler
+      # We are intentionally allowing an old toolchain on this builder (and that's
+      # incompatible with LLVM downloads today).
+      NO_DOWNLOAD_CI_LLVM: 1
+      CUSTOM_MINGW: 1
+      DIST_REQUIRE_ALL_TOOLS: 1
+    <<: *job-windows-8c
+
+  - image: dist-x86_64-msvc-alt
+    env:
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+    <<: *job-windows-8c
diff --git a/src/ci/scripts/calculate-job-matrix.py b/src/ci/scripts/calculate-job-matrix.py
deleted file mode 100755
index 9b1e74c23c3..00000000000
--- a/src/ci/scripts/calculate-job-matrix.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-This script serves for generating a matrix of jobs that should
-be executed on CI.
-
-It reads job definitions from `src/ci/github-actions/jobs.yml`
-and filters them based on the event that happened on CI.
-
-Currently, it only supports PR builds.
-"""
-
-import json
-from pathlib import Path
-
-import yaml
-
-JOBS_YAML_PATH = Path(__file__).absolute().parent.parent / "github-actions" / "jobs.yml"
-
-
-if __name__ == "__main__":
-    with open(JOBS_YAML_PATH) as f:
-        jobs = yaml.safe_load(f)
-    job_output = jobs["pr"]
-    print(f"jobs={json.dumps(job_output)}")
diff --git a/src/doc/unstable-book/src/language-features/coroutines.md b/src/doc/unstable-book/src/language-features/coroutines.md
index f8e5a22fbd5..9fb07594650 100644
--- a/src/doc/unstable-book/src/language-features/coroutines.md
+++ b/src/doc/unstable-book/src/language-features/coroutines.md
@@ -26,13 +26,13 @@ tweaks to the overall design.
 A syntactical example of a coroutine is:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
@@ -48,7 +48,8 @@ fn main() {
 }
 ```
 
-Coroutines are closure-like literals which can contain a `yield` statement. The
+Coroutines are closure-like literals which are annotated with `#[coroutine]`
+and can contain a `yield` statement. The
 `yield` statement takes an optional expression of a value to yield out of the
 coroutine. All coroutine literals implement the `Coroutine` trait in the
 `std::ops` module. The `Coroutine` trait has one main method, `resume`, which
@@ -58,13 +59,13 @@ An example of the control flow of coroutines is that the following example
 prints all numbers in order:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         println!("2");
         yield;
         println!("4");
@@ -78,9 +79,9 @@ fn main() {
 }
 ```
 
-At this time the main intended use case of coroutines is an implementation
-primitive for async/await syntax, but coroutines will likely be extended to
-ergonomic implementations of iterators and other primitives in the future.
+At this time the main use case of coroutines is an implementation
+primitive for `async`/`await` and `gen` syntax, but coroutines
+will likely be extended to other primitives in the future.
 Feedback on the design and usage is always appreciated!
 
 ### The `Coroutine` trait
@@ -163,14 +164,14 @@ which point all state is saved off in the coroutine and a value is returned.
 Let's take a look at an example to see what's going on here:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
     let ret = "foo";
-    let mut coroutine = move || {
+    let mut coroutine = #[coroutine] move || {
         yield 1;
         return ret
     };
@@ -183,7 +184,7 @@ fn main() {
 This coroutine literal will compile down to something similar to:
 
 ```rust
-#![feature(arbitrary_self_types, coroutines, coroutine_trait)]
+#![feature(arbitrary_self_types, coroutine_trait)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md
index 5f0f7547a0a..c6f54d79cfc 100644
--- a/src/doc/unstable-book/src/language-features/inline-const-pat.md
+++ b/src/doc/unstable-book/src/language-features/inline-const-pat.md
@@ -2,8 +2,6 @@
 
 The tracking issue for this feature is: [#76001]
 
-See also [`inline_const`](inline-const.md)
-
 ------
 
 This feature allows you to use inline constant expressions in pattern position:
diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md
deleted file mode 100644
index 7be70eed6ce..00000000000
--- a/src/doc/unstable-book/src/language-features/inline-const.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# `inline_const`
-
-The tracking issue for this feature is: [#76001]
-
-See also [`inline_const_pat`](inline-const-pat.md)
-
-------
-
-This feature allows you to use inline constant expressions. For example, you can
-turn this code:
-
-```rust
-# fn add_one(x: i32) -> i32 { x + 1 }
-const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4;
-
-fn main() {
-    let x = add_one(MY_COMPUTATION);
-}
-```
-
-into this code:
-
-```rust
-#![feature(inline_const)]
-
-# fn add_one(x: i32) -> i32 { x + 1 }
-fn main() {
-    let x = add_one(const { 1 + 2 * 3 / 4 });
-}
-```
-
-[#76001]: https://github.com/rust-lang/rust/issues/76001
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
index 0f4fb405669..63134f7ae28 100644
--- a/src/doc/unstable-book/src/the-unstable-book.md
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -5,13 +5,13 @@ each one organized by a "feature flag." That is, when using an unstable
 feature of Rust, you must use a flag, like this:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
index 4ae75544c60..232bccf6a15 100644
--- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const)]
 #![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
index 120f5c35cb0..5ce2ed2ffae 100644
--- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
@@ -1,5 +1,5 @@
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:27:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:26:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -9,7 +9,7 @@ LL |     x[index];
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:42:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:41:5
    |
 LL |     v[0];
    |     ^^^^
@@ -17,7 +17,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:42:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -25,7 +25,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:44:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:50:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:49:5
    |
 LL |     v[N];
    |     ^^^^
@@ -41,7 +41,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui-toml/suppress_lint_in_const/test.rs:51:5
+  --> tests/ui-toml/suppress_lint_in_const/test.rs:50:5
    |
 LL |     v[M];
    |     ^^^^
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index b454c29aef4..fdec14a1528 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -10,7 +10,7 @@
     arithmetic_overflow,
     unconditional_panic
 )]
-#![feature(const_mut_refs, inline_const)]
+#![feature(const_mut_refs)]
 #![warn(clippy::arithmetic_side_effects)]
 
 extern crate proc_macro_derive;
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
index 167263d31df..f7dad28b036 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
@@ -1,4 +1,4 @@
-#![feature(let_chains, inline_const)]
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
index f3f055eb7f0..d22871d2c8f 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
@@ -1,4 +1,4 @@
-#![feature(let_chains, inline_const)]
+#![feature(let_chains)]
 #![warn(clippy::bool_to_int_with_if)]
 #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
 
diff --git a/src/tools/clippy/tests/ui/const_is_empty.rs b/src/tools/clippy/tests/ui/const_is_empty.rs
index ae37a82e4f9..04e0de91ecf 100644
--- a/src/tools/clippy/tests/ui/const_is_empty.rs
+++ b/src/tools/clippy/tests/ui/const_is_empty.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const)]
 #![warn(clippy::const_is_empty)]
 #![allow(clippy::needless_late_init, unused_must_use)]
 
diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr
index 0e09da77bb4..7f80b520b1a 100644
--- a/src/tools/clippy/tests/ui/const_is_empty.stderr
+++ b/src/tools/clippy/tests/ui/const_is_empty.stderr
@@ -1,5 +1,5 @@
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:6:8
+  --> tests/ui/const_is_empty.rs:5:8
    |
 LL |     if "".is_empty() {
    |        ^^^^^^^^^^^^^
@@ -8,151 +8,151 @@ LL |     if "".is_empty() {
    = help: to override `-D warnings` add `#[allow(clippy::const_is_empty)]`
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:9:8
+  --> tests/ui/const_is_empty.rs:8:8
    |
 LL |     if "foobar".is_empty() {
    |        ^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:15:8
+  --> tests/ui/const_is_empty.rs:14:8
    |
 LL |     if b"".is_empty() {
    |        ^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:18:8
+  --> tests/ui/const_is_empty.rs:17:8
    |
 LL |     if b"foobar".is_empty() {
    |        ^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:35:8
+  --> tests/ui/const_is_empty.rs:34:8
    |
 LL |     if empty2.is_empty() {
    |        ^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:38:8
+  --> tests/ui/const_is_empty.rs:37:8
    |
 LL |     if non_empty2.is_empty() {
    |        ^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:60:13
+  --> tests/ui/const_is_empty.rs:59:13
    |
 LL |     let _ = EMPTY_STR.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:62:13
+  --> tests/ui/const_is_empty.rs:61:13
    |
 LL |     let _ = NON_EMPTY_STR.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:64:13
+  --> tests/ui/const_is_empty.rs:63:13
    |
 LL |     let _ = EMPTY_BSTR.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:66:13
+  --> tests/ui/const_is_empty.rs:65:13
    |
 LL |     let _ = NON_EMPTY_BSTR.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:68:13
+  --> tests/ui/const_is_empty.rs:67:13
    |
 LL |     let _ = EMPTY_ARRAY.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:70:13
+  --> tests/ui/const_is_empty.rs:69:13
    |
 LL |     let _ = EMPTY_ARRAY_REPEAT.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:72:13
+  --> tests/ui/const_is_empty.rs:71:13
    |
 LL |     let _ = EMPTY_U8_SLICE.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:74:13
+  --> tests/ui/const_is_empty.rs:73:13
    |
 LL |     let _ = NON_EMPTY_U8_SLICE.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:76:13
+  --> tests/ui/const_is_empty.rs:75:13
    |
 LL |     let _ = NON_EMPTY_ARRAY.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:78:13
+  --> tests/ui/const_is_empty.rs:77:13
    |
 LL |     let _ = NON_EMPTY_ARRAY_REPEAT.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:80:13
+  --> tests/ui/const_is_empty.rs:79:13
    |
 LL |     let _ = EMPTY_REF_ARRAY.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:82:13
+  --> tests/ui/const_is_empty.rs:81:13
    |
 LL |     let _ = NON_EMPTY_REF_ARRAY.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:84:13
+  --> tests/ui/const_is_empty.rs:83:13
    |
 LL |     let _ = EMPTY_SLICE.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:86:13
+  --> tests/ui/const_is_empty.rs:85:13
    |
 LL |     let _ = NON_EMPTY_SLICE.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:88:13
+  --> tests/ui/const_is_empty.rs:87:13
    |
 LL |     let _ = NON_EMPTY_SLICE_REPEAT.is_empty();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:94:13
+  --> tests/ui/const_is_empty.rs:93:13
    |
 LL |     let _ = value.is_empty();
    |             ^^^^^^^^^^^^^^^^
 
 error: this expression always evaluates to false
-  --> tests/ui/const_is_empty.rs:97:13
+  --> tests/ui/const_is_empty.rs:96:13
    |
 LL |     let _ = x.is_empty();
    |             ^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:99:13
+  --> tests/ui/const_is_empty.rs:98:13
    |
 LL |     let _ = "".is_empty();
    |             ^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:101:13
+  --> tests/ui/const_is_empty.rs:100:13
    |
 LL |     let _ = b"".is_empty();
    |             ^^^^^^^^^^^^^^
 
 error: this expression always evaluates to true
-  --> tests/ui/const_is_empty.rs:155:13
+  --> tests/ui/const_is_empty.rs:154:13
    |
 LL |     let _ = val.is_empty();
    |             ^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5238.rs b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
index b1fc3fb9d25..fe03a39ad1b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5238.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
@@ -1,9 +1,9 @@
 // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let _ = || {
+    let _ = #[coroutine] || {
         yield;
     };
 }
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 27ee2f91594..2e726141649 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -1,6 +1,5 @@
 //@compile-flags: -Zdeduplicate-diagnostics=yes
 
-#![feature(inline_const)]
 #![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index 5f62ec9b556..386f91becf1 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -1,5 +1,5 @@
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:16:20
+  --> tests/ui/indexing_slicing_index.rs:15:20
    |
 LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |                    ^^^^^^^^^^
@@ -10,19 +10,19 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error[E0080]: evaluation of `main::{constant#3}` failed
-  --> tests/ui/indexing_slicing_index.rs:48:14
+  --> tests/ui/indexing_slicing_index.rs:47:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant encountered
-  --> tests/ui/indexing_slicing_index.rs:48:5
+  --> tests/ui/indexing_slicing_index.rs:47:5
    |
 LL |     const { &ARR[idx4()] };
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:29:5
+  --> tests/ui/indexing_slicing_index.rs:28:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -30,7 +30,7 @@ LL |     x[index];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:32:5
+  --> tests/ui/indexing_slicing_index.rs:31:5
    |
 LL |     x[4];
    |     ^^^^
@@ -39,13 +39,13 @@ LL |     x[4];
    = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:34:5
+  --> tests/ui/indexing_slicing_index.rs:33:5
    |
 LL |     x[1 << 3];
    |     ^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:45:14
+  --> tests/ui/indexing_slicing_index.rs:44:14
    |
 LL |     const { &ARR[idx()] };
    |              ^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |     const { &ARR[idx()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:48:14
+  --> tests/ui/indexing_slicing_index.rs:47:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^
@@ -63,13 +63,13 @@ LL |     const { &ARR[idx4()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:55:5
+  --> tests/ui/indexing_slicing_index.rs:54:5
    |
 LL |     y[4];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:58:5
+  --> tests/ui/indexing_slicing_index.rs:57:5
    |
 LL |     v[0];
    |     ^^^^
@@ -77,7 +77,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:60:5
+  --> tests/ui/indexing_slicing_index.rs:59:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -85,7 +85,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:62:5
+  --> tests/ui/indexing_slicing_index.rs:61:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -93,13 +93,13 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:70:5
+  --> tests/ui/indexing_slicing_index.rs:69:5
    |
 LL |     x[N];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:73:5
+  --> tests/ui/indexing_slicing_index.rs:72:5
    |
 LL |     v[N];
    |     ^^^^
@@ -107,7 +107,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:75:5
+  --> tests/ui/indexing_slicing_index.rs:74:5
    |
 LL |     v[M];
    |     ^^^^
@@ -115,7 +115,7 @@ LL |     v[M];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:79:13
+  --> tests/ui/indexing_slicing_index.rs:78:13
    |
 LL |     let _ = x[4];
    |             ^^^^
diff --git a/src/tools/clippy/tests/ui/large_futures.fixed b/src/tools/clippy/tests/ui/large_futures.fixed
index aa8c3021b97..1e87859f452 100644
--- a/src/tools/clippy/tests/ui/large_futures.fixed
+++ b/src/tools/clippy/tests/ui/large_futures.fixed
@@ -1,4 +1,3 @@
-#![feature(coroutines)]
 #![warn(clippy::large_futures)]
 #![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs
index fc6ea458d3d..3f4ea2ebf8b 100644
--- a/src/tools/clippy/tests/ui/large_futures.rs
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -1,4 +1,3 @@
-#![feature(coroutines)]
 #![warn(clippy::large_futures)]
 #![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
index 5709c7b77a0..00082e579c5 100644
--- a/src/tools/clippy/tests/ui/large_futures.stderr
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -1,5 +1,5 @@
 error: large future with a size of 16385 bytes
-  --> tests/ui/large_futures.rs:11:9
+  --> tests/ui/large_futures.rs:10:9
    |
 LL |         big_fut([0u8; 1024 * 16]).await;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
@@ -8,37 +8,37 @@ LL |         big_fut([0u8; 1024 * 16]).await;
    = help: to override `-D warnings` add `#[allow(clippy::large_futures)]`
 
 error: large future with a size of 16386 bytes
-  --> tests/ui/large_futures.rs:15:5
+  --> tests/ui/large_futures.rs:14:5
    |
 LL |     f.await
    |     ^ help: consider `Box::pin` on it: `Box::pin(f)`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:20:9
+  --> tests/ui/large_futures.rs:19:9
    |
 LL |         wait().await;
    |         ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:25:13
+  --> tests/ui/large_futures.rs:24:13
    |
 LL |             wait().await;
    |             ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:33:5
+  --> tests/ui/large_futures.rs:32:5
    |
 LL |     foo().await;
    |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
 
 error: large future with a size of 49159 bytes
-  --> tests/ui/large_futures.rs:35:5
+  --> tests/ui/large_futures.rs:34:5
    |
 LL |     calls_fut(fut).await;
    |     ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:48:5
+  --> tests/ui/large_futures.rs:47:5
    |
 LL | /     async {
 LL | |
@@ -59,7 +59,7 @@ LL +     })
    |
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:60:13
+  --> tests/ui/large_futures.rs:59:13
    |
 LL | /             async {
 LL | |                 let x = [0i32; 1024 * 16];
diff --git a/src/tools/clippy/tests/ui/manual_float_methods.rs b/src/tools/clippy/tests/ui/manual_float_methods.rs
index f3e95d6807d..80781ecda72 100644
--- a/src/tools/clippy/tests/ui/manual_float_methods.rs
+++ b/src/tools/clippy/tests/ui/manual_float_methods.rs
@@ -2,7 +2,6 @@
 //@aux-build:proc_macros.rs
 #![allow(clippy::needless_if, unused)]
 #![warn(clippy::manual_is_infinite, clippy::manual_is_finite)]
-#![feature(inline_const)]
 
 #[macro_use]
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/manual_float_methods.stderr b/src/tools/clippy/tests/ui/manual_float_methods.stderr
index dae96839262..930df0b97cb 100644
--- a/src/tools/clippy/tests/ui/manual_float_methods.stderr
+++ b/src/tools/clippy/tests/ui/manual_float_methods.stderr
@@ -1,5 +1,5 @@
 error: manually checking if a float is infinite
-  --> tests/ui/manual_float_methods.rs:23:8
+  --> tests/ui/manual_float_methods.rs:22:8
    |
 LL |     if x == f32::INFINITY || x == f32::NEG_INFINITY {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()`
@@ -8,7 +8,7 @@ LL |     if x == f32::INFINITY || x == f32::NEG_INFINITY {}
    = help: to override `-D warnings` add `#[allow(clippy::manual_is_infinite)]`
 
 error: manually checking if a float is finite
-  --> tests/ui/manual_float_methods.rs:24:8
+  --> tests/ui/manual_float_methods.rs:23:8
    |
 LL |     if x != f32::INFINITY && x != f32::NEG_INFINITY {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,13 +29,13 @@ LL |     if !x.is_infinite() {}
    |        ~~~~~~~~~~~~~~~~
 
 error: manually checking if a float is infinite
-  --> tests/ui/manual_float_methods.rs:25:8
+  --> tests/ui/manual_float_methods.rs:24:8
    |
 LL |     if x == INFINITE || x == NEG_INFINITE {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()`
 
 error: manually checking if a float is finite
-  --> tests/ui/manual_float_methods.rs:26:8
+  --> tests/ui/manual_float_methods.rs:25:8
    |
 LL |     if x != INFINITE && x != NEG_INFINITE {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,13 +54,13 @@ LL |     if !x.is_infinite() {}
    |        ~~~~~~~~~~~~~~~~
 
 error: manually checking if a float is infinite
-  --> tests/ui/manual_float_methods.rs:28:8
+  --> tests/ui/manual_float_methods.rs:27:8
    |
 LL |     if x == f64::INFINITY || x == f64::NEG_INFINITY {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()`
 
 error: manually checking if a float is finite
-  --> tests/ui/manual_float_methods.rs:29:8
+  --> tests/ui/manual_float_methods.rs:28:8
    |
 LL |     if x != f64::INFINITY && x != f64::NEG_INFINITY {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 92f173d9db4..93c69209c69 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -1,4 +1,4 @@
-#![feature(inline_const, try_blocks)]
+#![feature(try_blocks)]
 #![allow(
     clippy::eq_op,
     clippy::single_match,
diff --git a/src/tools/clippy/tests/ui/panicking_macros.rs b/src/tools/clippy/tests/ui/panicking_macros.rs
index dccfbd409e5..2bbf5792ec4 100644
--- a/src/tools/clippy/tests/ui/panicking_macros.rs
+++ b/src/tools/clippy/tests/ui/panicking_macros.rs
@@ -1,5 +1,4 @@
 #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::let_unit_value)]
-#![feature(inline_const)]
 #![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)]
 
 extern crate core;
diff --git a/src/tools/clippy/tests/ui/panicking_macros.stderr b/src/tools/clippy/tests/ui/panicking_macros.stderr
index 06025859c0c..7c0f0a7d376 100644
--- a/src/tools/clippy/tests/ui/panicking_macros.stderr
+++ b/src/tools/clippy/tests/ui/panicking_macros.stderr
@@ -1,5 +1,5 @@
 error: `panic` should not be present in production code
-  --> tests/ui/panicking_macros.rs:23:5
+  --> tests/ui/panicking_macros.rs:22:5
    |
 LL |     panic!();
    |     ^^^^^^^^
@@ -8,19 +8,19 @@ LL |     panic!();
    = help: to override `-D warnings` add `#[allow(clippy::panic)]`
 
 error: `panic` should not be present in production code
-  --> tests/ui/panicking_macros.rs:26:5
+  --> tests/ui/panicking_macros.rs:25:5
    |
 LL |     panic!("message");
    |     ^^^^^^^^^^^^^^^^^
 
 error: `panic` should not be present in production code
-  --> tests/ui/panicking_macros.rs:28:5
+  --> tests/ui/panicking_macros.rs:27:5
    |
 LL |     panic!("{} {}", "panic with", "multiple arguments");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `todo` should not be present in production code
-  --> tests/ui/panicking_macros.rs:35:5
+  --> tests/ui/panicking_macros.rs:34:5
    |
 LL |     todo!();
    |     ^^^^^^^
@@ -29,19 +29,19 @@ LL |     todo!();
    = help: to override `-D warnings` add `#[allow(clippy::todo)]`
 
 error: `todo` should not be present in production code
-  --> tests/ui/panicking_macros.rs:38:5
+  --> tests/ui/panicking_macros.rs:37:5
    |
 LL |     todo!("message");
    |     ^^^^^^^^^^^^^^^^
 
 error: `todo` should not be present in production code
-  --> tests/ui/panicking_macros.rs:40:5
+  --> tests/ui/panicking_macros.rs:39:5
    |
 LL |     todo!("{} {}", "panic with", "multiple arguments");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `unimplemented` should not be present in production code
-  --> tests/ui/panicking_macros.rs:47:5
+  --> tests/ui/panicking_macros.rs:46:5
    |
 LL |     unimplemented!();
    |     ^^^^^^^^^^^^^^^^
@@ -50,19 +50,19 @@ LL |     unimplemented!();
    = help: to override `-D warnings` add `#[allow(clippy::unimplemented)]`
 
 error: `unimplemented` should not be present in production code
-  --> tests/ui/panicking_macros.rs:50:5
+  --> tests/ui/panicking_macros.rs:49:5
    |
 LL |     unimplemented!("message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `unimplemented` should not be present in production code
-  --> tests/ui/panicking_macros.rs:52:5
+  --> tests/ui/panicking_macros.rs:51:5
    |
 LL |     unimplemented!("{} {}", "panic with", "multiple arguments");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: usage of the `unreachable!` macro
-  --> tests/ui/panicking_macros.rs:59:5
+  --> tests/ui/panicking_macros.rs:58:5
    |
 LL |     unreachable!();
    |     ^^^^^^^^^^^^^^
@@ -71,37 +71,37 @@ LL |     unreachable!();
    = help: to override `-D warnings` add `#[allow(clippy::unreachable)]`
 
 error: usage of the `unreachable!` macro
-  --> tests/ui/panicking_macros.rs:62:5
+  --> tests/ui/panicking_macros.rs:61:5
    |
 LL |     unreachable!("message");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: usage of the `unreachable!` macro
-  --> tests/ui/panicking_macros.rs:64:5
+  --> tests/ui/panicking_macros.rs:63:5
    |
 LL |     unreachable!("{} {}", "panic with", "multiple arguments");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `panic` should not be present in production code
-  --> tests/ui/panicking_macros.rs:71:5
+  --> tests/ui/panicking_macros.rs:70:5
    |
 LL |     panic!();
    |     ^^^^^^^^
 
 error: `todo` should not be present in production code
-  --> tests/ui/panicking_macros.rs:73:5
+  --> tests/ui/panicking_macros.rs:72:5
    |
 LL |     todo!();
    |     ^^^^^^^
 
 error: `unimplemented` should not be present in production code
-  --> tests/ui/panicking_macros.rs:75:5
+  --> tests/ui/panicking_macros.rs:74:5
    |
 LL |     unimplemented!();
    |     ^^^^^^^^^^^^^^^^
 
 error: usage of the `unreachable!` macro
-  --> tests/ui/panicking_macros.rs:77:5
+  --> tests/ui/panicking_macros.rs:76:5
    |
 LL |     unreachable!();
    |     ^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index f6909828aa9..e9d77182a91 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -1,7 +1,7 @@
 //@aux-build:proc_macros.rs
 #![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
 #![warn(clippy::redundant_locals)]
-#![feature(async_closure, coroutines)]
+#![feature(async_closure, coroutines, stmt_expr_attributes)]
 
 extern crate proc_macros;
 use proc_macros::{external, with_span};
@@ -191,11 +191,11 @@ fn issue12225() {
         let v4 = v4;
         dbg!(&v4);
     });
-    assert_static(static || {
+    assert_static(#[coroutine] static || {
         let v5 = v5;
         yield;
     });
-    assert_static(|| {
+    assert_static(#[coroutine] || {
         let v6 = v6;
         yield;
     });
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index e1c0da9118d..44727e01ea2 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -12,7 +12,6 @@
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(trait_upcasting)]
-#![feature(absolute_path)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
index 005ae7e9132..8648be2a264 100644
--- a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
+++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     ops::{Coroutine, CoroutineState},
@@ -7,7 +7,7 @@ use std::{
 };
 
 fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
-    static move || {
+    #[coroutine] static move || {
         let mut num = 0;
         let num = &mut num;
         *num += 0;
diff --git a/src/tools/miri/tests/pass/coroutine.rs b/src/tools/miri/tests/pass/coroutine.rs
index 7e1f64df04d..e76abfc4185 100644
--- a/src/tools/miri/tests/pass/coroutine.rs
+++ b/src/tools/miri/tests/pass/coroutine.rs
@@ -1,6 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(coroutines, coroutine_trait, never_type)]
+#![feature(coroutines, coroutine_trait, never_type, stmt_expr_attributes)]
 
 use std::fmt::Debug;
 use std::mem::ManuallyDrop;
@@ -43,9 +43,9 @@ fn basic() {
         panic!()
     }
 
-    finish(1, false, || yield 1);
+    finish(1, false, #[coroutine] || yield 1);
 
-    finish(3, false, || {
+    finish(3, false, #[coroutine] || {
         let mut x = 0;
         yield 1;
         x += 1;
@@ -55,27 +55,27 @@ fn basic() {
         assert_eq!(x, 2);
     });
 
-    finish(7 * 8 / 2, false, || {
+    finish(7 * 8 / 2, false, #[coroutine] || {
         for i in 0..8 {
             yield i;
         }
     });
 
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         if true {
             yield 1;
         } else {
         }
     });
 
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         if false {
         } else {
             yield 1;
         }
     });
 
-    finish(2, false, || {
+    finish(2, false, #[coroutine] || {
         if {
             yield 1;
             false
@@ -88,7 +88,7 @@ fn basic() {
 
     // also test self-referential coroutines
     assert_eq!(
-        finish(5, true, static || {
+        finish(5, true, #[coroutine] static || {
             let mut x = 5;
             let y = &mut x;
             *y = 5;
@@ -99,7 +99,7 @@ fn basic() {
         10
     );
     assert_eq!(
-        finish(5, true, || {
+        finish(5, true, #[coroutine] || {
             let mut x = Box::new(5);
             let y = &mut *x;
             *y = 5;
@@ -111,7 +111,7 @@ fn basic() {
     );
 
     let b = true;
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         yield 1;
         if b {
             return;
@@ -123,7 +123,7 @@ fn basic() {
         drop(x);
     });
 
-    finish(3, false, || {
+    finish(3, false, #[coroutine] || {
         yield 1;
         #[allow(unreachable_code)]
         let _x: (String, !) = (String::new(), {
@@ -172,7 +172,7 @@ fn smoke_resume_arg() {
     }
 
     drain(
-        &mut |mut b| {
+        &mut #[coroutine] |mut b| {
             while b != 0 {
                 b = yield (b + 1);
             }
@@ -181,21 +181,21 @@ fn smoke_resume_arg() {
         vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))],
     );
 
-    expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))]));
+    expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))]));
 
     expect_drops(6, || {
         drain(
-            &mut |a| yield yield a,
+            &mut #[coroutine] |a| yield yield a,
             vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))],
         )
     });
 
     #[allow(unreachable_code)]
-    expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))]));
+    expect_drops(2, || drain(&mut #[coroutine] |a| yield return a, vec![(DropMe, Complete(DropMe))]));
 
     expect_drops(2, || {
         drain(
-            &mut |a: DropMe| {
+            &mut #[coroutine] |a: DropMe| {
                 if false { yield () } else { a }
             },
             vec![(DropMe, Complete(DropMe))],
@@ -205,7 +205,7 @@ fn smoke_resume_arg() {
     expect_drops(4, || {
         drain(
             #[allow(unused_assignments, unused_variables)]
-            &mut |mut a: DropMe| {
+            &mut #[coroutine] |mut a: DropMe| {
                 a = yield;
                 a = yield;
                 a = yield;
@@ -228,7 +228,7 @@ fn uninit_fields() {
     }
 
     fn run<T>(x: bool, y: bool) {
-        let mut c = || {
+        let mut c = #[coroutine] || {
             if x {
                 let _a: T;
                 if y {
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs
index cdb441b450b..1fc713d48dc 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/portable-simd.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-strict-provenance
-#![feature(portable_simd, adt_const_params, inline_const, core_intrinsics)]
+#![feature(portable_simd, adt_const_params, core_intrinsics)]
 #![allow(incomplete_features, internal_features)]
 use std::intrinsics::simd as intrinsics;
 use std::ptr;
diff --git a/src/tools/miri/tests/pass/shims/path.rs b/src/tools/miri/tests/pass/shims/path.rs
index 9fc6e7faefb..cadbeb476bd 100644
--- a/src/tools/miri/tests/pass/shims/path.rs
+++ b/src/tools/miri/tests/pass/shims/path.rs
@@ -1,5 +1,4 @@
 //@compile-flags: -Zmiri-disable-isolation
-#![feature(absolute_path)]
 use std::path::{absolute, Path};
 
 #[track_caller]
diff --git a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
index c4b15c8758b..bb98e024a0a 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
@@ -1,6 +1,6 @@
 // See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
 // this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     ops::{Coroutine, CoroutineState},
@@ -8,7 +8,7 @@ use std::{
 };
 
 fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
-    static move || {
+    #[coroutine] static move || {
         let mut num = 0;
         let num = &mut num;
 
diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs
index d88bcc98858..c3803af3cc8 100644
--- a/src/tools/miri/tests/pass/track-caller-attribute.rs
+++ b/src/tools/miri/tests/pass/track-caller-attribute.rs
@@ -232,7 +232,7 @@ fn test_coroutine() {
     }
 
     #[rustfmt::skip]
-    let coroutine = #[track_caller] |arg: String| {
+    let coroutine = #[track_caller] #[coroutine] |arg: String| {
         yield ("first", arg.clone(), Location::caller());
         yield ("second", arg.clone(), Location::caller());
     };
@@ -255,7 +255,7 @@ fn test_coroutine() {
     assert_eq!(mono_loc.column(), 42);
 
     #[rustfmt::skip]
-    let non_tracked_coroutine = || { yield Location::caller(); };
+    let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); };
     let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
     let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
         CoroutineState::Yielded(val) => val,
@@ -263,7 +263,7 @@ fn test_coroutine() {
     };
     assert_eq!(non_tracked_loc.file(), file!());
     assert_eq!(non_tracked_loc.line(), non_tracked_line);
-    assert_eq!(non_tracked_loc.column(), 44);
+    assert_eq!(non_tracked_loc.column(), 57);
 }
 
 fn main() {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index d50088e6cf1..c92d4e78ffa 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -3869,7 +3869,7 @@ use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
@@ -3901,7 +3901,7 @@ use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         println!("2");
         yield;
         println!("4");
@@ -4007,7 +4007,7 @@ use std::pin::Pin;
 
 fn main() {
     let ret = "foo";
-    let mut coroutine = move || {
+    let mut coroutine = #[coroutine] move || {
         yield 1;
         return ret
     };
diff --git a/src/tools/rustfmt/tests/source/immovable_coroutines.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
index 3b94af0c96c..539049577a0 100644
--- a/src/tools/rustfmt/tests/source/immovable_coroutines.rs
+++ b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || { 
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }
diff --git a/src/tools/rustfmt/tests/target/immovable_coroutines.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
index f52cfa00f97..539049577a0 100644
--- a/src/tools/rustfmt/tests/target/immovable_coroutines.rs
+++ b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || {
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index f0ed0ae806f..93188b4fbae 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -317,7 +317,6 @@ run-make/unstable-flag-required/Makefile
 run-make/use-suggestions-rust-2018/Makefile
 run-make/used-cdylib-macos/Makefile
 run-make/used/Makefile
-run-make/valid-print-requests/Makefile
 run-make/volatile-intrinsics/Makefile
 run-make/wasm-exceptions-nostd/Makefile
 run-make/wasm-override-linker/Makefile
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs
index 12339cb4415..51b4dc4e169 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs
@@ -37,23 +37,9 @@ pub fn array_char(f: fn(*const char)) {
     f(&b as *const _);
     f(&c as *const _);
 
-    // Any type of local array variable leads to stack protection with the
-    // "strong" heuristic. The 'basic' heuristic only adds stack protection to
-    // functions with local array variables of a byte-sized type, however. Since
-    // 'char' is 4 bytes in Rust, this function is not protected by the 'basic'
-    // heuristic
-    //
-    // (This test *also* takes the address of the local stack variables. We
-    // cannot know that this isn't what triggers the `strong` heuristic.
-    // However, the test strategy of passing the address of a stack array to an
-    // external function is sufficient to trigger the `basic` heuristic (see
-    // test `array_u8_large()`). Since the `basic` heuristic only checks for the
-    // presence of stack-local array variables, we can be confident that this
-    // test also captures this part of the `strong` heuristic specification.)
-
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
@@ -231,8 +217,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
     // Even though the local variable conceptually doesn't have its address
     // taken, it's so large that the "move" is implemented with a reference to a
     // stack-local variable in the ABI. Consequently, this function *is*
-    // protected by the `strong` heuristic. This is also the case for
-    // rvalue-references in C++, regardless of struct size:
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -246,7 +232,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
 
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
@@ -259,9 +245,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
     // A new instance of `Gigastruct` is passed to `f()`, without any apparent
     // connection to this stack frame. Still, since instances of `Gigastruct`
     // are sufficiently large, it is allocated in the caller stack frame and
-    // passed as a pointer. As such, this function is *also* protected by the
-    // `strong` heuristic, just like `local_large_var_moved`. This is also the
-    // case for pass-by-value of sufficiently large structs in C++:
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -276,7 +262,7 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
 
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs
index 46c77511251..c5915262c09 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs
@@ -37,23 +37,9 @@ pub fn array_char(f: fn(*const char)) {
     f(&b as *const _);
     f(&c as *const _);
 
-    // Any type of local array variable leads to stack protection with the
-    // "strong" heuristic. The 'basic' heuristic only adds stack protection to
-    // functions with local array variables of a byte-sized type, however. Since
-    // 'char' is 4 bytes in Rust, this function is not protected by the 'basic'
-    // heuristic
-    //
-    // (This test *also* takes the address of the local stack variables. We
-    // cannot know that this isn't what triggers the `strong` heuristic.
-    // However, the test strategy of passing the address of a stack array to an
-    // external function is sufficient to trigger the `basic` heuristic (see
-    // test `array_u8_large()`). Since the `basic` heuristic only checks for the
-    // presence of stack-local array variables, we can be confident that this
-    // test also captures this part of the `strong` heuristic specification.)
-
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
@@ -239,8 +225,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
     // Even though the local variable conceptually doesn't have its address
     // taken, it's so large that the "move" is implemented with a reference to a
     // stack-local variable in the ABI. Consequently, this function *is*
-    // protected by the `strong` heuristic. This is also the case for
-    // rvalue-references in C++, regardless of struct size:
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -254,7 +240,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
 
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
@@ -267,9 +253,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
     // A new instance of `Gigastruct` is passed to `f()`, without any apparent
     // connection to this stack frame. Still, since instances of `Gigastruct`
     // are sufficiently large, it is allocated in the caller stack frame and
-    // passed as a pointer. As such, this function is *also* protected by the
-    // `strong` heuristic, just like `local_large_var_moved`. This is also the
-    // case for pass-by-value of sufficiently large structs in C++:
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -284,7 +270,7 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
 
     // all: __security_check_cookie
     // strong: __security_check_cookie
-    // basic-NOT: __security_check_cookie
+    // basic: __security_check_cookie
     // none-NOT: __security_check_cookie
     // missing-NOT: __security_check_cookie
 }
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
index e63adc88ff5..8e32d170244 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
@@ -11,6 +11,11 @@
 //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
 //@ min-llvm-version: 17.0.2
 
+// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR,
+// despite those types having no semantic meaning. This means that the `basic` and `strong`
+// settings do not behave in a coherent way. This is a known issue in LLVM.
+// See comments on https://github.com/rust-lang/rust/issues/114903.
+
 #![crate_type = "lib"]
 
 #![allow(incomplete_features)]
@@ -39,23 +44,9 @@ pub fn array_char(f: fn(*const char)) {
     f(&b as *const _);
     f(&c as *const _);
 
-    // Any type of local array variable leads to stack protection with the
-    // "strong" heuristic. The 'basic' heuristic only adds stack protection to
-    // functions with local array variables of a byte-sized type, however. Since
-    // 'char' is 4 bytes in Rust, this function is not protected by the 'basic'
-    // heuristic
-    //
-    // (This test *also* takes the address of the local stack variables. We
-    // cannot know that this isn't what triggers the `strong` heuristic.
-    // However, the test strategy of passing the address of a stack array to an
-    // external function is sufficient to trigger the `basic` heuristic (see
-    // test `array_u8_large()`). Since the `basic` heuristic only checks for the
-    // presence of stack-local array variables, we can be confident that this
-    // test also captures this part of the `strong` heuristic specification.)
-
     // all: __stack_chk_fail
     // strong: __stack_chk_fail
-    // basic-NOT: __stack_chk_fail
+    // basic: __stack_chk_fail
     // none-NOT: __stack_chk_fail
     // missing-NOT: __stack_chk_fail
 }
@@ -163,26 +154,11 @@ pub fn local_string_addr_taken(f: fn(&String)) {
     f(&x);
 
     // Taking the address of the local variable `x` leads to stack smash
-    // protection with the `strong` heuristic, but not with the `basic`
-    // heuristic. It does not matter that the reference is not mut.
-    //
-    // An interesting note is that a similar function in C++ *would* be
-    // protected by the `basic` heuristic, because `std::string` has a char
-    // array internally as a small object optimization:
-    // ```
-    // cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
-    // #include <string>
-    // void f(void (*g)(const std::string&)) {
-    //     std::string x;
-    //     g(x);
-    // }
-    // EOF
-    // ```
-    //
+    // protection. It does not matter that the reference is not mut.
 
     // all: __stack_chk_fail
     // strong: __stack_chk_fail
-    // basic-NOT: __stack_chk_fail
+    // basic: __stack_chk_fail
     // none-NOT: __stack_chk_fail
     // missing-NOT: __stack_chk_fail
 }
@@ -233,8 +209,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
     // Even though the local variable conceptually doesn't have its address
     // taken, it's so large that the "move" is implemented with a reference to a
     // stack-local variable in the ABI. Consequently, this function *is*
-    // protected by the `strong` heuristic. This is also the case for
-    // rvalue-references in C++, regardless of struct size:
+    // protected. This is also the case for rvalue-references in C++,
+    // regardless of struct size:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -248,7 +224,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
 
     // all: __stack_chk_fail
     // strong: __stack_chk_fail
-    // basic-NOT: __stack_chk_fail
+    // basic: __stack_chk_fail
     // none-NOT: __stack_chk_fail
     // missing-NOT: __stack_chk_fail
 }
@@ -261,9 +237,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
     // A new instance of `Gigastruct` is passed to `f()`, without any apparent
     // connection to this stack frame. Still, since instances of `Gigastruct`
     // are sufficiently large, it is allocated in the caller stack frame and
-    // passed as a pointer. As such, this function is *also* protected by the
-    // `strong` heuristic, just like `local_large_var_moved`. This is also the
-    // case for pass-by-value of sufficiently large structs in C++:
+    // passed as a pointer. As such, this function is *also* protected, just
+    // like `local_large_var_moved`. This is also the case for pass-by-value
+    // of sufficiently large structs in C++:
     // ```
     // cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
     // #include <cstdint>
@@ -275,10 +251,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
     // EOF
     // ```
 
-
     // all: __stack_chk_fail
     // strong: __stack_chk_fail
-    // basic-NOT: __stack_chk_fail
+    // basic: __stack_chk_fail
     // none-NOT: __stack_chk_fail
     // missing-NOT: __stack_chk_fail
 }
diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs
index 306e3ce1358..71f2dd42ec2 100644
--- a/tests/codegen/align-byval-alignment-mismatch.rs
+++ b/tests/codegen/align-byval-alignment-mismatch.rs
@@ -56,7 +56,7 @@ extern "C" {
 #[no_mangle]
 pub unsafe fn rust_to_c_increases_alignment(x: Align1) {
     // i686-linux: start:
-    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align1, align 4
+    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4
     // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x
     // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]])
 
@@ -90,7 +90,7 @@ pub unsafe extern "C" fn c_to_rust_decreases_alignment(x: Align1) {
 #[no_mangle]
 pub unsafe extern "C" fn c_to_rust_increases_alignment(x: Align16) {
     // i686-linux: start:
-    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16
+    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
     // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
     // i686-linux-NEXT: call void @extern_rust_align16({{.+}} [[ALLOCA]])
 
@@ -116,7 +116,7 @@ pub unsafe extern "C" fn c_to_rust_ref_decreases_alignment(x: Align1) {
 #[no_mangle]
 pub unsafe extern "C" fn c_to_rust_ref_increases_alignment(x: Align16) {
     // i686-linux: start:
-    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16
+    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
     // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
     // i686-linux-NEXT: call void @extern_rust_ref_align16({{.+}} [[ALLOCA]])
 
diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs
index c74e236f29d..3a2be2b2b9c 100644
--- a/tests/codegen/align-byval.rs
+++ b/tests/codegen/align-byval.rs
@@ -106,20 +106,20 @@ pub struct ForceAlign16 {
 pub unsafe fn call_na1(x: NaturalAlign1) {
     // CHECK: start:
 
-    // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
+    // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1
     // m68k: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
 
-    // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
+    // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1
     // wasm: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
 
     // x86_64-linux: call void @natural_align_1(i16
 
     // x86_64-windows: call void @natural_align_1(i16
 
-    // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
+    // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 4
     // i686-linux: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
 
-    // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
+    // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 4
     // i686-windows: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
     natural_align_1(x);
 }
@@ -134,10 +134,10 @@ pub unsafe fn call_na2(x: NaturalAlign2) {
     // x86_64-linux-NEXT: call void @natural_align_2
     // x86_64-windows-NEXT: call void @natural_align_2
 
-    // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+    // i686-linux: [[ALLOCA:%[0-9]+]] = alloca [34 x i8], align 4
     // i686-linux: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
 
-    // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+    // i686-windows: [[ALLOCA:%[0-9]+]] = alloca [34 x i8], align 4
     // i686-windows: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
     natural_align_2(x);
 }
diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs
index b40168d77a4..93d5a87fb30 100644
--- a/tests/codegen/align-enum.rs
+++ b/tests/codegen/align-enum.rs
@@ -18,7 +18,7 @@ pub struct Nested64 {
 // CHECK-LABEL: @align64
 #[no_mangle]
 pub fn align64(a: u32) -> Align64 {
-// CHECK: %a64 = alloca %Align64, align 64
+// CHECK: %a64 = alloca [64 x i8], align 64
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
     let a64 = Align64::A(a);
     a64
@@ -27,7 +27,7 @@ pub fn align64(a: u32) -> Align64 {
 // CHECK-LABEL: @nested64
 #[no_mangle]
 pub fn nested64(a: u8, b: u32, c: u16) -> Nested64 {
-// CHECK: %n64 = alloca %Nested64, align 64
+// CHECK: %n64 = alloca [128 x i8], align 64
     let n64 = Nested64 { a, b: Align64::B(b), c };
     n64
 }
diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs
index dbbb85bee6f..e70b42b47db 100644
--- a/tests/codegen/align-struct.rs
+++ b/tests/codegen/align-struct.rs
@@ -26,7 +26,7 @@ pub enum Enum64 {
 // CHECK-LABEL: @align64
 #[no_mangle]
 pub fn align64(i : i32) -> Align64 {
-// CHECK: %a64 = alloca %Align64, align 64
+// CHECK: %a64 = alloca [64 x i8], align 64
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
     let a64 = Align64(i);
     a64
@@ -44,7 +44,7 @@ pub fn align64_load(a: Align64) -> i32 {
 // CHECK-LABEL: @nested64
 #[no_mangle]
 pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 {
-// CHECK: %n64 = alloca %Nested64, align 64
+// CHECK: %n64 = alloca [128 x i8], align 64
     let n64 = Nested64 { a, b, c, d };
     n64
 }
@@ -52,7 +52,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 {
 // CHECK-LABEL: @enum4
 #[no_mangle]
 pub fn enum4(a: i32) -> Enum4 {
-// CHECK: %e4 = alloca %Enum4, align 4
+// CHECK: %e4 = alloca [8 x i8], align 4
     let e4 = Enum4::A(a);
     e4
 }
@@ -60,7 +60,7 @@ pub fn enum4(a: i32) -> Enum4 {
 // CHECK-LABEL: @enum64
 #[no_mangle]
 pub fn enum64(a: Align64) -> Enum64 {
-// CHECK: %e64 = alloca %Enum64, align 64
+// CHECK: %e64 = alloca [128 x i8], align 64
     let e64 = Enum64::A(a);
     e64
 }
diff --git a/tests/codegen/array-codegen.rs b/tests/codegen/array-codegen.rs
index 1310e61c41d..fc272f2556c 100644
--- a/tests/codegen/array-codegen.rs
+++ b/tests/codegen/array-codegen.rs
@@ -18,7 +18,7 @@ pub fn array_load(a: &[u8; 4]) -> [u8; 4] {
 #[no_mangle]
 pub fn array_store(a: [u8; 4], p: &mut [u8; 4]) {
     // CHECK-NOT: alloca
-    // CHECK: %[[TEMP:.+]] = alloca i32, [[TEMPALIGN:align [0-9]+]]
+    // CHECK: %[[TEMP:.+]] = alloca [4 x i8], [[TEMPALIGN:align [0-9]+]]
     // CHECK-NOT: alloca
     // CHECK: %a = alloca [4 x i8]
     // CHECK-NOT: alloca
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
index 743a15989f7..f49dddcfc20 100644
--- a/tests/codegen/array-map.rs
+++ b/tests/codegen/array-map.rs
@@ -27,7 +27,7 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
 #[no_mangle]
 pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] {
     // CHECK: start:
-    // CHECK-NEXT: alloca [512 x i32]
+    // CHECK-NEXT: alloca [2048 x i8]
     // CHECK-NOT: alloca
     // CHECK: mul <{{[0-9]+}} x i32>
     // CHECK: add <{{[0-9]+}} x i32>
diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs
index e6024f03425..9c31acc9bb7 100644
--- a/tests/codegen/cast-target-abi.rs
+++ b/tests/codegen/cast-target-abi.rs
@@ -77,15 +77,20 @@ extern "C" {
 // CHECK-LABEL: @call_twou16s
 #[no_mangle]
 pub unsafe fn call_twou16s() {
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
-    // powerpc64:   [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i32]], align [[ABI_ALIGN:4]]
-    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
+    // powerpc64:   [[ABI_ALLOCA:%.+]] = alloca [4 x i8], align [[ABI_ALIGN:4]]
+    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
 
-    // CHECK: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]]
+    // CHECK: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]]
 
     // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 4, i1 false)
-    // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+
+    // aarch64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // powerpc64:   [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i32]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // sparc64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+
     // CHECK: call void @receives_twou16s([[ABI_TYPE]] [[ABI_VALUE]])
     let x = TwoU16s { a: 1, b: 2 };
     receives_twou16s(x);
@@ -96,23 +101,23 @@ pub unsafe fn call_twou16s() {
 pub unsafe fn return_twou16s() -> TwoU16s {
     // powerpc returns this struct via sret pointer, it doesn't use the cast ABI.
 
-    // powerpc64: [[RETVAL:%.+]] = alloca %TwoU16s, align 2
+    // powerpc64: [[RETVAL:%.+]] = alloca [4 x i8], align 2
     // powerpc64: call void @returns_twou16s(ptr {{.+}} [[RETVAL]])
 
 
     // The other targets copy the cast ABI type to an alloca.
 
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
-    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
+    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]]
 
-    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]]
-    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]]
-    // sparc64:     [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]]
+    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]]
+    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]]
+    // sparc64:     [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]]
 
-    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s()
-    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s()
-    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s()
+    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s()
+    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s()
+    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s()
 
     // aarch64:     store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
     // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
@@ -127,12 +132,12 @@ pub unsafe fn return_twou16s() -> TwoU16s {
 // CHECK-LABEL: @call_fiveu16s
 #[no_mangle]
 pub unsafe fn call_fiveu16s() {
-    // CHECK: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
+    // CHECK: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
 
-    // CHECK: [[RUST_ALLOCA:%.+]] = alloca %FiveU16s, align 2
+    // CHECK: [[RUST_ALLOCA:%.+]] = alloca [10 x i8], align 2
 
     // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 10, i1 false)
-    // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
     // CHECK: call void @receives_fiveu16s([[ABI_TYPE]] [[ABI_VALUE]])
     let x = FiveU16s { a: 1, b: 2, c: 3, d: 4, e: 5 };
     receives_fiveu16s(x);
@@ -149,13 +154,13 @@ pub unsafe fn return_fiveu16s() -> FiveU16s {
 
     // The other targets copy the cast ABI type to the sret pointer.
 
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
-    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
 
-    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s()
-    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s()
-    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s()
+    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s()
+    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s()
+    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s()
 
     // aarch64:     store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
     // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
@@ -170,15 +175,17 @@ pub unsafe fn return_fiveu16s() -> FiveU16s {
 // CHECK-LABEL: @call_doubledouble
 #[no_mangle]
 pub unsafe fn call_doubledouble() {
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]]
-    // powerpc64:   [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
-    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]]
+    // CHECK: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
 
-    // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]]
+    // CHECK: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
 
     // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false)
-    // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+
+    // aarch64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x double\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // powerpc64:   [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // sparc64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+
     // CHECK: call void @receives_doubledouble([[ABI_TYPE]] [[ABI_VALUE]])
     let x = DoubleDouble { f: 1., g: 2. };
     receives_doubledouble(x);
@@ -189,23 +196,23 @@ pub unsafe fn call_doubledouble() {
 pub unsafe fn return_doubledouble() -> DoubleDouble {
     // powerpc returns this struct via sret pointer, it doesn't use the cast ABI.
 
-    // powerpc64: [[RETVAL:%.+]] = alloca %DoubleDouble, align 8
+    // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8
     // powerpc64: call void @returns_doubledouble(ptr {{.+}} [[RETVAL]])
 
 
     // The other targets copy the cast ABI type to an alloca.
 
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]]
-    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // sparc64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
 
-    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]]
-    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]]
-    // sparc64:     [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]]
+    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
+    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
+    // sparc64:     [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
 
-    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble()
-    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble()
-    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble()
+    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x double\]]] @returns_doubledouble()
+    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doubledouble()
+    // sparc64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doubledouble()
 
     // aarch64:     store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
     // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
@@ -224,21 +231,21 @@ pub unsafe fn return_doubledouble() -> DoubleDouble {
 // powerpc64-LABEL:   @call_doublefloat
 #[no_mangle]
 pub unsafe fn call_doublefloat() {
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]]
-    // powerpc64:   [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [12 x i8], align [[ABI_ALIGN:8]]
+    // powerpc64:   [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
 
-    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]]
-    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]]
-    // powerpc64:   [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]]
+    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
+    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
+    // powerpc64:   [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
 
     // aarch64:     call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false)
     // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 12, i1 false)
     // powerpc64:   call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false)
 
-    // aarch64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
-    // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
-    // powerpc64:   [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // aarch64:     [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, float }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
+    // powerpc64:   [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
 
     // aarch64:     call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]])
     // loongarch64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]])
@@ -256,20 +263,20 @@ pub unsafe fn call_doublefloat() {
 pub unsafe fn return_doublefloat() -> DoubleFloat {
     // powerpc returns this struct via sret pointer, it doesn't use the cast ABI.
 
-    // powerpc64: [[RETVAL:%.+]] = alloca %DoubleFloat, align 8
+    // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8
     // powerpc64: call void @returns_doublefloat(ptr {{.+}} [[RETVAL]])
 
 
     // The other targets copy the cast ABI type to an alloca.
 
-    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]]
-    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]]
+    // aarch64:     [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]]
+    // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [12 x i8], align [[ABI_ALIGN:8]]
 
-    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]]
-    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]]
+    // aarch64:     [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
+    // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]]
 
-    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat()
-    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat()
+    // aarch64:     [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_doublefloat()
+    // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, float }]] @returns_doublefloat()
 
     // aarch64:     store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
     // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]]
diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
index 8b32e902b3f..35bf00f8f3c 100644
--- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
+++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
@@ -33,7 +33,7 @@ extern "C" {
 pub fn test() {
     let s = S { f1: 1, f2: 2, f3: 3 };
     unsafe {
-        // CHECK: [[ALLOCA:%.+]] = alloca { i64, i32 }, align 8
+        // CHECK: [[ALLOCA:%.+]] = alloca [12 x i8], align 8
         // CHECK: [[LOAD:%.+]] = load { i64, i32 }, ptr [[ALLOCA]], align 8
         // CHECK: call void @foo({ i64, i32 } [[LOAD]])
         foo(s);
diff --git a/tests/codegen/const_scalar_pair.rs b/tests/codegen/const_scalar_pair.rs
index 0aa430a8efa..f142896c31f 100644
--- a/tests/codegen/const_scalar_pair.rs
+++ b/tests/codegen/const_scalar_pair.rs
@@ -1,7 +1,5 @@
 //@ compile-flags: --crate-type=lib -Copt-level=0 -Zmir-opt-level=0 -C debuginfo=2
 
-#![feature(inline_const)]
-
 // Test that we don't generate a memory allocation for the constant
 // and read the fields from that, but instead just create the value pair directly.
 pub fn foo() -> (i32, i32) {
diff --git a/tests/codegen/coroutine-debug-msvc.rs b/tests/codegen/coroutine-debug-msvc.rs
index fb1b46fe497..e2296db1d59 100644
--- a/tests/codegen/coroutine-debug-msvc.rs
+++ b/tests/codegen/coroutine-debug-msvc.rs
@@ -11,7 +11,7 @@
 use std::ops::Coroutine;
 
 fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
-    || {
+    #[coroutine] || {
         yield 0;
         let s = String::from("foo");
         yield 1;
diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs
index 7eaee669559..914515f58b8 100644
--- a/tests/codegen/coroutine-debug.rs
+++ b/tests/codegen/coroutine-debug.rs
@@ -11,7 +11,7 @@
 use std::ops::Coroutine;
 
 fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
-    || {
+    #[coroutine] || {
         yield 0;
         let s = String::from("foo");
         yield 1;
diff --git a/tests/codegen/debug-fndef-size.rs b/tests/codegen/debug-fndef-size.rs
index b3cc45614bc..5551d2cc39c 100644
--- a/tests/codegen/debug-fndef-size.rs
+++ b/tests/codegen/debug-fndef-size.rs
@@ -12,7 +12,7 @@ pub fn main() {
     foo(0, 1, i32::cmp);
 }
 
-// CHECK: %compare.dbg.spill = alloca {}, align 1
+// CHECK: %compare.dbg.spill = alloca [0 x i8], align 1
 // CHECK: call void @llvm.dbg.declare(metadata ptr %compare.dbg.spill, metadata ![[VAR:.*]], metadata !DIExpression()), !dbg !{{.*}}
 // CHECK: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 1, dwarfAddressSpace: {{.*}})
 // CHECK: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 1)
diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs
new file mode 100644
index 00000000000..7de7bd81b5c
--- /dev/null
+++ b/tests/codegen/emcripten-catch-unwind.rs
@@ -0,0 +1,59 @@
+//@ compile-flags: -O --target wasm32-unknown-emscripten
+//@ needs-llvm-components: webassembly
+
+// Emscripten has its own unique implementation of catch_unwind (in `codegen_emcc_try`),
+// make sure it generates something reasonable.
+
+#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+#[rustc_intrinsic]
+fn size_of<T>() -> usize { loop {} }
+
+extern "rust-intrinsic" {
+    fn catch_unwind(
+        try_fn: fn(_: *mut u8),
+        data: *mut u8,
+        catch_fn: fn(_: *mut u8, _: *mut u8)
+    ) -> i32;
+}
+
+// CHECK-LABEL: @ptr_size
+#[no_mangle]
+pub fn ptr_size() -> usize {
+    // CHECK: ret [[PTR_SIZE:.*]]
+    size_of::<*mut u8>()
+}
+
+// CHECK-LABEL: @test_catch_unwind
+#[no_mangle]
+pub unsafe fn test_catch_unwind(
+    try_fn: fn(_: *mut u8),
+    data: *mut u8,
+    catch_fn: fn(_: *mut u8, _: *mut u8)
+) -> i32 {
+    // CHECK: start:
+    // CHECK: [[ALLOCA:%.*]] = alloca
+
+    // CHECK: catch.i:
+    // CHECK: [[LANDINGPAD:%.*]] = landingpad
+    // CHECK: [[EXCEPTION:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 0
+    // CHECK: [[SELECTOR:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 1
+
+    // CHECK: [[IS_RUST_EXN:%.*]] = icmp eq {{.*}}[[SELECTOR]]
+    // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8
+
+    // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]]
+    // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], [[PTR_SIZE]]
+    // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]]
+
+    // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]])
+
+    catch_unwind(try_fn, data, catch_fn)
+}
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 2e6dad8791b..f1c40f6695b 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -15,7 +15,7 @@ pub enum Enum0 {
 // CHECK-NEXT: start:
 // CHECK-NEXT: %1 = icmp eq i8 %0, 2
 // CHECK-NEXT: %2 = and i8 %0, 1
-// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2
+// CHECK-NEXT: %{{.+}} = select i1 %1, i8 13, i8 %2
 #[no_mangle]
 pub fn match0(e: Enum0) -> u8 {
     use Enum0::*;
diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs
index b2e0c294c39..3e6ed2b8e16 100644
--- a/tests/codegen/i128-x86-align.rs
+++ b/tests/codegen/i128-x86-align.rs
@@ -6,7 +6,6 @@
 // correctly.
 
 // CHECK: %ScalarPair = type { i32, [3 x i32], i128 }
-// CHECK: %Struct = type { i32, i32, [2 x i32], i128 }
 
 #![feature(core_intrinsics)]
 
@@ -43,7 +42,7 @@ pub fn store(x: &mut ScalarPair) {
 #[no_mangle]
 pub fn alloca() {
     // CHECK-LABEL: @alloca(
-    // CHECK:      [[X:%.*]] = alloca %ScalarPair, align 16
+    // CHECK:      [[X:%.*]] = alloca [32 x i8], align 16
     // CHECK:      store i32 1, ptr %x, align 16
     // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
     // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16
@@ -55,7 +54,7 @@ pub fn alloca() {
 pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
     // CHECK-LABEL: @load_volatile(
     // CHECK-SAME: align 16 dereferenceable(32) %x
-    // CHECK:      [[TMP:%.*]] = alloca %ScalarPair, align 16
+    // CHECK:      [[TMP:%.*]] = alloca [32 x i8], align 16
     // CHECK:      [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16
     // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr [[TMP]], align 16
     // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16
@@ -67,7 +66,7 @@ pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
 #[no_mangle]
 pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit<i128>, i128) {
     // CHECK-LABEL: define { i128, i128 } @transmute(i32 noundef %x.0, i128 noundef %x.1)
-    // CHECK:       [[TMP:%.*]] = alloca { i128, i128 }, align 16
+    // CHECK:       [[TMP:%.*]] = alloca [32 x i8], align 16
     // CHECK-NEXT:  store i32 %x.0, ptr [[TMP]], align 16
     // CHECK-NEXT:  [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16
     // CHECK-NEXT:  store i128 %x.1, ptr [[GEP]], align 16
@@ -92,7 +91,7 @@ pub struct Struct {
 pub fn store_struct(x: &mut Struct) {
     // CHECK-LABEL: @store_struct(
     // CHECK-SAME: align 16 dereferenceable(32) %x
-    // CHECK:      [[TMP:%.*]] = alloca %Struct, align 16
+    // CHECK:      [[TMP:%.*]] = alloca [32 x i8], align 16
     // CHECK:      store i32 1, ptr [[TMP]], align 16
     // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 4
     // CHECK-NEXT: store i32 2, ptr [[GEP1]], align 4
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index f858562b5f1..04a91bb87f7 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -4,7 +4,6 @@
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
 #![feature(custom_mir)]
-#![feature(inline_const)]
 #![allow(unreachable_code)]
 
 use std::intrinsics::{transmute, transmute_unchecked};
@@ -153,7 +152,7 @@ pub unsafe fn check_from_newtype(x: Scalar64) -> u64 {
 // CHECK-LABEL: @check_aggregate_to_bool(
 #[no_mangle]
 pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
-    // CHECK: %x = alloca %Aggregate8, align 1
+    // CHECK: %x = alloca [1 x i8], align 1
     // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1
     // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1
     // CHECK: ret i1 %[[BOOL]]
@@ -163,7 +162,7 @@ pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
 // CHECK-LABEL: @check_aggregate_from_bool(
 #[no_mangle]
 pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
-    // CHECK: %_0 = alloca %Aggregate8, align 1
+    // CHECK: %_0 = alloca [1 x i8], align 1
     // CHECK: %[[BYTE:.+]] = zext i1 %x to i8
     // CHECK: store i8 %[[BYTE]], ptr %_0, align 1
     transmute(x)
@@ -190,7 +189,7 @@ pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
 // CHECK-LABEL: @check_to_pair(
 #[no_mangle]
 pub unsafe fn check_to_pair(x: u64) -> Option<i32> {
-    // CHECK: %_0 = alloca %"core::option::Option<i32>", align 4
+    // CHECK: %_0 = alloca [8 x i8], align 4
     // CHECK: store i64 %x, ptr %_0, align 4
     transmute(x)
 }
@@ -202,7 +201,7 @@ pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
     // immediates so we can write using the destination alloca's alignment.
     const { assert!(std::mem::align_of::<Option<i32>>() == 4) };
 
-    // CHECK: %_0 = alloca i64, align 8
+    // CHECK: %_0 = alloca [8 x i8], align 8
     // CHECK: store i32 %x.0, ptr %_0, align 8
     // CHECK: store i32 %x.1, ptr %0, align 4
     // CHECK: %[[R:.+]] = load i64, ptr %_0, align 8
@@ -248,7 +247,7 @@ pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 {
 // CHECK-LABEL: @check_to_aggregate(
 #[no_mangle]
 pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 {
-    // CHECK: %_0 = alloca %Aggregate64, align 4
+    // CHECK: %_0 = alloca [8 x i8], align 4
     // CHECK: store i64 %x, ptr %_0, align 4
     // CHECK: %0 = load i64, ptr %_0, align 4
     // CHECK: ret i64 %0
@@ -258,7 +257,7 @@ pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 {
 // CHECK-LABEL: @check_from_aggregate(
 #[no_mangle]
 pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 {
-    // CHECK: %x = alloca %Aggregate64, align 4
+    // CHECK: %x = alloca [8 x i8], align 4
     // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 4
     // CHECK: ret i64 %[[VAL]]
     transmute(x)
@@ -452,7 +451,7 @@ pub struct HighAlignScalar(u8);
 // CHECK-LABEL: @check_to_overalign(
 #[no_mangle]
 pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar {
-    // CHECK: %_0 = alloca %HighAlignScalar, align 8
+    // CHECK: %_0 = alloca [8 x i8], align 8
     // CHECK: store i64 %x, ptr %_0, align 8
     // CHECK: %0 = load i64, ptr %_0, align 8
     // CHECK: ret i64 %0
@@ -462,7 +461,7 @@ pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar {
 // CHECK-LABEL: @check_from_overalign(
 #[no_mangle]
 pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 {
-    // CHECK: %x = alloca %HighAlignScalar, align 8
+    // CHECK: %x = alloca [8 x i8], align 8
     // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 8
     // CHECK: ret i64 %[[VAL]]
     transmute(x)
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
index 0bd43dc50b2..56b4330b1a6 100644
--- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -15,7 +15,7 @@ pub fn outer_function(x: S, y: S) -> usize {
 // Check that we do not attempt to load from the spilled arg before it is assigned to
 // when generating debuginfo.
 // CHECK-LABEL: @outer_function
-// CHECK: [[spill:%.*]] = alloca %"{closure@{{.*.rs}}:9:23: 9:25}"
+// CHECK: [[spill:%.*]] = alloca
 // CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds i8, ptr [[spill]]
 // CHECK-NOT: [[load:%.*]] = load ptr, ptr
 // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
index 3f4c7e7d542..41bfb493ff5 100644
--- a/tests/codegen/issues/issue-111603.rs
+++ b/tests/codegen/issues/issue-111603.rs
@@ -11,7 +11,7 @@ pub fn new_from_array(x: u64) -> Arc<[u64]> {
     // Ensure that we only generate one alloca for the array.
 
     // CHECK: alloca
-    // CHECK-SAME: [1000 x i64]
+    // CHECK-SAME: [8000 x i8]
     // CHECK-NOT: alloca
     let array = [x; 1000];
     Arc::new(array)
diff --git a/tests/codegen/issues/issue-96274.rs b/tests/codegen/issues/issue-96274.rs
index d278796dd02..ffefd5f43f8 100644
--- a/tests/codegen/issues/issue-96274.rs
+++ b/tests/codegen/issues/issue-96274.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: -O
 
 #![crate_type = "lib"]
-#![feature(inline_const)]
 
 use std::mem::MaybeUninit;
 
diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs
index 9e5b69ff267..7cd8d19c211 100644
--- a/tests/codegen/overaligned-constant.rs
+++ b/tests/codegen/overaligned-constant.rs
@@ -2,7 +2,7 @@
 // do not ICE during codegen, and that the LLVM constant has the higher alignment.
 //
 //@ compile-flags: -Zmir-opt-level=0 -Zmir-enable-passes=+GVN
-//@ compile-flags: -Cno-prepopulate-passes
+//@ compile-flags: -Cno-prepopulate-passes --crate-type=lib
 //@ only-64bit
 
 struct S(i32);
@@ -12,9 +12,10 @@ struct SmallStruct(f32, Option<S>, &'static [f32]);
 // CHECK: @0 = private unnamed_addr constant
 // CHECK-SAME: , align 8
 
-fn main() {
-    // CHECK-LABEL: @_ZN20overaligned_constant4main
-    // CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8
+#[no_mangle]
+pub fn overaligned_constant() {
+    // CHECK-LABEL: @overaligned_constant
+    // CHECK: [[full:%_.*]] = alloca [32 x i8], align 8
     // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false)
     // CHECK: %b.0 = load i32, ptr @0, align 4
     // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4
diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs
index 764476b0aa1..5142df9c488 100644
--- a/tests/codegen/packed.rs
+++ b/tests/codegen/packed.rs
@@ -51,7 +51,7 @@ pub struct BigPacked2 {
 // CHECK-LABEL: @call_pkd1
 #[no_mangle]
 pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
-// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
+// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
 // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
@@ -63,7 +63,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 // CHECK-LABEL: @call_pkd2
 #[no_mangle]
 pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
-// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
+// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
 // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs
index f2ab9c3bb82..0ef4aa424d8 100644
--- a/tests/codegen/personality_lifetimes.rs
+++ b/tests/codegen/personality_lifetimes.rs
@@ -23,7 +23,7 @@ pub fn test() {
     let _s = S;
     // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just
     // in the first one.
-    // CHECK: [[SLOT:%[0-9]+]] = alloca { ptr, i32{{.*}} }
+    // CHECK: [[SLOT:%[0-9]+]] = alloca [{{[0-9]+}} x i8]
     // CHECK-LABEL: cleanup:
     // CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}})
     // CHECK-LABEL: cleanup1:
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
index ca781a99296..6c3d991af9f 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
@@ -5,7 +5,7 @@
 //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
 
 #![crate_type="lib"]
-#![feature(inline_const, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
 extern crate core;
 
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index 488be2a8629..c416f4d28bb 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -4,7 +4,6 @@
 #![crate_type = "lib"]
 #![allow(non_camel_case_types)]
 #![feature(repr_simd, intrinsics)]
-#![feature(inline_const)]
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs
index d8c2d2c6f9e..32786d2a76a 100644
--- a/tests/codegen/sroa-fragment-debuginfo.rs
+++ b/tests/codegen/sroa-fragment-debuginfo.rs
@@ -14,9 +14,9 @@ pub struct ExtraSlice<'input> {
 #[no_mangle]
 pub fn extra(s: &[u8]) {
 // CHECK: void @extra(
-// CHECK: %slice.dbg.spill1 = alloca i32,
-// CHECK: %slice.dbg.spill = alloca { ptr, i64 },
-// CHECK: %s.dbg.spill = alloca { ptr, i64 },
+// CHECK: %slice.dbg.spill1 = alloca [4 x i8],
+// CHECK: %slice.dbg.spill = alloca [16 x i8],
+// CHECK: %s.dbg.spill = alloca [16 x i8],
 // CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()),
 // CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)),
 // CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)),
diff --git a/tests/codegen/stores.rs b/tests/codegen/stores.rs
index 3fda5aa47ea..86ec52fa101 100644
--- a/tests/codegen/stores.rs
+++ b/tests/codegen/stores.rs
@@ -15,8 +15,8 @@ pub struct Bytes {
 // dependent alignment
 #[no_mangle]
 pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
-// CHECK: [[TMP:%.+]] = alloca i32
-// CHECK: %y = alloca [4 x i8]
+// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4
+// CHECK: %y = alloca [4 x i8], align 1
 // CHECK: store i32 %0, ptr [[TMP]]
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
     *x = y;
@@ -27,8 +27,8 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
 // dependent alignment
 #[no_mangle]
 pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
-// CHECK: [[TMP:%.+]] = alloca i32
-// CHECK: %y = alloca %Bytes
+// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4
+// CHECK: %y = alloca [4 x i8], align 1
 // CHECK: store i32 %0, ptr [[TMP]]
 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
     *x = y;
diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs
index b182f3ed947..b976f6fe207 100644
--- a/tests/codegen/swap-large-types.rs
+++ b/tests/codegen/swap-large-types.rs
@@ -15,7 +15,7 @@ type KeccakBuffer = [[u64; 5]; 5];
 // CHECK-LABEL: @swap_basic
 #[no_mangle]
 pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) {
-// CHECK: alloca [5 x [5 x i64]]
+// CHECK: alloca [200 x i8]
 
     // SAFETY: exclusive references are always valid to read/write,
     // are non-overlapping, and nothing here panics so it's drop-safe.
diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs
index 4dcfed2a53a..1a48c63d813 100644
--- a/tests/codegen/swap-small-types.rs
+++ b/tests/codegen/swap-small-types.rs
@@ -12,7 +12,7 @@ type RGB48 = [u16; 3];
 pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
     // FIXME: See #115212 for why this has an alloca again
 
-    // CHECK: alloca [3 x i16], align 2
+    // CHECK: alloca [6 x i8], align 2
     // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
     // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
     // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map
index ef9faab590b..255708d365e 100644
--- a/tests/coverage/coroutine.cov-map
+++ b/tests/coverage/coroutine.cov-map
@@ -43,11 +43,11 @@ Number of file 0 mappings: 9
     = ((c4 - c5) - c6)
 
 Function name: coroutine::main::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 1c, 01, 1f, 05, 02, 10, 01, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 29, 01, 1f, 05, 02, 10, 01, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 21, 28) to (start + 1, 31)
+- Code(Counter(0)) at (prev + 21, 41) to (start + 1, 31)
 - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6)
 
diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage
index bd3d4e46880..68b52d19831 100644
--- a/tests/coverage/coroutine.coverage
+++ b/tests/coverage/coroutine.coverage
@@ -1,4 +1,4 @@
-   LL|       |#![feature(coroutines, coroutine_trait)]
+   LL|       |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
    LL|       |
    LL|       |use std::ops::{Coroutine, CoroutineState};
    LL|       |use std::pin::Pin;
@@ -18,7 +18,7 @@
    LL|       |
    LL|      1|fn main() {
    LL|      1|    let is_true = std::env::args().len() == 1;
-   LL|      1|    let mut coroutine = || {
+   LL|      1|    let mut coroutine = #[coroutine] || {
    LL|      1|        yield get_u32(is_true);
    LL|      1|        return "foo";
    LL|      1|    };
diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs
index 2aa689466fc..7f72e0d8bd4 100644
--- a/tests/coverage/coroutine.rs
+++ b/tests/coverage/coroutine.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
@@ -18,7 +18,7 @@ fn get_u32(val: bool) -> Result<u32, String> {
 
 fn main() {
     let is_true = std::env::args().len() == 1;
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield get_u32(is_true);
         return "foo";
     };
diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map
index 9cc67dfe88a..0347aaaa367 100644
--- a/tests/coverage/yield.cov-map
+++ b/tests/coverage/yield.cov-map
@@ -41,21 +41,21 @@ Number of file 0 mappings: 16
 - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2)
 
 Function name: yield::main::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 29, 01, 10, 05, 02, 10, 01, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 8, 28) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 8, 41) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6)
 
 Function name: yield::main::{closure#1}
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 1c, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06]
+Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 29, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 22, 41) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16)
 - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16)
 - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6)
diff --git a/tests/coverage/yield.coverage b/tests/coverage/yield.coverage
index d7e455f211e..e2fc9196d24 100644
--- a/tests/coverage/yield.coverage
+++ b/tests/coverage/yield.coverage
@@ -1,11 +1,11 @@
-   LL|       |#![feature(coroutines, coroutine_trait)]
+   LL|       |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
    LL|       |#![allow(unused_assignments)]
    LL|       |
    LL|       |use std::ops::{Coroutine, CoroutineState};
    LL|       |use std::pin::Pin;
    LL|       |
    LL|      1|fn main() {
-   LL|      1|    let mut coroutine = || {
+   LL|      1|    let mut coroutine = #[coroutine] || {
    LL|      1|        yield 1;
    LL|      1|        return "foo";
    LL|      1|    };
@@ -19,7 +19,7 @@
    LL|      0|        _ => panic!("unexpected value from resume"),
    LL|       |    }
    LL|       |
-   LL|      1|    let mut coroutine = || {
+   LL|      1|    let mut coroutine = #[coroutine] || {
    LL|      1|        yield 1;
    LL|      1|        yield 2;
    LL|      0|        yield 3;
diff --git a/tests/coverage/yield.rs b/tests/coverage/yield.rs
index b7e2ba31b59..64ea2706604 100644
--- a/tests/coverage/yield.rs
+++ b/tests/coverage/yield.rs
@@ -1,11 +1,11 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 #![allow(unused_assignments)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo";
     };
@@ -19,7 +19,7 @@ fn main() {
         _ => panic!("unexpected value from resume"),
     }
 
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         yield 2;
         yield 3;
diff --git a/tests/debuginfo/coroutine-locals.rs b/tests/debuginfo/coroutine-locals.rs
index 54b5cd577c8..c019998040b 100644
--- a/tests/debuginfo/coroutine-locals.rs
+++ b/tests/debuginfo/coroutine-locals.rs
@@ -46,7 +46,7 @@
 // lldb-command:v c
 // lldb-check:(int) c = 6
 
-#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
 #![omit_gdb_pretty_printer_section]
 
 use std::ops::Coroutine;
@@ -54,7 +54,8 @@ use std::pin::Pin;
 
 fn main() {
     let mut a = 5;
-    let mut b = || {
+    let mut b = #[coroutine]
+    || {
         let c = 6; // Live across multiple yield points
 
         let d = 7; // Live across only one yield point
@@ -76,4 +77,6 @@ fn main() {
     _zzz(); // #break
 }
 
-fn _zzz() {()}
+fn _zzz() {
+    ()
+}
diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs
index 9e1bd5d62e7..e13f20455a8 100644
--- a/tests/debuginfo/coroutine-objects.rs
+++ b/tests/debuginfo/coroutine-objects.rs
@@ -63,7 +63,7 @@
 // cdb-check: b                : Returned [Type: enum2$<coroutine_objects::main::coroutine_env$0>]
 // cdb-check:    [+0x[...]] _ref__a          : 0x[...] : 6 [Type: int *]
 
-#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
 #![omit_gdb_pretty_printer_section]
 
 use std::ops::Coroutine;
@@ -71,7 +71,8 @@ use std::pin::Pin;
 
 fn main() {
     let mut a = 5;
-    let mut b = || {
+    let mut b = #[coroutine]
+    || {
         let mut c = 6;
         let mut d = 7;
 
diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs
index 1e4be432445..2b0c2593676 100644
--- a/tests/debuginfo/function-names.rs
+++ b/tests/debuginfo/function-names.rs
@@ -83,7 +83,7 @@
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
-#![feature(adt_const_params, coroutines, coroutine_trait)]
+#![feature(adt_const_params, coroutines, coroutine_trait, stmt_expr_attributes)]
 #![allow(incomplete_features)]
 
 use std::ops::Coroutine;
@@ -111,7 +111,8 @@ fn main() {
     closure();
 
     // Coroutine
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine]
+    || {
         yield;
         return;
     };
diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs
index 93e1a2558f6..995779a6a9c 100644
--- a/tests/debuginfo/issue-57822.rs
+++ b/tests/debuginfo/issue-57822.rs
@@ -26,7 +26,7 @@
 // lldb-command:v b
 // lldbg-check:(issue_57822::main::{coroutine_env#3}) b =
 
-#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
 #![omit_gdb_pretty_printer_section]
 
 use std::ops::Coroutine;
@@ -38,11 +38,13 @@ fn main() {
     let g = move || f();
 
     let mut y = 2;
-    let mut a = move || {
+    let mut a = #[coroutine]
+    move || {
         y += 1;
         yield;
     };
-    let mut b = move || {
+    let mut b = #[coroutine]
+    move || {
         Pin::new(&mut a).resume(());
         yield;
     };
diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs
index fe6abc54687..e9a53b7aacb 100644
--- a/tests/mir-opt/building/custom/arrays.rs
+++ b/tests/mir-opt/building/custom/arrays.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-#![feature(custom_mir, core_intrinsics, inline_const)]
+#![feature(custom_mir, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::mir::*;
diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs
index 42abf5019e5..1a410177fa5 100644
--- a/tests/mir-opt/building/custom/consts.rs
+++ b/tests/mir-opt/building/custom/consts.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-#![feature(custom_mir, core_intrinsics, inline_const)]
+#![feature(custom_mir, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::mir::*;
diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs
index bc72ed8dfe3..eb97bcc73b7 100644
--- a/tests/mir-opt/building/custom/operators.rs
+++ b/tests/mir-opt/building/custom/operators.rs
@@ -1,6 +1,6 @@
 // skip-filecheck
 //@ compile-flags: --crate-type=lib
-#![feature(custom_mir, core_intrinsics, inline_const)]
+#![feature(custom_mir, core_intrinsics)]
 use std::intrinsics::mir::*;
 
 // EMIT_MIR operators.f.built.after.mir
diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs
index afd8746af5f..2b7271f63ff 100644
--- a/tests/mir-opt/const_prop/invalid_constant.rs
+++ b/tests/mir-opt/const_prop/invalid_constant.rs
@@ -4,7 +4,6 @@
 // Verify that we can pretty print invalid constants.
 
 #![feature(adt_const_params)]
-#![feature(inline_const)]
 #![allow(incomplete_features)]
 
 #[derive(Copy, Clone)]
diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
index 7214b01c601..7e033916fd3 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}` 0 coroutine_drop
 
-fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
+fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () {
     let mut _0: ();
     let mut _2: ();
     let _3: std::string::String;
diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
index 00769a493b5..613ef2909b5 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}` 0 coroutine_drop
 
-fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
+fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () {
     let mut _0: ();
     let mut _2: ();
     let _3: std::string::String;
diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs
index 69984c737fe..33fdd2dd0d9 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.rs
+++ b/tests/mir-opt/coroutine_drop_cleanup.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
@@ -8,7 +8,8 @@
 
 // EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir
 fn main() {
-    let gen = || {
+    let gen = #[coroutine]
+    || {
         let _s = String::new();
         yield;
     };
diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir
index 8369a3e60dd..4731aed335d 100644
--- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir
+++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}` before StateTransform
 
-fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
+fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
 yields ()
  {
     let mut _0: ();
diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir
index 1773db1abff..14e1782b860 100644
--- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir
+++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}` before StateTransform
 
-fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
+fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
 yields ()
  {
     let mut _0: ();
diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine_storage_dead_unwind.rs
index 253be1ff698..ce9bad483af 100644
--- a/tests/mir-opt/coroutine_storage_dead_unwind.rs
+++ b/tests/mir-opt/coroutine_storage_dead_unwind.rs
@@ -6,7 +6,7 @@
 // Basic block and local names can safely change, but the StorageDead statements
 // should not go away.
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 struct Foo(i32);
 
@@ -20,7 +20,8 @@ fn take<T>(_x: T) {}
 
 // EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
 fn main() {
-    let _gen = || {
+    let _gen = #[coroutine]
+    || {
         let a = Foo(5);
         let b = Bar(6);
         yield;
diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
index 165aa3a05cb..f8b3f68d21e 100644
--- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
@@ -4,7 +4,7 @@
         _0: CoroutineSavedTy {
             ty: HasDrop,
             source_info: SourceInfo {
-                span: $DIR/coroutine_tiny.rs:21:13: 21:15 (#0),
+                span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
                 scope: scope[0],
             },
             ignore_for_traits: false,
@@ -21,7 +21,7 @@
     },
 } */
 
-fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}>, _2: u8) -> CoroutineState<(), ()> {
+fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
     debug _x => _10;
     let mut _0: std::ops::CoroutineState<(), ()>;
     let _3: HasDrop;
@@ -34,18 +34,18 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24
     let _10: u8;
     let mut _11: u32;
     scope 1 {
-        debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop);
+        debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop);
     }
 
     bb0: {
-        _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})));
+        _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
         switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6];
     }
 
     bb1: {
         _10 = move _2;
         nop;
-        (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop) = HasDrop;
+        (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop;
         StorageLive(_4);
         goto -> bb2;
     }
@@ -58,7 +58,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_7);
-        discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))) = 3;
+        discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))) = 3;
         return;
     }
 
diff --git a/tests/mir-opt/coroutine_tiny.rs b/tests/mir-opt/coroutine_tiny.rs
index 9728425f232..81e9940541b 100644
--- a/tests/mir-opt/coroutine_tiny.rs
+++ b/tests/mir-opt/coroutine_tiny.rs
@@ -5,7 +5,7 @@
 //@ compile-flags: -C panic=abort
 //@ no-prefer-dynamic
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 struct HasDrop;
 
@@ -17,7 +17,8 @@ fn callee() {}
 
 // EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
 fn main() {
-    let _gen = |_x: u8| {
+    let _gen = #[coroutine]
+    |_x: u8| {
         let _d = HasDrop;
         loop {
             yield;
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 859082c3111..07031a298bc 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -4,24 +4,24 @@
   fn main() -> () {
       let mut _0: ();
       let _1: std::ops::CoroutineState<i32, bool>;
-      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>;
-      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
-      let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
+      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>;
+      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
+      let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
 +     let mut _5: bool;
       scope 1 {
           debug _r => _1;
       }
 +     scope 2 (inlined g) {
 +     }
-+     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) {
++     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
-+         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) {
++         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
 +             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
 +         debug a => _5;
-+         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
++         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
 +         let mut _7: u32;
 +         let mut _8: i32;
 +     }
@@ -32,22 +32,22 @@
           StorageLive(_3);
           StorageLive(_4);
 -         _4 = g() -> [return: bb1, unwind unreachable];
-+         _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
++         _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
 +         _3 = &mut _4;
-+         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 };
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
 +         StorageLive(_6);
 +         StorageLive(_7);
-+         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8});
++         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
       }
   
       bb1: {
 -         _3 = &mut _4;
--         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind unreachable];
+-         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind unreachable];
 +         StorageDead(_4);
 +         _0 = const ();
 +         StorageDead(_1);
@@ -56,7 +56,7 @@
   
       bb2: {
 -         StorageDead(_3);
--         _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
+-         _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
 +         StorageDead(_7);
 +         StorageDead(_6);
 +         StorageDead(_5);
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 44b06c34972..ab6c62b0baf 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -4,24 +4,24 @@
   fn main() -> () {
       let mut _0: ();
       let _1: std::ops::CoroutineState<i32, bool>;
-      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>;
-      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
-      let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
+      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>;
+      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
+      let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
 +     let mut _5: bool;
       scope 1 {
           debug _r => _1;
       }
 +     scope 2 (inlined g) {
 +     }
-+     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) {
++     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
-+         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) {
++         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
 +             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
 +         debug a => _5;
-+         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
++         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
 +         let mut _7: u32;
 +         let mut _8: i32;
 +     }
@@ -32,22 +32,22 @@
           StorageLive(_3);
           StorageLive(_4);
 -         _4 = g() -> [return: bb1, unwind continue];
-+         _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
++         _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
 +         _3 = &mut _4;
-+         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 };
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
 +         StorageLive(_6);
 +         StorageLive(_7);
-+         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8});
++         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
       }
   
       bb1: {
 -         _3 = &mut _4;
--         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5];
+-         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind: bb5];
 +         StorageDead(_4);
 +         _0 = const ();
 +         StorageDead(_1);
@@ -56,7 +56,7 @@
   
 -     bb2: {
 -         StorageDead(_3);
--         _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
+-         _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
 +     bb2 (cleanup): {
 +         drop(_4) -> [return: bb3, unwind terminate(cleanup)];
       }
diff --git a/tests/mir-opt/inline/inline_coroutine.rs b/tests/mir-opt/inline/inline_coroutine.rs
index 180f9d4a6fd..07f8fb20f7e 100644
--- a/tests/mir-opt/inline/inline_coroutine.rs
+++ b/tests/mir-opt/inline/inline_coroutine.rs
@@ -16,5 +16,6 @@ fn main() {
 #[inline]
 pub fn g() -> impl Coroutine<bool> {
     #[inline]
-    |a| { yield if a { 7 } else { 13 } }
+    #[coroutine]
+    |a| yield if a { 7 } else { 13 }
 }
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index 5076adf5aa4..5eb7d2fcae3 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -1,6 +1,5 @@
 //@ pp-exact
 
-#![feature(inline_const)]
 #![feature(inline_const_pat)]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
diff --git a/tests/run-make/valid-print-requests/Makefile b/tests/run-make/valid-print-requests/Makefile
deleted file mode 100644
index 99430e98d1c..00000000000
--- a/tests/run-make/valid-print-requests/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) --print uwu 2>&1 | diff - valid-print-requests.stderr
diff --git a/tests/run-make/valid-print-requests/valid-print-requests.stderr b/tests/run-make/valid-print-requests/valid-print-requests.stderr
deleted file mode 100644
index 22bb102f9c9..00000000000
--- a/tests/run-make/valid-print-requests/valid-print-requests.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown print request `uwu`. Valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
-
diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr
index fb0e63c207a..8d40e6905e0 100644
--- a/tests/ui/associated-types/issue-25700.stderr
+++ b/tests/ui/associated-types/issue-25700.stderr
@@ -12,7 +12,10 @@ note: if `S<()>` implemented `Clone`, you could clone the value
   --> $DIR/issue-25700.rs:1:1
    |
 LL | struct S<T: 'static>(#[allow(dead_code)] Option<&'static T>);
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     drop(t);
+   |          - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr
index b0677a83864..d7caf6b3c0d 100644
--- a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr
+++ b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/async-outside-of-await-issue-121096.rs:7:7
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 ...
 LL |     }.await
    |       ^^^^^ only allowed inside `async` functions and blocks
diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
index 928eb0b821d..a98bb0764c0 100644
--- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
+++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
@@ -141,7 +141,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/incorrect-syntax-suggestions.rs:68:19
    |
 LL | fn foo13() -> Result<(), ()> {
-   |    ----- this is not `async`
+   | ---------------------------- this is not `async`
 LL |     let _ = bar().await();
    |                   ^^^^^ only allowed inside `async` functions and blocks
 
@@ -149,7 +149,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/incorrect-syntax-suggestions.rs:73:19
    |
 LL | fn foo14() -> Result<(), ()> {
-   |    ----- this is not `async`
+   | ---------------------------- this is not `async`
 LL |     let _ = bar().await()?;
    |                   ^^^^^ only allowed inside `async` functions and blocks
 
@@ -157,7 +157,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/incorrect-syntax-suggestions.rs:78:19
    |
 LL | fn foo15() -> Result<(), ()> {
-   |    ----- this is not `async`
+   | ---------------------------- this is not `async`
 LL |     let _ = bar().await;
    |                   ^^^^^ only allowed inside `async` functions and blocks
 
@@ -165,7 +165,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/incorrect-syntax-suggestions.rs:82:19
    |
 LL | fn foo16() -> Result<(), ()> {
-   |    ----- this is not `async`
+   | ---------------------------- this is not `async`
 LL |     let _ = bar().await?;
    |                   ^^^^^ only allowed inside `async` functions and blocks
 
@@ -173,7 +173,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/incorrect-syntax-suggestions.rs:87:23
    |
 LL |     fn foo() -> Result<(), ()> {
-   |        --- this is not `async`
+   |     -------------------------- this is not `async`
 LL |         let _ = bar().await?;
    |                       ^^^^^ only allowed inside `async` functions and blocks
 
diff --git a/tests/ui/async-await/coroutine-not-future.rs b/tests/ui/async-await/coroutine-not-future.rs
index 2993f58378a..45227435507 100644
--- a/tests/ui/async-await/coroutine-not-future.rs
+++ b/tests/ui/async-await/coroutine-not-future.rs
@@ -1,5 +1,5 @@
 //@ edition:2018
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::future::Future;
 use std::ops::Coroutine;
@@ -9,6 +9,7 @@ fn returns_async_block() -> impl Future<Output = ()> {
     async {}
 }
 fn returns_coroutine() -> impl Coroutine<(), Yield = (), Return = ()> {
+    #[coroutine]
     || {
         let _: () = yield ();
     }
@@ -23,9 +24,12 @@ fn main() {
     takes_future(returns_async_block());
     takes_future(async {});
     takes_coroutine(returns_coroutine());
-    takes_coroutine(|| {
-        let _: () = yield ();
-    });
+    takes_coroutine(
+        #[coroutine]
+        || {
+            let _: () = yield ();
+        },
+    );
 
     // async futures are not coroutines:
     takes_coroutine(async_fn());
@@ -38,8 +42,11 @@ fn main() {
     // coroutines are not futures:
     takes_future(returns_coroutine());
     //~^ ERROR is not a future
-    takes_future(|ctx| {
-        //~^ ERROR is not a future
-        ctx = yield ();
-    });
+    takes_future(
+        #[coroutine]
+        |ctx| {
+            //~^ ERROR is not a future
+            ctx = yield ();
+        },
+    );
 }
diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr
index 580217fb4f8..403e547a753 100644
--- a/tests/ui/async-await/coroutine-not-future.stderr
+++ b/tests/ui/async-await/coroutine-not-future.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
-  --> $DIR/coroutine-not-future.rs:31:21
+  --> $DIR/coroutine-not-future.rs:35:21
    |
 LL |     takes_coroutine(async_fn());
    |     --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
@@ -7,13 +7,13 @@ LL |     takes_coroutine(async_fn());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_coroutine`
-  --> $DIR/coroutine-not-future.rs:18:39
+  --> $DIR/coroutine-not-future.rs:19:39
    |
 LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
 
 error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
-  --> $DIR/coroutine-not-future.rs:33:21
+  --> $DIR/coroutine-not-future.rs:37:21
    |
 LL |     takes_coroutine(returns_async_block());
    |     --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
@@ -21,27 +21,27 @@ LL |     takes_coroutine(returns_async_block());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_coroutine`
-  --> $DIR/coroutine-not-future.rs:18:39
+  --> $DIR/coroutine-not-future.rs:19:39
    |
 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:35:21: 35:29}: Coroutine<_>` is not satisfied
-  --> $DIR/coroutine-not-future.rs:35:21
+error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}: 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:35:21: 35:29}`
+   |     --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_coroutine`
-  --> $DIR/coroutine-not-future.rs:18:39
+  --> $DIR/coroutine-not-future.rs:19:39
    |
 LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
 
 error[E0277]: `impl Coroutine<Yield = (), Return = ()>` is not a future
-  --> $DIR/coroutine-not-future.rs:39:18
+  --> $DIR/coroutine-not-future.rs:43:18
    |
 LL |     takes_future(returns_coroutine());
    |     ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine<Yield = (), Return = ()>` is not a future
@@ -50,26 +50,26 @@ LL |     takes_future(returns_coroutine());
    |
    = help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
 note: required by a bound in `takes_future`
-  --> $DIR/coroutine-not-future.rs:17:26
+  --> $DIR/coroutine-not-future.rs:18:26
    |
 LL | fn takes_future(_f: impl Future<Output = ()>) {}
    |                          ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
 
-error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
-  --> $DIR/coroutine-not-future.rs:41:18
+error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
+  --> $DIR/coroutine-not-future.rs:47:9
    |
-LL |       takes_future(|ctx| {
-   |  _____------------_^
-   | |     |
-   | |     required by a bound introduced by this call
+LL |       takes_future(
+   |       ------------ required by a bound introduced by this call
+LL |           #[coroutine]
+LL | /         |ctx| {
 LL | |
-LL | |         ctx = yield ();
-LL | |     });
-   | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
+LL | |             ctx = yield ();
+LL | |         },
+   | |_________^ `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
    |
-   = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}`
+   = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}`
 note: required by a bound in `takes_future`
-  --> $DIR/coroutine-not-future.rs:17:26
+  --> $DIR/coroutine-not-future.rs:18:26
    |
 LL | fn takes_future(_f: impl Future<Output = ()>) {}
    |                          ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
diff --git a/tests/ui/async-await/issues/issue-51751.stderr b/tests/ui/async-await/issues/issue-51751.stderr
index ba256b19948..ab12e0427b4 100644
--- a/tests/ui/async-await/issues/issue-51751.stderr
+++ b/tests/ui/async-await/issues/issue-51751.stderr
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/issue-51751.rs:9:27
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 LL |     let result = inc(10000);
 LL |     let finished = result.await;
    |                           ^^^^^ only allowed inside `async` functions and blocks
diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr
index 02933f4f2f2..f8a4b5d9af8 100644
--- a/tests/ui/async-await/issues/issue-62009-1.stderr
+++ b/tests/ui/async-await/issues/issue-62009-1.stderr
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/issue-62009-1.rs:6:23
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 LL |     async { let (); }.await;
    |                       ^^^^^ only allowed inside `async` functions and blocks
 
@@ -10,7 +10,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/issue-62009-1.rs:10:7
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 ...
 LL |     }.await;
    |       ^^^^^ only allowed inside `async` functions and blocks
@@ -19,7 +19,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/issue-62009-1.rs:12:16
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 ...
 LL |     (|_| 2333).await;
    |                ^^^^^ only allowed inside `async` functions and blocks
diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr
index 80a831cc547..0004f99f901 100644
--- a/tests/ui/async-await/issues/issue-62009-2.stderr
+++ b/tests/ui/async-await/issues/issue-62009-2.stderr
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/issue-62009-2.rs:8:23
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 LL |     (async || 2333)().await;
    |                       ^^^^^ only allowed inside `async` functions and blocks
 
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
index f937311a5a0..6b7dfc1235e 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
@@ -6,15 +6,13 @@
 //@ error-pattern:coroutine resumed after completion
 //@ edition:2018
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
-use std::{
-    ops::Coroutine,
-    pin::Pin,
-};
+use std::{ops::Coroutine, pin::Pin};
 
 fn main() {
-    let mut g = || {
+    let mut g = #[coroutine]
+    || {
         yield;
     };
     Pin::new(&mut g).resume(()); // Yields once.
diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.stderr b/tests/ui/async-await/issues/non-async-enclosing-span.stderr
index 91a9e5aa6ca..9c26de1c504 100644
--- a/tests/ui/async-await/issues/non-async-enclosing-span.stderr
+++ b/tests/ui/async-await/issues/non-async-enclosing-span.stderr
@@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> $DIR/non-async-enclosing-span.rs:9:28
    |
 LL | fn main() {
-   |    ---- this is not `async`
+   | --------- this is not `async`
 LL |     let x = move || {};
 LL |     let y = do_the_thing().await;
    |                            ^^^^^ only allowed inside `async` functions and blocks
diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs
index 71b88124219..95de3c5b005 100644
--- a/tests/ui/async-await/non-trivial-drop.rs
+++ b/tests/ui/async-await/non-trivial-drop.rs
@@ -8,7 +8,7 @@ fn main() {
 }
 
 fn foo() {
-    || {
+    #[coroutine] || {
         yield drop(Config {
             nickname: NonCopy,
             b: NonCopy2,
diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs
new file mode 100644
index 00000000000..7f95fa7ebbe
--- /dev/null
+++ b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs
@@ -0,0 +1,8 @@
+//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"]
+fn main() {
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs
new file mode 100644
index 00000000000..d96e8b8ef84
--- /dev/null
+++ b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs
@@ -0,0 +1,8 @@
+//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"]
+fn main() {
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs
index db3407a7d55..694fa460e9b 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs
@@ -1,14 +1,29 @@
+//@ ignore-cross-compile because aux-bin does not yet support it
+//@ only-unix because SIGPIPE is a unix thing
+//@ aux-bin: assert-inherit-sig_dfl.rs
+//@ aux-bin: assert-inherit-sig_ign.rs
 //@ run-pass
-//@ aux-build:sigpipe-utils.rs
 
-#![feature(unix_sigpipe)]
+#![feature(rustc_private, unix_sigpipe)]
 
-#[unix_sigpipe = "inherit"]
+extern crate libc;
+
+// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec:ing child
+// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See
+// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384
+#[unix_sigpipe = "sig_dfl"]
 fn main() {
-    extern crate sigpipe_utils;
+    // First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"].
+    assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl");
+
+    // With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN.
+    unsafe {
+        libc::signal(libc::SIGPIPE, libc::SIG_IGN);
+    }
+    assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_ign");
+}
 
-    // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
-    // instead the default handler shall be installed. (We assume that the
-    // process that runs these tests have the default handler.)
-    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+fn assert_inherit_sigpipe_disposition(aux_bin: &str) {
+    let mut cmd = std::process::Command::new(aux_bin);
+    assert!(cmd.status().unwrap().success());
 }
diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
index dcf1c02bcee..4c1de72798c 100644
--- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
+++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
@@ -23,6 +23,13 @@ LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
    |                   |                  value moved here
    |                   move occurs because `x` has type `T`, which does not implement the `Copy` trait
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:8:9
+   |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   |         ^                            - you could clone this value
+   |         |
+   |         consider constraining this type parameter with `Clone`
 help: consider further restricting this bound
    |
 LL | fn copy<T: Magic + Copy>(x: T) -> (T, T) { (x, x) }
diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr
index 6fbbb55437e..1b59216b3c7 100644
--- a/tests/ui/binop/binop-consume-args.stderr
+++ b/tests/ui/binop/binop-consume-args.stderr
@@ -8,6 +8,13 @@ LL |     lhs + rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:5:8
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs + rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -26,6 +33,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:5:30
+   |
+LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs + rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn add<A: Add<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -41,6 +55,13 @@ LL |     lhs - rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:11:8
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs - rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -59,6 +80,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:11:30
+   |
+LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs - rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn sub<A: Sub<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -74,6 +102,13 @@ LL |     lhs * rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:17:8
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs * rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -92,6 +127,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:17:30
+   |
+LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs * rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn mul<A: Mul<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -107,6 +149,13 @@ LL |     lhs / rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:23:8
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs / rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -125,6 +174,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:23:30
+   |
+LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs / rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn div<A: Div<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -140,6 +196,13 @@ LL |     lhs % rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:29:8
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs % rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -158,6 +221,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:29:30
+   |
+LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs % rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn rem<A: Rem<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -173,6 +243,13 @@ LL |     lhs & rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:35:11
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           ^ consider constraining this type parameter with `Clone`
+LL |     lhs & rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 help: consider further restricting this bound
@@ -191,6 +268,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:35:36
+   |
+LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    ^ consider constraining this type parameter with `Clone`
+LL |     lhs & rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn bitand<A: BitAnd<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -206,6 +290,13 @@ LL |     lhs | rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:41:10
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |          ^ consider constraining this type parameter with `Clone`
+LL |     lhs | rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 help: consider further restricting this bound
@@ -224,6 +315,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:41:34
+   |
+LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                  ^ consider constraining this type parameter with `Clone`
+LL |     lhs | rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn bitor<A: BitOr<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -239,6 +337,13 @@ LL |     lhs ^ rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:47:11
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |           ^ consider constraining this type parameter with `Clone`
+LL |     lhs ^ rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 help: consider further restricting this bound
@@ -257,6 +362,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:47:36
+   |
+LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                                    ^ consider constraining this type parameter with `Clone`
+LL |     lhs ^ rhs;
+   |           --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn bitxor<A: BitXor<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -272,6 +384,13 @@ LL |     lhs << rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:53:8
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs << rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 help: consider further restricting this bound
@@ -290,6 +409,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:53:30
+   |
+LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs << rhs;
+   |            --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn shl<A: Shl<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
@@ -305,6 +431,13 @@ LL |     lhs >> rhs;
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+help: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:59:8
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     lhs >> rhs;
+   |     --- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 help: consider further restricting this bound
@@ -323,6 +456,13 @@ LL |     drop(lhs);
 LL |     drop(rhs);
    |          ^^^ value used here after move
    |
+help: if `B` implemented `Clone`, you could clone the value
+  --> $DIR/binop-consume-args.rs:59:30
+   |
+LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
+   |                              ^ consider constraining this type parameter with `Clone`
+LL |     lhs >> rhs;
+   |            --- you could clone this value
 help: consider restricting type parameter `B`
    |
 LL | fn shr<A: Shr<B, Output=()>, B: Copy>(lhs: A, rhs: B) {
diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr
index 1dd8c9a87d4..83c27590e90 100644
--- a/tests/ui/binop/binop-move-semantics.stderr
+++ b/tests/ui/binop/binop-move-semantics.stderr
@@ -11,6 +11,13 @@ LL | |     x;
    | |_____value used here after move
    |       `x` moved due to usage in operator
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/binop-move-semantics.rs:5:16
+   |
+LL | fn double_move<T: Add<Output=()>>(x: T) {
+   |                ^ consider constraining this type parameter with `Clone`
+LL |     x
+   |     - you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider further restricting this bound
@@ -51,6 +58,14 @@ LL |     x
 ...
 LL |     use_mut(n); use_imm(m);
    |                         - borrow later used here
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/binop-move-semantics.rs:17:18
+   |
+LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
+   |                  ^ consider constraining this type parameter with `Clone`
+LL |     let m = &x;
+   |             -- you could clone this value
 
 error[E0505]: cannot move out of `y` because it is borrowed
   --> $DIR/binop-move-semantics.rs:23:5
@@ -65,6 +80,15 @@ LL |     y;
    |     ^ move out of `y` occurs here
 LL |     use_mut(n); use_imm(m);
    |             - borrow later used here
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/binop-move-semantics.rs:17:18
+   |
+LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
+   |                  ^ consider constraining this type parameter with `Clone`
+LL |     let m = &x;
+LL |     let n = &mut y;
+   |             ------ you could clone this value
 
 error[E0507]: cannot move out of `*m` which is behind a mutable reference
   --> $DIR/binop-move-semantics.rs:30:5
@@ -80,12 +104,29 @@ LL | |     *n;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/binop-move-semantics.rs:26:24
+   |
+LL | fn illegal_dereference<T: Add<Output=()>>(mut x: T, y: T) {
+   |                        ^ consider constraining this type parameter with `Clone`
+...
+LL |     *m
+   |     -- you could clone this value
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/binop-move-semantics.rs:32:5
    |
 LL |     *n;
    |     ^^ move occurs because `*n` has type `T`, which does not implement the `Copy` trait
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/binop-move-semantics.rs:26:24
+   |
+LL | fn illegal_dereference<T: Add<Output=()>>(mut x: T, y: T) {
+   |                        ^ consider constraining this type parameter with `Clone`
+...
+LL |     *n;
+   |     -- you could clone this value
 
 error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
   --> $DIR/binop-move-semantics.rs:54:5
diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr
index 01647011207..9915acfe065 100644
--- a/tests/ui/borrowck/borrowck-move-by-capture.stderr
+++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr
@@ -11,6 +11,12 @@ LL |         let _h = to_fn_once(move || -> isize { *bar });
    |                             |                  variable moved due to use in closure
    |                             |                  move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
    |                             `bar` is moved here
+   |
+help: clone the value before moving it into the closure
+   |
+LL ~         let value = bar.clone();
+LL ~         let _h = to_fn_once(move || -> isize { value });
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
index 86bddacbdc7..b4b60d40d91 100644
--- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
+++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
@@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/borrowck-move-out-of-static-item.rs:3:1
    |
 LL | struct Foo {
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     test(BAR);
+   |          --- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
index 4d9477f8581..cc6c3bdeb10 100644
--- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr
+++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -14,7 +14,10 @@ note: if `S` implemented `Clone`, you could clone the value
   --> $DIR/borrowck-move-subcomponent.rs:6:1
    |
 LL | struct S {
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |   let pb = &a;
+   |            -- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr
index 1602058c183..c3b7b0b6080 100644
--- a/tests/ui/borrowck/borrowck-overloaded-call.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr
@@ -34,7 +34,10 @@ note: if `SFnOnce` implemented `Clone`, you could clone the value
   --> $DIR/borrowck-overloaded-call.rs:41:1
    |
 LL | struct SFnOnce {
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     s(" world".to_string());
+   |     - you could clone this value
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr
index f0eaf4bac7d..19f040556f8 100644
--- a/tests/ui/borrowck/clone-on-ref.stderr
+++ b/tests/ui/borrowck/clone-on-ref.stderr
@@ -32,6 +32,13 @@ LL |
 LL |     println!("{b}");
    |               --- borrow later used here
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/clone-on-ref.rs:11:8
+   |
+LL | fn bar<T: std::fmt::Display>(x: T) {
+   |        ^ consider constraining this type parameter with `Clone`
+LL |     let a = &x;
+   |             -- you could clone this value
 help: consider further restricting this bound
    |
 LL | fn bar<T: std::fmt::Display + Clone>(x: T) {
@@ -56,7 +63,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/clone-on-ref.rs:19:1
    |
 LL | struct A;
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+LL | fn qux(x: A) {
+LL |     let a = &x;
+   |             -- you could clone this value
 help: consider annotating `A` with `#[derive(Clone)]`
    |
 LL + #[derive(Clone)]
diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr
index b4775496f4f..a894fa63ace 100644
--- a/tests/ui/borrowck/issue-101119.stderr
+++ b/tests/ui/borrowck/issue-101119.stderr
@@ -22,7 +22,10 @@ note: if `State` implemented `Clone`, you could clone the value
   --> $DIR/issue-101119.rs:1:1
    |
 LL | struct State;
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |             fill_segment(state);
+   |                          ----- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr
index 94421c35c65..603055beadc 100644
--- a/tests/ui/borrowck/issue-103624.stderr
+++ b/tests/ui/borrowck/issue-103624.stderr
@@ -13,8 +13,11 @@ LL |             self.b;
 note: if `StructB` implemented `Clone`, you could clone the value
   --> $DIR/issue-103624.rs:23:1
    |
+LL |             self.b;
+   |             ------ you could clone this value
+...
 LL | struct StructB {}
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 
 error[E0521]: borrowed data escapes outside of method
   --> $DIR/issue-103624.rs:14:9
diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
index 701f00d079d..dde17d1f652 100644
--- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
+++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
@@ -15,7 +15,10 @@ note: if `Example<E, NoLifetime>` implemented `Clone`, you could clone the value
   --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1
    |
 LL | struct Example<E, FakeParam>(PhantomData<(fn(E), fn(FakeParam))>);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         unsafe { self.change() }
+   |                  ---- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr
index e2c3a9d5a26..057ac6d7e3d 100644
--- a/tests/ui/borrowck/issue-17718-static-move.stderr
+++ b/tests/ui/borrowck/issue-17718-static-move.stderr
@@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/issue-17718-static-move.rs:1:1
    |
 LL | struct Foo;
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let _a = FOO;
+   |              --- you could clone this value
 help: consider borrowing here
    |
 LL |     let _a = &FOO;
diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr
index 1da6f0bef02..20a4bd4e423 100644
--- a/tests/ui/borrowck/issue-20801.stderr
+++ b/tests/ui/borrowck/issue-20801.stderr
@@ -23,7 +23,10 @@ note: if `T` implemented `Clone`, you could clone the value
   --> $DIR/issue-20801.rs:3:1
    |
 LL | struct T(u8);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let a = unsafe { *mut_ref() };
+   |                      ---------- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let a = unsafe { *mut_ref() };
@@ -40,7 +43,10 @@ note: if `T` implemented `Clone`, you could clone the value
   --> $DIR/issue-20801.rs:3:1
    |
 LL | struct T(u8);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let b = unsafe { *imm_ref() };
+   |                      ---------- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let b = unsafe { *imm_ref() };
@@ -57,7 +63,10 @@ note: if `T` implemented `Clone`, you could clone the value
   --> $DIR/issue-20801.rs:3:1
    |
 LL | struct T(u8);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let c = unsafe { *mut_ptr() };
+   |                      ---------- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let c = unsafe { *mut_ptr() };
@@ -74,7 +83,10 @@ note: if `T` implemented `Clone`, you could clone the value
   --> $DIR/issue-20801.rs:3:1
    |
 LL | struct T(u8);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let d = unsafe { *const_ptr() };
+   |                      ------------ you could clone this value
 help: consider removing the dereference here
    |
 LL -     let d = unsafe { *const_ptr() };
diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr
index 43f4e820857..1e9b1d5209c 100644
--- a/tests/ui/borrowck/move-error-in-promoted-2.stderr
+++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr
@@ -11,7 +11,10 @@ note: if `S` implemented `Clone`, you could clone the value
   --> $DIR/move-error-in-promoted-2.rs:3:1
    |
 LL | struct S;
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     &([S][0],);
+   |       ------ you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr
index 40b64398aef..97d14051518 100644
--- a/tests/ui/borrowck/move-error-snippets.stderr
+++ b/tests/ui/borrowck/move-error-snippets.stderr
@@ -13,7 +13,12 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-error-snippets.rs:9:1
    |
 LL | struct A;
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+   |
+  ::: $DIR/move-error-snippets-ext.rs:5:17
+   |
+LL |         let a = $c;
+   |                 -- you could clone this value
    = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider borrowing here
    |
diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
index a4e70b50646..009e85a8031 100644
--- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
+++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
@@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/move-in-static-initializer-issue-38520.rs:5:1
    |
 LL | struct Foo(usize);
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL | static Y: usize = get(*&X);
+   |                       --- you could clone this value
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/move-in-static-initializer-issue-38520.rs:13:22
@@ -20,7 +23,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/move-in-static-initializer-issue-38520.rs:5:1
    |
 LL | struct Foo(usize);
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL | const Z: usize = get(*&X);
+   |                      --- you could clone this value
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr
index 53ff5f0107d..bdaa9449f91 100644
--- a/tests/ui/box/leak-alloc.stderr
+++ b/tests/ui/box/leak-alloc.stderr
@@ -16,7 +16,10 @@ note: if `Alloc` implemented `Clone`, you could clone the value
   --> $DIR/leak-alloc.rs:8:1
    |
 LL | struct Alloc {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let boxed = Box::new_in(10, alloc.by_ref());
+   |                                 ----- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-with-coroutine.rs b/tests/ui/coherence/coherence-with-coroutine.rs
index 1ba98344672..6b0617e950b 100644
--- a/tests/ui/coherence/coherence-with-coroutine.rs
+++ b/tests/ui/coherence/coherence-with-coroutine.rs
@@ -8,6 +8,7 @@
 
 type OpaqueCoroutine = impl Sized;
 fn defining_use() -> OpaqueCoroutine {
+    #[coroutine]
     || {
         for i in 0..10 {
             yield i;
diff --git a/tests/ui/coherence/coherence-with-coroutine.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
index 9cf20ea4936..5f58b3088f1 100644
--- a/tests/ui/coherence/coherence-with-coroutine.stock.stderr
+++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
-  --> $DIR/coherence-with-coroutine.rs:21:1
+  --> $DIR/coherence-with-coroutine.rs:22:1
    |
 LL | impl Trait for Wrapper<OpaqueCoroutine> {}
    | --------------------------------------- first implementation here
diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
index 7332a8f03c0..f1305202ad4 100644
--- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
+++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
@@ -1,4 +1,4 @@
-#![feature(inline_const, generic_const_exprs)]
+#![feature(generic_const_exprs)]
 //~^ WARN the feature `generic_const_exprs` is incomplete
 
 fn foo<T>() {
diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
index a85e0cbcf7e..03b0004bf0b 100644
--- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
@@ -1,8 +1,8 @@
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-block-is-poly.rs:1:26
+  --> $DIR/const-block-is-poly.rs:1:12
    |
-LL | #![feature(inline_const, generic_const_exprs)]
-   |                          ^^^^^^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
    = note: `#[warn(incomplete_features)]` on by default
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs
index 4333ec9f552..f9cf8210d65 100644
--- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![feature(inline_const, generic_const_exprs)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 use std::marker::PhantomData;
 
diff --git a/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs b/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs
index 3bc02f4c6bb..073e0fe0a7f 100644
--- a/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs
+++ b/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(generic_const_exprs)]
-#![feature(inline_const)]
 #![allow(incomplete_features)]
 
 pub struct ConstDefaultUnstable<const N: usize = { const { 3 } }>;
diff --git a/tests/ui/const_prop/dont-propagate-generic-instance-2.rs b/tests/ui/const_prop/dont-propagate-generic-instance-2.rs
index 768c9b3171a..08064bc6589 100644
--- a/tests/ui/const_prop/dont-propagate-generic-instance-2.rs
+++ b/tests/ui/const_prop/dont-propagate-generic-instance-2.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(inline_const)]
-
 // Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls.
 // This is relevant when we have an overlapping impl and builtin dyn instance.
 // See <https://github.com/rust-lang/rust/pull/114941> for more context.
diff --git a/tests/ui/consts/closure-structural-match-issue-90013.rs b/tests/ui/consts/closure-structural-match-issue-90013.rs
index 7a5d9b69ee4..454341a7784 100644
--- a/tests/ui/consts/closure-structural-match-issue-90013.rs
+++ b/tests/ui/consts/closure-structural-match-issue-90013.rs
@@ -1,6 +1,5 @@
 // Regression test for issue 90013.
 //@ check-pass
-#![feature(inline_const)]
 
 fn main() {
     const { || {} };
diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs
index b0d5e19ad55..933eb6cfc0a 100644
--- a/tests/ui/consts/const-block-const-bound.rs
+++ b/tests/ui/consts/const-block-const-bound.rs
@@ -1,7 +1,7 @@
 //@ known-bug: #103507
 
 #![allow(unused)]
-#![feature(const_trait_impl, inline_const, negative_impls)]
+#![feature(const_trait_impl, negative_impls)]
 
 use std::marker::Destruct;
 
diff --git a/tests/ui/consts/const-blocks/fn-call-in-const.rs b/tests/ui/consts/const-blocks/fn-call-in-const.rs
index 9bf267b7de9..a3e24ddae7d 100644
--- a/tests/ui/consts/const-blocks/fn-call-in-const.rs
+++ b/tests/ui/consts/const-blocks/fn-call-in-const.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 
-#![feature(inline_const)]
 #![allow(unused)]
 
 // Some type that is not copyable.
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs
index 6c4fca35626..2517560c2c3 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 #![feature(core_intrinsics)]
 #![feature(const_heap)]
-#![feature(inline_const)]
 
 use std::intrinsics;
 
diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs
index 146a87862e8..c53bb36f4a2 100644
--- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs
+++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 #![feature(core_intrinsics)]
 #![feature(const_heap)]
-#![feature(inline_const)]
 
 use std::intrinsics;
 
diff --git a/tests/ui/consts/issue-102117.rs b/tests/ui/consts/issue-102117.rs
index 3ed90aed235..6cb9832bcd8 100644
--- a/tests/ui/consts/issue-102117.rs
+++ b/tests/ui/consts/issue-102117.rs
@@ -1,4 +1,4 @@
-#![feature(inline_const, const_type_id)]
+#![feature(const_type_id)]
 
 use std::alloc::Layout;
 use std::any::TypeId;
diff --git a/tests/ui/coroutine/addassign-yield.rs b/tests/ui/coroutine/addassign-yield.rs
index 8718e73512f..8329b53d715 100644
--- a/tests/ui/coroutine/addassign-yield.rs
+++ b/tests/ui/coroutine/addassign-yield.rs
@@ -5,21 +5,21 @@
 // is being used), we were failing to account for all types that might
 // possibly be live across a yield point.
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn foo() {
-    let _x = static || {
+    let _x = #[coroutine] static || {
         let mut s = String::new();
         s += { yield; "" };
     };
 
-    let _y = static || {
+    let _y = #[coroutine] static || {
         let x = &mut 0;
         *{ yield; x } += match String::new() { _ => 0 };
     };
 
     // Please don't ever actually write something like this
-    let _z = static || {
+    let _z = #[coroutine] static || {
         let x = &mut 0;
         *{
             let inner = &mut 1;
diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs
index 5fce70e8e54..4c239f9ee76 100644
--- a/tests/ui/coroutine/auto-trait-regions.rs
+++ b/tests/ui/coroutine/auto-trait-regions.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(auto_traits)]
 #![feature(negative_impls)]
 
@@ -23,7 +23,7 @@ fn assert_foo<T: Foo>(f: T) {}
 fn main() {
     // Make sure 'static is erased for coroutine interiors so we can't match it in trait selection
     let x: &'static _ = &OnlyFooIfStaticRef(No);
-    let gen = move || {
+    let gen = #[coroutine] move || {
         let x = x;
         yield;
         assert_foo(x);
@@ -33,7 +33,7 @@ fn main() {
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
-    let gen = move || {
+    let gen = #[coroutine] move || {
         let x = x;
         yield;
         assert_foo(x);
@@ -41,7 +41,7 @@ fn main() {
     assert_foo(gen); // ok
 
     // Disallow impls which relates lifetimes in the coroutine interior
-    let gen = move || {
+    let gen = #[coroutine] move || {
         let a = A(&mut true, &mut true, No);
         //~^ temporary value dropped while borrowed
         //~| temporary value dropped while borrowed
diff --git a/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs
index 8af6973134a..8ecb8c0c097 100644
--- a/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs
+++ b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs
@@ -5,6 +5,7 @@ use std::marker::Unpin;
 use std::ops::Coroutine;
 
 pub fn g() -> impl Coroutine<(), Yield = (), Return = ()> {
+    #[coroutine]
     || {
         yield;
     }
diff --git a/tests/ui/coroutine/auxiliary/unwind-aux.rs b/tests/ui/coroutine/auxiliary/unwind-aux.rs
index ff1e8ed32cd..5d5e5c2218d 100644
--- a/tests/ui/coroutine/auxiliary/unwind-aux.rs
+++ b/tests/ui/coroutine/auxiliary/unwind-aux.rs
@@ -2,9 +2,10 @@
 //@ no-prefer-dynamic
 //@ edition:2021
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 pub fn run<T>(a: T) {
-    let _ = move || {
+    let _ = #[coroutine]
+    move || {
         drop(a);
         yield;
     };
diff --git a/tests/ui/coroutine/auxiliary/xcrate-reachable.rs b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs
index 673153f0619..0b5d1882300 100644
--- a/tests/ui/coroutine/auxiliary/xcrate-reachable.rs
+++ b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs
@@ -7,6 +7,7 @@ fn msg() -> u32 {
 }
 
 pub fn foo() -> impl Coroutine<(), Yield = (), Return = u32> {
+    #[coroutine]
     || {
         yield;
         return msg();
diff --git a/tests/ui/coroutine/auxiliary/xcrate.rs b/tests/ui/coroutine/auxiliary/xcrate.rs
index f749a95ad35..52f188135bd 100644
--- a/tests/ui/coroutine/auxiliary/xcrate.rs
+++ b/tests/ui/coroutine/auxiliary/xcrate.rs
@@ -1,9 +1,10 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::marker::Unpin;
 use std::ops::Coroutine;
 
 pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
+    #[coroutine]
     || {
         if false {
             yield;
@@ -12,7 +13,10 @@ pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
 }
 
 pub fn bar<T: 'static>(t: T) -> Box<Coroutine<(), Yield = T, Return = ()> + Unpin> {
-    Box::new(|| {
-        yield t;
-    })
+    Box::new(
+        #[coroutine]
+        || {
+            yield t;
+        },
+    )
 }
diff --git a/tests/ui/coroutine/borrow-in-tail-expr.rs b/tests/ui/coroutine/borrow-in-tail-expr.rs
index 2f0aa62019e..380e95cfc77 100644
--- a/tests/ui/coroutine/borrow-in-tail-expr.rs
+++ b/tests/ui/coroutine/borrow-in-tail-expr.rs
@@ -1,9 +1,9 @@
 //@ run-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let _a = || {
+    let _a = #[coroutine] || {
         yield;
         let a = String::new();
         a.len()
diff --git a/tests/ui/coroutine/borrowing.rs b/tests/ui/coroutine/borrowing.rs
index 778eed8bd0d..a6628766c1b 100644
--- a/tests/ui/coroutine/borrowing.rs
+++ b/tests/ui/coroutine/borrowing.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
@@ -6,13 +6,13 @@ use std::pin::Pin;
 fn main() {
     let _b = {
         let a = 3;
-        Pin::new(&mut || yield &a).resume(())
+        Pin::new(&mut #[coroutine] || yield &a).resume(())
         //~^ ERROR: `a` does not live long enough
     };
 
     let _b = {
         let a = 3;
-        || {
+        #[coroutine] || {
             yield &a
             //~^ ERROR: `a` does not live long enough
         }
diff --git a/tests/ui/coroutine/borrowing.stderr b/tests/ui/coroutine/borrowing.stderr
index acd4cdafdfd..4f8b9737777 100644
--- a/tests/ui/coroutine/borrowing.stderr
+++ b/tests/ui/coroutine/borrowing.stderr
@@ -1,13 +1,14 @@
 error[E0597]: `a` does not live long enough
-  --> $DIR/borrowing.rs:9:33
+  --> $DIR/borrowing.rs:9:46
    |
 LL |     let _b = {
    |         -- borrow later stored here
 LL |         let a = 3;
-LL |         Pin::new(&mut || yield &a).resume(())
-   |                       --        ^ borrowed value does not live long enough
-   |                       |
-   |                       value captured here by coroutine
+   |             - binding `a` declared here
+LL |         Pin::new(&mut #[coroutine] || yield &a).resume(())
+   |                                    --        ^ borrowed value does not live long enough
+   |                                    |
+   |                                    value captured here by coroutine
 LL |
 LL |     };
    |     - `a` dropped here while still borrowed
@@ -18,8 +19,9 @@ error[E0597]: `a` does not live long enough
 LL |     let _b = {
    |         -- borrow later stored here
 LL |         let a = 3;
-LL |         || {
-   |         -- value captured here by coroutine
+   |             - binding `a` declared here
+LL |         #[coroutine] || {
+   |                      -- value captured here by coroutine
 LL |             yield &a
    |                    ^ borrowed value does not live long enough
 ...
diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs
index a316c50e867..327756ebe66 100644
--- a/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs
+++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs
@@ -7,27 +7,27 @@ struct Contravariant<'a>(fn(&'a ()));
 struct Covariant<'a>(fn() -> &'a ());
 
 fn bad1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'short>> {
-    |_: Covariant<'short>| {
+    #[coroutine] |_: Covariant<'short>| {
         let a: Covariant<'long> = yield ();
         //~^ ERROR lifetime may not live long enough
     }
 }
 
 fn bad2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'long>> {
-    |_: Contravariant<'long>| {
+    #[coroutine] |_: Contravariant<'long>| {
         let a: Contravariant<'short> = yield ();
         //~^ ERROR lifetime may not live long enough
     }
 }
 
 fn good1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'long>> {
-    |_: Covariant<'long>| {
+    #[coroutine] |_: Covariant<'long>| {
         let a: Covariant<'short> = yield ();
     }
 }
 
 fn good2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'short>> {
-    |_: Contravariant<'short>| {
+    #[coroutine] |_: Contravariant<'short>| {
         let a: Contravariant<'long> = yield ();
     }
 }
diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr
index e0cbca2dd52..8eb7ab3501b 100644
--- a/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr
+++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr
@@ -5,15 +5,15 @@ LL | fn bad1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'short>> {
    |         ------  ----- lifetime `'long` defined here
    |         |
    |         lifetime `'short` defined here
-LL |     |_: Covariant<'short>| {
+LL |     #[coroutine] |_: Covariant<'short>| {
 LL |         let a: Covariant<'long> = yield ();
    |                ^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
    |
    = help: consider adding the following bound: `'short: 'long`
 help: consider adding 'move' keyword before the nested closure
    |
-LL |     move |_: Covariant<'short>| {
-   |     ++++
+LL |     #[coroutine] move |_: Covariant<'short>| {
+   |                  ++++
 
 error: lifetime may not live long enough
   --> $DIR/check-resume-ty-lifetimes-2.rs:18:40
@@ -22,15 +22,15 @@ LL | fn bad2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'long>> {
    |         ------  ----- lifetime `'long` defined here
    |         |
    |         lifetime `'short` defined here
-LL |     |_: Contravariant<'long>| {
+LL |     #[coroutine] |_: Contravariant<'long>| {
 LL |         let a: Contravariant<'short> = yield ();
    |                                        ^^^^^^^^ yielding this value requires that `'short` must outlive `'long`
    |
    = help: consider adding the following bound: `'short: 'long`
 help: consider adding 'move' keyword before the nested closure
    |
-LL |     move |_: Contravariant<'long>| {
-   |     ++++
+LL |     #[coroutine] move |_: Contravariant<'long>| {
+   |                  ++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.rs b/tests/ui/coroutine/check-resume-ty-lifetimes.rs
index add0b5080a8..b75e46c541c 100644
--- a/tests/ui/coroutine/check-resume-ty-lifetimes.rs
+++ b/tests/ui/coroutine/check-resume-ty-lifetimes.rs
@@ -1,5 +1,5 @@
 #![feature(coroutine_trait)]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![allow(unused)]
 
 use std::ops::Coroutine;
@@ -9,11 +9,14 @@ use std::pin::pin;
 fn mk_static(s: &str) -> &'static str {
     let mut storage: Option<&'static str> = None;
 
-    let mut coroutine = pin!(|_: &str| {
-        let x: &'static str = yield ();
-        //~^ ERROR lifetime may not live long enough
-        storage = Some(x);
-    });
+    let mut coroutine = pin!(
+        #[coroutine]
+        |_: &str| {
+            let x: &'static str = yield ();
+            //~^ ERROR lifetime may not live long enough
+            storage = Some(x);
+        }
+    );
 
     coroutine.as_mut().resume(s);
     coroutine.as_mut().resume(s);
diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr
index f373aa778a8..1fbaeb9f7fa 100644
--- a/tests/ui/coroutine/check-resume-ty-lifetimes.stderr
+++ b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr
@@ -1,11 +1,11 @@
 error: lifetime may not live long enough
-  --> $DIR/check-resume-ty-lifetimes.rs:13:16
+  --> $DIR/check-resume-ty-lifetimes.rs:15:20
    |
 LL | fn mk_static(s: &str) -> &'static str {
    |                 - let's call the lifetime of this reference `'1`
 ...
-LL |         let x: &'static str = yield ();
-   |                ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
+LL |             let x: &'static str = yield ();
+   |                    ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs
index 9a165cf4672..56d1ccac703 100644
--- a/tests/ui/coroutine/clone-impl-static.rs
+++ b/tests/ui/coroutine/clone-impl-static.rs
@@ -1,10 +1,11 @@
 // gate-test-coroutine_clone
 // Verifies that static coroutines cannot be cloned/copied.
 
-#![feature(coroutines, coroutine_clone)]
+#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
 
 fn main() {
-    let gen = static move || {
+    let gen = #[coroutine]
+    static move || {
         yield;
     };
     check_copy(&gen);
diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr
index 8fa9fb12bf6..43920326d5d 100644
--- a/tests/ui/coroutine/clone-impl-static.stderr
+++ b/tests/ui/coroutine/clone-impl-static.stderr
@@ -1,27 +1,27 @@
-error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Copy` is not satisfied
-  --> $DIR/clone-impl-static.rs:10:16
+error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Copy` is not satisfied
+  --> $DIR/clone-impl-static.rs:11:16
    |
 LL |     check_copy(&gen);
-   |     ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
+   |     ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-static.rs:16:18
+  --> $DIR/clone-impl-static.rs:17:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Clone` is not satisfied
-  --> $DIR/clone-impl-static.rs:12:17
+error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Clone` is not satisfied
+  --> $DIR/clone-impl-static.rs:13:17
    |
 LL |     check_clone(&gen);
-   |     ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
+   |     ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-static.rs:17:19
+  --> $DIR/clone-impl-static.rs:18:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs
index fffdae632ef..94420e56a22 100644
--- a/tests/ui/coroutine/clone-impl.rs
+++ b/tests/ui/coroutine/clone-impl.rs
@@ -2,13 +2,14 @@
 // Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held
 // across awaits can be cloned/copied.
 
-#![feature(coroutines, coroutine_clone)]
+#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
 
 struct NonClone;
 
 fn test1() {
     let copyable: u32 = 123;
-    let gen_copy_0 = move || {
+    let gen_copy_0 = #[coroutine]
+    move || {
         yield;
         drop(copyable);
     };
@@ -18,7 +19,8 @@ fn test1() {
 
 fn test2() {
     let copyable: u32 = 123;
-    let gen_copy_1 = move || {
+    let gen_copy_1 = #[coroutine]
+    move || {
         /*
         let v = vec!['a'];
         let n = NonClone;
@@ -37,7 +39,8 @@ fn test2() {
 
 fn test3() {
     let clonable_0: Vec<u32> = Vec::new();
-    let gen_clone_0 = move || {
+    let gen_clone_0 = #[coroutine]
+    move || {
         let v = vec!['a'];
         yield;
         drop(v);
@@ -51,7 +54,8 @@ fn test3() {
 
 fn test4() {
     let clonable_1: Vec<u32> = Vec::new();
-    let gen_clone_1 = move || {
+    let gen_clone_1 = #[coroutine]
+    move || {
         let v = vec!['a'];
         /*
         let n = NonClone;
@@ -71,7 +75,8 @@ fn test4() {
 
 fn test5() {
     let non_clonable: NonClone = NonClone;
-    let gen_non_clone = move || {
+    let gen_non_clone = #[coroutine]
+    move || {
         yield;
         drop(non_clonable);
     };
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index b454846faac..5330d3bbd39 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -1,76 +1,76 @@
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
-  --> $DIR/clone-impl.rs:46:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
+  --> $DIR/clone-impl.rs:49:5
    |
-LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:44:14
+  --> $DIR/clone-impl.rs:47:14
    |
 LL |         drop(clonable_0);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:84:18
+  --> $DIR/clone-impl.rs:89:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
-  --> $DIR/clone-impl.rs:46:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
+  --> $DIR/clone-impl.rs:49:5
    |
-LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:42:9
+  --> $DIR/clone-impl.rs:45:9
    |
 LL |         let v = vec!['a'];
    |             - has type `Vec<char>` which does not implement `Copy`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `v` maybe used later
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:84:18
+  --> $DIR/clone-impl.rs:89:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
-  --> $DIR/clone-impl.rs:66:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
+  --> $DIR/clone-impl.rs:70:5
    |
-LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:64:14
+  --> $DIR/clone-impl.rs:68:14
    |
 LL |         drop(clonable_1);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:84:18
+  --> $DIR/clone-impl.rs:89:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
-  --> $DIR/clone-impl.rs:66:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
+  --> $DIR/clone-impl.rs:70:5
    |
-LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:60:9
+  --> $DIR/clone-impl.rs:64:9
    |
 LL |         let v = vec!['a'];
    |             - has type `Vec<char>` which does not implement `Copy`
@@ -78,27 +78,27 @@ LL |         let v = vec!['a'];
 LL |         yield;
    |         ^^^^^ yield occurs here, with `v` maybe used later
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:84:18
+  --> $DIR/clone-impl.rs:89:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
-  --> $DIR/clone-impl.rs:78:5
+error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
+  --> $DIR/clone-impl.rs:83:5
    |
-LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:76:14
+  --> $DIR/clone-impl.rs:81:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:84:18
+  --> $DIR/clone-impl.rs:89:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -108,22 +108,22 @@ LL + #[derive(Copy)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
-  --> $DIR/clone-impl.rs:80:5
+error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
+  --> $DIR/clone-impl.rs:85:5
    |
-LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Clone`
    |
 note: captured value does not implement `Clone`
-  --> $DIR/clone-impl.rs:76:14
+  --> $DIR/clone-impl.rs:81:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl.rs:85:19
+  --> $DIR/clone-impl.rs:90:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr
index 41aa2d63af0..c223f1f211a 100644
--- a/tests/ui/coroutine/clone-rpit.next.stderr
+++ b/tests/ui/coroutine/clone-rpit.next.stderr
@@ -5,32 +5,32 @@ LL | pub fn foo<'a, 'b>() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires coroutine witness types for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires building MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires match-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires type-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:14:5
+  --> $DIR/clone-rpit.rs:15:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs
index 0df9bf61601..66569b4f427 100644
--- a/tests/ui/coroutine/clone-rpit.rs
+++ b/tests/ui/coroutine/clone-rpit.rs
@@ -11,6 +11,7 @@
 // witness types, which we don't know until after borrowck. When we later check
 // the goal for correctness, we want to be able to bind the `impl Clone` opaque.
 pub fn foo<'a, 'b>() -> impl Clone {
+    #[coroutine]
     move |_: ()| {
         let () = yield ();
     }
diff --git a/tests/ui/coroutine/conditional-drop.rs b/tests/ui/coroutine/conditional-drop.rs
index 65d3a9e701e..52e1b561946 100644
--- a/tests/ui/coroutine/conditional-drop.rs
+++ b/tests/ui/coroutine/conditional-drop.rs
@@ -3,7 +3,7 @@
 //@ revisions: default nomiropt
 //@[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
@@ -29,7 +29,7 @@ fn main() {
 }
 
 fn t1() {
-    let mut a = || {
+    let mut a = #[coroutine] || {
         let b = B;
         if test() {
             drop(b);
@@ -45,7 +45,7 @@ fn t1() {
 }
 
 fn t2() {
-    let mut a = || {
+    let mut a = #[coroutine] || {
         let b = B;
         if test2() {
             drop(b);
diff --git a/tests/ui/coroutine/control-flow.rs b/tests/ui/coroutine/control-flow.rs
index 9070ba17856..f64b6f73883 100644
--- a/tests/ui/coroutine/control-flow.rs
+++ b/tests/ui/coroutine/control-flow.rs
@@ -3,7 +3,7 @@
 //@ revisions: default nomiropt
 //@[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
@@ -24,25 +24,25 @@ fn finish<T>(mut amt: usize, mut t: T) -> T::Return
 }
 
 fn main() {
-    finish(1, || yield);
-    finish(8, || {
+    finish(1, #[coroutine] || yield);
+    finish(8, #[coroutine] || {
         for _ in 0..8 {
             yield;
         }
     });
-    finish(1, || {
+    finish(1, #[coroutine] || {
         if true {
             yield;
         } else {
         }
     });
-    finish(1, || {
+    finish(1, #[coroutine] || {
         if false {
         } else {
             yield;
         }
     });
-    finish(2, || {
+    finish(2, #[coroutine] || {
         if { yield; false } {
             yield;
             panic!()
diff --git a/tests/ui/coroutine/coroutine-region-requirements.rs b/tests/ui/coroutine/coroutine-region-requirements.rs
index 8bc34fdd2f0..ab6f16995e2 100644
--- a/tests/ui/coroutine/coroutine-region-requirements.rs
+++ b/tests/ui/coroutine/coroutine-region-requirements.rs
@@ -1,9 +1,9 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn dangle(x: &mut i32) -> &'static mut i32 {
-    let mut g = || {
+    let mut g = #[coroutine] || {
         yield;
         x
     };
diff --git a/tests/ui/coroutine/coroutine-resume-after-panic.rs b/tests/ui/coroutine/coroutine-resume-after-panic.rs
index 8445bf7e635..2745ebc6132 100644
--- a/tests/ui/coroutine/coroutine-resume-after-panic.rs
+++ b/tests/ui/coroutine/coroutine-resume-after-panic.rs
@@ -5,7 +5,7 @@
 
 // Test that we get the correct message for resuming a panicked coroutine.
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     ops::Coroutine,
@@ -14,7 +14,7 @@ use std::{
 };
 
 fn main() {
-    let mut g = || {
+    let mut g = #[coroutine] || {
         panic!();
         yield;
     };
diff --git a/tests/ui/coroutine/coroutine-with-nll.rs b/tests/ui/coroutine/coroutine-with-nll.rs
index 28a3643fbc9..fa77ab4e049 100644
--- a/tests/ui/coroutine/coroutine-with-nll.rs
+++ b/tests/ui/coroutine/coroutine-with-nll.rs
@@ -1,6 +1,7 @@
 #![feature(coroutines)]
 
 fn main() {
+    #[coroutine]
     || {
         // The reference in `_a` is a Legal with NLL since it ends before the yield
         let _a = &mut true;
diff --git a/tests/ui/coroutine/coroutine-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr
index 77e8bb1f92e..3f3d51da311 100644
--- a/tests/ui/coroutine/coroutine-with-nll.stderr
+++ b/tests/ui/coroutine/coroutine-with-nll.stderr
@@ -1,5 +1,5 @@
 error[E0626]: borrow may still be in use when coroutine yields
-  --> $DIR/coroutine-with-nll.rs:7:17
+  --> $DIR/coroutine-with-nll.rs:8:17
    |
 LL |         let b = &mut true;
    |                 ^^^^^^^^^
diff --git a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs
index 3c91b3c9329..f3110d71d0d 100644
--- a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs
+++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs
@@ -1,5 +1,5 @@
 #![feature(coroutine_trait)]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 // Test that we cannot create a coroutine that returns a value of its
 // own type.
@@ -12,7 +12,7 @@ pub fn want_cyclic_coroutine_return<T>(_: T)
 }
 
 fn supply_cyclic_coroutine_return() {
-    want_cyclic_coroutine_return(|| {
+    want_cyclic_coroutine_return(#[coroutine] || {
         //~^ ERROR type mismatch
         if false { yield None.unwrap(); }
         None.unwrap()
@@ -25,7 +25,7 @@ pub fn want_cyclic_coroutine_yield<T>(_: T)
 }
 
 fn supply_cyclic_coroutine_yield() {
-    want_cyclic_coroutine_yield(|| {
+    want_cyclic_coroutine_yield(#[coroutine] || {
         //~^ ERROR type mismatch
         if false { yield None.unwrap(); }
         None.unwrap()
diff --git a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr
index 325030524ba..32799148ae1 100644
--- a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr
+++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr
@@ -1,8 +1,8 @@
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36}`
-  --> $DIR/coroutine-yielding-or-returning-itself.rs:15:34
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49}`
+  --> $DIR/coroutine-yielding-or-returning-itself.rs:15:47
    |
-LL |       want_cyclic_coroutine_return(|| {
-   |  _____----------------------------_^
+LL |       want_cyclic_coroutine_return(#[coroutine] || {
+   |  _____----------------------------______________^
    | |     |
    | |     required by a bound introduced by this call
 LL | |
@@ -23,11 +23,11 @@ LL | pub fn want_cyclic_coroutine_return<T>(_: T)
 LL |     where T: Coroutine<Yield = (), Return = T>
    |                                    ^^^^^^^^^^ required by this bound in `want_cyclic_coroutine_return`
 
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35}`
-  --> $DIR/coroutine-yielding-or-returning-itself.rs:28:33
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48}`
+  --> $DIR/coroutine-yielding-or-returning-itself.rs:28:46
    |
-LL |       want_cyclic_coroutine_yield(|| {
-   |  _____---------------------------_^
+LL |       want_cyclic_coroutine_yield(#[coroutine] || {
+   |  _____---------------------------______________^
    | |     |
    | |     required by a bound introduced by this call
 LL | |
diff --git a/tests/ui/coroutine/derived-drop-parent-expr.rs b/tests/ui/coroutine/derived-drop-parent-expr.rs
index f70a732c90f..cc217e4960e 100644
--- a/tests/ui/coroutine/derived-drop-parent-expr.rs
+++ b/tests/ui/coroutine/derived-drop-parent-expr.rs
@@ -1,7 +1,7 @@
 //@ build-pass
 
 //! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn assert_send<T: Send>(_thing: T) {}
 
@@ -9,8 +9,8 @@ fn assert_send<T: Send>(_thing: T) {}
 pub struct Client { pub nickname: String }
 
 fn main() {
-    let g = move || match drop(Client { ..Client::default() }) {
-        _status => yield,
-    };
+    let g = #[coroutine] move || match drop(Client { ..Client::default() }) {
+            _status => yield,
+        };
     assert_send(g);
 }
diff --git a/tests/ui/coroutine/discriminant.rs b/tests/ui/coroutine/discriminant.rs
index a44d8f74746..d6879e21825 100644
--- a/tests/ui/coroutine/discriminant.rs
+++ b/tests/ui/coroutine/discriminant.rs
@@ -86,7 +86,7 @@ fn cycle(
 fn main() {
     // Has only one invalid discr. value.
     let gen_u8_tiny_niche = || {
-        || {
+        #[coroutine] || {
             // 3 reserved variants
 
             yield250!(); // 253 variants
@@ -98,7 +98,7 @@ fn main() {
 
     // Uses all values in the u8 discriminant.
     let gen_u8_full = || {
-        || {
+        #[coroutine] || {
             // 3 reserved variants
 
             yield250!(); // 253 variants
@@ -111,7 +111,7 @@ fn main() {
 
     // Barely needs a u16 discriminant.
     let gen_u16 = || {
-        || {
+        #[coroutine] || {
             // 3 reserved variants
 
             yield250!(); // 253 variants
diff --git a/tests/ui/coroutine/drop-and-replace.rs b/tests/ui/coroutine/drop-and-replace.rs
index 6e30d76512b..d3d7e000020 100644
--- a/tests/ui/coroutine/drop-and-replace.rs
+++ b/tests/ui/coroutine/drop-and-replace.rs
@@ -4,7 +4,7 @@
 // #60187, this produced incorrect code for coroutines when a saved local was
 // re-assigned.
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
@@ -17,7 +17,8 @@ impl Drop for Foo {
 }
 
 fn main() {
-    let mut a = || {
+    let mut a = #[coroutine]
+    || {
         let mut x = Foo(4);
         yield;
         assert_eq!(x.0, 4);
diff --git a/tests/ui/coroutine/drop-control-flow.rs b/tests/ui/coroutine/drop-control-flow.rs
index f4e8eed4f8d..f576b1b7594 100644
--- a/tests/ui/coroutine/drop-control-flow.rs
+++ b/tests/ui/coroutine/drop-control-flow.rs
@@ -4,7 +4,7 @@
 // and also that values that are dropped along all paths to a yield do not get
 // included in the coroutine type.
 
-#![feature(coroutines, negative_impls)]
+#![feature(coroutines, negative_impls, stmt_expr_attributes)]
 #![allow(unused_assignments, dead_code)]
 
 struct Ptr;
@@ -19,7 +19,7 @@ fn assert_send<T: Send>(_: T) {}
 
 // This test case is reduced from tests/ui/drop/dynamic-drop-async.rs
 fn one_armed_if(arg: bool) {
-    let _ = || {
+    let _ = #[coroutine] || {
         let arr = [Ptr];
         if arg {
             drop(arr);
@@ -29,7 +29,7 @@ fn one_armed_if(arg: bool) {
 }
 
 fn two_armed_if(arg: bool) {
-    assert_send(|| {
+    assert_send(#[coroutine] || {
         let arr = [Ptr];
         if arg {
             drop(arr);
@@ -41,7 +41,7 @@ fn two_armed_if(arg: bool) {
 }
 
 fn if_let(arg: Option<i32>) {
-    let _ = || {
+    let _ = #[coroutine] || {
         let arr = [Ptr];
         if let Some(_) = arg {
             drop(arr);
@@ -51,7 +51,7 @@ fn if_let(arg: Option<i32>) {
 }
 
 fn init_in_if(arg: bool) {
-    assert_send(|| {
+    assert_send(#[coroutine] || {
         let mut x = NonSend;
         drop(x);
         if arg {
@@ -63,7 +63,7 @@ fn init_in_if(arg: bool) {
 }
 
 fn init_in_match_arm(arg: Option<i32>) {
-    assert_send(|| {
+    assert_send(#[coroutine] || {
         let mut x = NonSend;
         drop(x);
         match arg {
@@ -74,7 +74,7 @@ fn init_in_match_arm(arg: Option<i32>) {
 }
 
 fn reinit() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut arr = [Ptr];
         drop(arr);
         arr = [Ptr];
@@ -83,7 +83,7 @@ fn reinit() {
 }
 
 fn loop_uninit() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut arr = [Ptr];
         let mut count = 0;
         drop(arr);
@@ -96,7 +96,7 @@ fn loop_uninit() {
 }
 
 fn nested_loop() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut arr = [Ptr];
         let mut count = 0;
         drop(arr);
@@ -111,7 +111,7 @@ fn nested_loop() {
 }
 
 fn loop_continue(b: bool) {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut arr = [Ptr];
         let mut count = 0;
         drop(arr);
diff --git a/tests/ui/coroutine/drop-env.rs b/tests/ui/coroutine/drop-env.rs
index b189ab81499..d36228dc849 100644
--- a/tests/ui/coroutine/drop-env.rs
+++ b/tests/ui/coroutine/drop-env.rs
@@ -3,7 +3,7 @@
 //@ revisions: default nomiropt
 //@[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 #![allow(dropping_copy_types)]
 
 use std::ops::Coroutine;
@@ -28,7 +28,7 @@ fn main() {
 
 fn t1() {
     let b = B;
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield;
         drop(b);
     };
@@ -42,7 +42,7 @@ fn t1() {
 
 fn t2() {
     let b = B;
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield b;
     };
 
@@ -55,7 +55,7 @@ fn t2() {
 
 fn t3() {
     let b = B;
-    let foo = || {
+    let foo = #[coroutine] || {
         yield;
         drop(b);
     };
diff --git a/tests/ui/coroutine/drop-track-addassign-yield.rs b/tests/ui/coroutine/drop-track-addassign-yield.rs
index b1a4bd79f31..537e66c41b2 100644
--- a/tests/ui/coroutine/drop-track-addassign-yield.rs
+++ b/tests/ui/coroutine/drop-track-addassign-yield.rs
@@ -3,10 +3,10 @@
 // Based on addassign-yield.rs, but with drop tracking enabled. Originally we did not implement
 // the fake_read callback on ExprUseVisitor which caused this case to break.
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn foo() {
-    let _y = static || {
+    let _y = #[coroutine] static || {
         let x = &mut 0;
         *{
             yield;
@@ -17,7 +17,7 @@ fn foo() {
     };
 
     // Please don't ever actually write something like this
-    let _z = static || {
+    let _z = #[coroutine] static || {
         let x = &mut 0;
         *{
             let inner = &mut 1;
diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.rs b/tests/ui/coroutine/drop-tracking-parent-expression.rs
index 4d40192c07a..0f4d99c8936 100644
--- a/tests/ui/coroutine/drop-tracking-parent-expression.rs
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, negative_impls, rustc_attrs)]
+#![feature(coroutines, negative_impls, rustc_attrs, stmt_expr_attributes)]
 
 macro_rules! type_combinations {
     (
@@ -14,7 +14,7 @@ macro_rules! type_combinations {
         // Struct update syntax. This fails because the Client used in the update is considered
         // dropped *after* the yield.
         {
-            let g = move || match drop($name::Client { ..$name::Client::default() }) {
+            let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
             //~^ `significant_drop::Client` which is not `Send`
             //~| `insignificant_dtor::Client` which is not `Send`
             //~| `derived_drop::Client` which is not `Send`
@@ -29,7 +29,7 @@ macro_rules! type_combinations {
         // Simple owned value. This works because the Client is considered moved into `drop`,
         // even though the temporary expression doesn't end until after the yield.
         {
-            let g = move || match drop($name::Client::default()) {
+            let g = #[coroutine] move || match drop($name::Client::default()) {
                 _ => yield,
             };
             assert_send(g);
diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
index 21aa35b9579..5f8d8495e4f 100644
--- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
@@ -13,12 +13,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `derived_drop::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `derived_drop::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
@@ -53,12 +53,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `significant_drop::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `significant_drop::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
@@ -93,12 +93,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `insignificant_dtor::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
diff --git a/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs
index 0f94016f11b..43e42fa85f7 100644
--- a/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs
+++ b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs
@@ -1,10 +1,10 @@
 //@ build-pass
 //@ edition:2018
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let _ = static |x: u8| match x {
+    let _ = #[coroutine] static |x: u8| match x {
         y if { yield } == y + 1 => (),
         _ => (),
     };
diff --git a/tests/ui/coroutine/drop-yield-twice.rs b/tests/ui/coroutine/drop-yield-twice.rs
index 015343a2776..7ac1345b2ff 100644
--- a/tests/ui/coroutine/drop-yield-twice.rs
+++ b/tests/ui/coroutine/drop-yield-twice.rs
@@ -1,10 +1,10 @@
-#![feature(negative_impls, coroutines)]
+#![feature(negative_impls, coroutines, stmt_expr_attributes)]
 
 struct Foo(i32);
 impl !Send for Foo {}
 
 fn main() {
-    assert_send(|| { //~ ERROR coroutine cannot be sent between threads safely
+    assert_send(#[coroutine] || { //~ ERROR coroutine cannot be sent between threads safely
         let guard = Foo(42);
         yield;
         drop(guard);
diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr
index c6a9e20b8b5..362c6e943ad 100644
--- a/tests/ui/coroutine/drop-yield-twice.stderr
+++ b/tests/ui/coroutine/drop-yield-twice.stderr
@@ -1,7 +1,7 @@
 error: coroutine cannot be sent between threads safely
   --> $DIR/drop-yield-twice.rs:7:5
    |
-LL | /     assert_send(|| {
+LL | /     assert_send(#[coroutine] || {
 LL | |         let guard = Foo(42);
 LL | |         yield;
 LL | |         drop(guard);
@@ -9,7 +9,7 @@ LL | |         yield;
 LL | |     })
    | |______^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}: Send`
+   = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-yield-twice.rs:9:9
    |
diff --git a/tests/ui/coroutine/dropck-resume.rs b/tests/ui/coroutine/dropck-resume.rs
index 07ca4d37aba..df014400f00 100644
--- a/tests/ui/coroutine/dropck-resume.rs
+++ b/tests/ui/coroutine/dropck-resume.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
@@ -16,7 +16,8 @@ fn drop_using_coroutine() -> i32 {
     let z = &mut y;
     let r;
     {
-        let mut g = move |r| {
+        let mut g = #[coroutine]
+        move |r| {
             let _s = SetToNone(r);
             yield;
         };
diff --git a/tests/ui/coroutine/dropck-resume.stderr b/tests/ui/coroutine/dropck-resume.stderr
index aa6e423c760..e9243ffa41e 100644
--- a/tests/ui/coroutine/dropck-resume.stderr
+++ b/tests/ui/coroutine/dropck-resume.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
-  --> $DIR/dropck-resume.rs:25:13
+  --> $DIR/dropck-resume.rs:26:13
    |
 LL |     let z = &mut y;
    |             ------ mutable borrow occurs here
diff --git a/tests/ui/coroutine/dropck.rs b/tests/ui/coroutine/dropck.rs
index 450361c8dd0..9331c1fa1d5 100644
--- a/tests/ui/coroutine/dropck.rs
+++ b/tests/ui/coroutine/dropck.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::cell::RefCell;
 use std::ops::Coroutine;
@@ -10,7 +10,8 @@ fn main() {
     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
     //~^ ERROR `*cell` does not live long enough [E0597]
     // the upvar is the non-dropck `&mut Option<Ref<'a, i32>>`.
-    gen = || {
+    gen = #[coroutine]
+    || {
         // but the coroutine can use it to drop a `Ref<'a, i32>`.
         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
         yield;
diff --git a/tests/ui/coroutine/dropck.stderr b/tests/ui/coroutine/dropck.stderr
index 241d6dfe0a1..78fdeec972f 100644
--- a/tests/ui/coroutine/dropck.stderr
+++ b/tests/ui/coroutine/dropck.stderr
@@ -16,10 +16,13 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are defined
 
 error[E0597]: `ref_` does not live long enough
-  --> $DIR/dropck.rs:15:18
+  --> $DIR/dropck.rs:16:18
    |
-LL |     gen = || {
-   |           -- value captured here by coroutine
+LL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+   |         ---- binding `ref_` declared here
+...
+LL |     || {
+   |     -- value captured here by coroutine
 LL |         // but the coroutine can use it to drop a `Ref<'a, i32>`.
 LL |         let _d = ref_.take();
    |                  ^^^^ borrowed value does not live long enough
diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr
index 2b9eb4a820b..322259cf2f8 100644
--- a/tests/ui/coroutine/gen_block.e2024.stderr
+++ b/tests/ui/coroutine/gen_block.e2024.stderr
@@ -1,5 +1,25 @@
+error[E0658]: the `#[coroutines]` attribute is an experimental feature
+  --> $DIR/gen_block.rs:20:13
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ^^^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature
+  --> $DIR/gen_block.rs:24:13
+   |
+LL |     let _ = #[coroutine] || {};
+   |             ^^^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0658]: yield syntax is experimental
-  --> $DIR/gen_block.rs:15:16
+  --> $DIR/gen_block.rs:16:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
@@ -8,13 +28,34 @@ LL |     let _ = || yield true;
    = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/gen_block.rs:16:16
+   |
+LL |     let _ = || yield true;
+   |                ^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ++++++++++++
+
+error[E0658]: yield syntax is experimental
+  --> $DIR/gen_block.rs:20:29
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |                             ^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0282]: type annotations needed
-  --> $DIR/gen_block.rs:6:13
+  --> $DIR/gen_block.rs:7:13
    |
 LL |     let x = gen {};
    |             ^^^^^^ cannot infer type
 
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0282, E0658.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr
index 78a8c5e798a..64fa2be003d 100644
--- a/tests/ui/coroutine/gen_block.none.stderr
+++ b/tests/ui/coroutine/gen_block.none.stderr
@@ -1,5 +1,5 @@
 error: expected identifier, found reserved keyword `yield`
-  --> $DIR/gen_block.rs:9:19
+  --> $DIR/gen_block.rs:10:19
    |
 LL |     let y = gen { yield 42 };
    |             ---   ^^^^^ expected identifier, found reserved keyword
@@ -7,25 +7,25 @@ LL |     let y = gen { yield 42 };
    |             while parsing this struct
 
 error[E0422]: cannot find struct, variant or union type `gen` in this scope
-  --> $DIR/gen_block.rs:6:13
+  --> $DIR/gen_block.rs:7:13
    |
 LL |     let x = gen {};
    |             ^^^ not found in this scope
 
 error[E0422]: cannot find struct, variant or union type `gen` in this scope
-  --> $DIR/gen_block.rs:9:13
+  --> $DIR/gen_block.rs:10:13
    |
 LL |     let y = gen { yield 42 };
    |             ^^^ not found in this scope
 
 error[E0422]: cannot find struct, variant or union type `gen` in this scope
-  --> $DIR/gen_block.rs:12:5
+  --> $DIR/gen_block.rs:13:5
    |
 LL |     gen {};
    |     ^^^ not found in this scope
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/gen_block.rs:15:16
+  --> $DIR/gen_block.rs:16:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
@@ -35,17 +35,69 @@ LL |     let _ = || yield true;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/gen_block.rs:15:16
+  --> $DIR/gen_block.rs:20:29
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |                             ^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature
+  --> $DIR/gen_block.rs:20:13
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ^^^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature
+  --> $DIR/gen_block.rs:24:13
+   |
+LL |     let _ = #[coroutine] || {};
+   |             ^^^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` 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[E0658]: yield syntax is experimental
+  --> $DIR/gen_block.rs:16:16
+   |
+LL |     let _ = || yield true;
+   |                ^^^^^^^^^^
+   |
+   = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
+   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/gen_block.rs:16:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
    |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ++++++++++++
+
+error[E0658]: yield syntax is experimental
+  --> $DIR/gen_block.rs:20:29
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |                             ^^^^^^^^^^
+   |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
    = help: add `#![feature(coroutines)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 6 previous errors
+error: aborting due to 11 previous errors
 
 Some errors have detailed explanations: E0422, E0658.
 For more information about an error, try `rustc --explain E0422`.
diff --git a/tests/ui/coroutine/gen_block.rs b/tests/ui/coroutine/gen_block.rs
index f6a775aa661..7e87a572b90 100644
--- a/tests/ui/coroutine/gen_block.rs
+++ b/tests/ui/coroutine/gen_block.rs
@@ -1,6 +1,7 @@
 //@ revisions: e2024 none
 //@[e2024] compile-flags: --edition 2024 -Zunstable-options
 #![cfg_attr(e2024, feature(gen_blocks))]
+#![feature(stmt_expr_attributes)]
 
 fn main() {
     let x = gen {};
@@ -14,4 +15,12 @@ fn main() {
 
     let _ = || yield true; //[none]~ ERROR yield syntax is experimental
     //~^ ERROR yield syntax is experimental
+    //~^^ ERROR `yield` can only be used in
+
+    let _ = #[coroutine] || yield true; //[none]~ ERROR yield syntax is experimental
+    //~^ ERROR `#[coroutines]` attribute is an experimental feature
+    //~^^ ERROR yield syntax is experimental
+
+    let _ = #[coroutine] || {};
+    //~^ ERROR `#[coroutines]` attribute is an experimental feature
 }
diff --git a/tests/ui/coroutine/issue-102645.rs b/tests/ui/coroutine/issue-102645.rs
index a0263510e13..ccf82c3606a 100644
--- a/tests/ui/coroutine/issue-102645.rs
+++ b/tests/ui/coroutine/issue-102645.rs
@@ -1,11 +1,12 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
     let mut a = 5;
-    let mut b = || {
+    let mut b = #[coroutine]
+    || {
         let d = 6;
         yield;
         _zzz(); // #break
diff --git a/tests/ui/coroutine/issue-102645.stderr b/tests/ui/coroutine/issue-102645.stderr
index 7a3b7f2b04c..ab5e4a8459f 100644
--- a/tests/ui/coroutine/issue-102645.stderr
+++ b/tests/ui/coroutine/issue-102645.stderr
@@ -1,5 +1,5 @@
 error[E0061]: this method takes 1 argument but 0 arguments were supplied
-  --> $DIR/issue-102645.rs:14:22
+  --> $DIR/issue-102645.rs:15:22
    |
 LL |     Pin::new(&mut b).resume();
    |                      ^^^^^^-- an argument of type `()` is missing
diff --git a/tests/ui/coroutine/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs
index 7801f1bcea0..4e40bc127d7 100644
--- a/tests/ui/coroutine/issue-105084.rs
+++ b/tests/ui/coroutine/issue-105084.rs
@@ -11,7 +11,8 @@ fn copy<T: Copy>(x: T) -> T {
 }
 
 fn main() {
-    let mut g = || {
+    let mut g = #[coroutine]
+    || {
         // This is desuraged as 4 stages:
         // - allocate a `*mut u8` with `exchange_malloc`;
         // - create a Box that is ignored for trait computations;
diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr
index c8a6522dbd9..6b1701f0c2a 100644
--- a/tests/ui/coroutine/issue-105084.stderr
+++ b/tests/ui/coroutine/issue-105084.stderr
@@ -1,8 +1,8 @@
 error[E0382]: borrow of moved value: `g`
-  --> $DIR/issue-105084.rs:37:14
+  --> $DIR/issue-105084.rs:38:14
    |
-LL |     let mut g = || {
-   |         ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, which does not implement the `Copy` trait
+LL |     let mut g = #[coroutine]
+   |         ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, which does not implement the `Copy` trait
 ...
 LL |     let mut h = copy(g);
    |                      - value moved here
@@ -22,17 +22,17 @@ help: consider cloning the value if the performance cost is acceptable
 LL |     let mut h = copy(g.clone());
    |                       ++++++++
 
-error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`
-  --> $DIR/issue-105084.rs:31:17
+error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`
+  --> $DIR/issue-105084.rs:32:17
    |
-LL |     let mut g = || {
-   |                 -- within this `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`
+LL |     || {
+   |     -- within this `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`
 ...
 LL |     let mut h = copy(g);
-   |                 ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}: Copy`
+   |                 ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/issue-105084.rs:21:22
+  --> $DIR/issue-105084.rs:22:22
    |
 LL |         Box::new((5, yield));
    |         -------------^^^^^--
diff --git a/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs
index 3d372ac9110..300c8fe6d46 100644
--- a/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs
+++ b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs
@@ -1,11 +1,12 @@
 //@ edition:2021
 //@ check-pass
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
     let x = &mut ();
     || {
-        let _c = || yield *&mut *x;
+        let _c = #[coroutine]
+        || yield *&mut *x;
         || _ = &mut *x;
     };
 }
diff --git a/tests/ui/coroutine/issue-113279.rs b/tests/ui/coroutine/issue-113279.rs
index f251c924c13..98617af105c 100644
--- a/tests/ui/coroutine/issue-113279.rs
+++ b/tests/ui/coroutine/issue-113279.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 // `foo` attempts to dereference `""`, which results in an error being reported. Later, the
 // coroutine transform for `foo` then produces a union which contains a `str` type - unions should
@@ -9,7 +9,8 @@
 // makes sure that doesn't happen again.
 
 fn foo() {
-    let _y = static || {
+    let _y = #[coroutine]
+    static || {
         let x = &mut 0;
         *{
             yield;
diff --git a/tests/ui/coroutine/issue-113279.stderr b/tests/ui/coroutine/issue-113279.stderr
index cc9b64ef9ac..a80fe670188 100644
--- a/tests/ui/coroutine/issue-113279.stderr
+++ b/tests/ui/coroutine/issue-113279.stderr
@@ -1,11 +1,11 @@
 error[E0161]: cannot move a value of type `str`
-  --> $DIR/issue-113279.rs:17:20
+  --> $DIR/issue-113279.rs:18:20
    |
 LL |         } += match { *"" }.len() {
    |                    ^^^^^^^ the size of `str` cannot be statically determined
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-113279.rs:17:22
+  --> $DIR/issue-113279.rs:18:22
    |
 LL |         } += match { *"" }.len() {
    |                      ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
diff --git a/tests/ui/coroutine/issue-44197.rs b/tests/ui/coroutine/issue-44197.rs
index e18bcc2c996..0240f7a7eaa 100644
--- a/tests/ui/coroutine/issue-44197.rs
+++ b/tests/ui/coroutine/issue-44197.rs
@@ -10,7 +10,7 @@ fn foo(_: &str) -> String {
 }
 
 fn bar(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> {
-    move || {
+    #[coroutine] move || {
         yield foo(&baz);
     }
 }
@@ -20,7 +20,7 @@ fn foo2(_: &str) -> Result<String, ()> {
 }
 
 fn bar2(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> {
-    move || {
+    #[coroutine] move || {
         if let Ok(quux) = foo2(&baz) {
             yield quux;
         }
diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs
index dab9c81bc8f..d90886b6b1d 100644
--- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs
+++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs
@@ -1,7 +1,8 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let _ = || {
+    let _ = #[coroutine]
+    || {
         *(1 as *mut u32) = 42;
         //~^ ERROR dereference of raw pointer is unsafe
         yield;
diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr
index 19949b42939..f99c295bb9e 100644
--- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr
+++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr
@@ -1,5 +1,5 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-45729-unsafe-in-coroutine.rs:5:9
+  --> $DIR/issue-45729-unsafe-in-coroutine.rs:6:9
    |
 LL |         *(1 as *mut u32) = 42;
    |         ^^^^^^^^^^^^^^^^ dereference of raw pointer
diff --git a/tests/ui/coroutine/issue-48048.rs b/tests/ui/coroutine/issue-48048.rs
index b61b7c77072..75664f20198 100644
--- a/tests/ui/coroutine/issue-48048.rs
+++ b/tests/ui/coroutine/issue-48048.rs
@@ -3,7 +3,7 @@
 fn main() {
     let x = (|_| {},);
 
-    || {
+    #[coroutine] || {
         let x = x;
 
         x.0({ //~ ERROR borrow may still be in use when coroutine yields
diff --git a/tests/ui/coroutine/issue-52304.rs b/tests/ui/coroutine/issue-52304.rs
index 01ed181ab1d..552bc0028ee 100644
--- a/tests/ui/coroutine/issue-52304.rs
+++ b/tests/ui/coroutine/issue-52304.rs
@@ -5,6 +5,7 @@
 use std::ops::Coroutine;
 
 pub fn example() -> impl Coroutine {
+    #[coroutine]
     || yield &1
 }
 
diff --git a/tests/ui/coroutine/issue-52398.rs b/tests/ui/coroutine/issue-52398.rs
index 826ce6b9d9b..f8b2faf4eab 100644
--- a/tests/ui/coroutine/issue-52398.rs
+++ b/tests/ui/coroutine/issue-52398.rs
@@ -14,14 +14,14 @@ impl A {
 fn main() {
     // Test that the MIR local with type &A created for the auto-borrow adjustment
     // is caught by typeck
-    move || { //~ WARN unused coroutine that must be used
+    #[coroutine] move || { //~ WARN unused coroutine that must be used
         A.test(yield);
     };
 
     // Test that the std::cell::Ref temporary returned from the `borrow` call
     // is caught by typeck
     let y = RefCell::new(true);
-    static move || { //~ WARN unused coroutine that must be used
+    #[coroutine] static move || { //~ WARN unused coroutine that must be used
         yield *y.borrow();
         return "Done";
     };
diff --git a/tests/ui/coroutine/issue-52398.stderr b/tests/ui/coroutine/issue-52398.stderr
index 18d816da4c6..806690cc332 100644
--- a/tests/ui/coroutine/issue-52398.stderr
+++ b/tests/ui/coroutine/issue-52398.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/issue-52398.rs:17:5
+  --> $DIR/issue-52398.rs:17:18
    |
-LL | /     move || {
+LL |       #[coroutine] move || {
+   |  __________________^
 LL | |         A.test(yield);
 LL | |     };
    | |_____^
@@ -10,9 +11,10 @@ LL | |     };
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: unused coroutine that must be used
-  --> $DIR/issue-52398.rs:24:5
+  --> $DIR/issue-52398.rs:24:18
    |
-LL | /     static move || {
+LL |       #[coroutine] static move || {
+   |  __________________^
 LL | |         yield *y.borrow();
 LL | |         return "Done";
 LL | |     };
diff --git a/tests/ui/coroutine/issue-53548.rs b/tests/ui/coroutine/issue-53548.rs
index 6d55994137f..3b8dff2be28 100644
--- a/tests/ui/coroutine/issue-53548.rs
+++ b/tests/ui/coroutine/issue-53548.rs
@@ -17,7 +17,7 @@
 //
 //@ check-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -29,7 +29,7 @@ struct Store<C> {
 }
 
 fn main() {
-    Box::new(static move || {
+    Box::new(#[coroutine] static move || {
         let store = Store::<Box<dyn Trait>> {
             inner: Default::default(),
         };
diff --git a/tests/ui/coroutine/issue-57017.rs b/tests/ui/coroutine/issue-57017.rs
index b83d916932a..19cd80ab4a6 100644
--- a/tests/ui/coroutine/issue-57017.rs
+++ b/tests/ui/coroutine/issue-57017.rs
@@ -1,5 +1,5 @@
 //@ build-pass
-#![feature(coroutines, negative_impls)]
+#![feature(coroutines, negative_impls, stmt_expr_attributes)]
 #![allow(dropping_references, dropping_copy_types)]
 
 macro_rules! type_combinations {
@@ -21,7 +21,7 @@ macro_rules! type_combinations {
 
         // This is the same bug as issue 57017, but using yield instead of await
         {
-            let g = move || match drop(&$name::unsync::Client::default()) {
+            let g = #[coroutine] move || match drop(&$name::unsync::Client::default()) {
                 _status => yield,
             };
             assert_send(g);
@@ -30,7 +30,7 @@ macro_rules! type_combinations {
         // This tests that `Client` is properly considered to be dropped after moving it into the
         // function.
         {
-            let g = move || match drop($name::unsend::Client::default()) {
+            let g = #[coroutine] move || match drop($name::unsend::Client::default()) {
                 _status => yield,
             };
             assert_send(g);
diff --git a/tests/ui/coroutine/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs
index 51b0c8e1de9..2df60550e03 100644
--- a/tests/ui/coroutine/issue-57084.rs
+++ b/tests/ui/coroutine/issue-57084.rs
@@ -8,7 +8,7 @@ use std::ops::Coroutine;
 fn with<F>(f: F) -> impl Coroutine<Yield=(), Return=()>
 where F: Fn() -> ()
 {
-    move || {
+    #[coroutine] move || {
         loop {
             match f() {
                 _ => yield,
@@ -19,7 +19,7 @@ where F: Fn() -> ()
 
 fn main() {
     let data = &vec![1];
-    || { //~ WARN unused coroutine that must be used
+    #[coroutine] || { //~ WARN unused coroutine that must be used
         let _to_pin = with(move || println!("{:p}", data));
         loop {
             yield
diff --git a/tests/ui/coroutine/issue-57084.stderr b/tests/ui/coroutine/issue-57084.stderr
index 9f5b79a6ae8..81bd27da919 100644
--- a/tests/ui/coroutine/issue-57084.stderr
+++ b/tests/ui/coroutine/issue-57084.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/issue-57084.rs:22:5
+  --> $DIR/issue-57084.rs:22:18
    |
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         let _to_pin = with(move || println!("{:p}", data));
 LL | |         loop {
 LL | |             yield
diff --git a/tests/ui/coroutine/issue-57478.rs b/tests/ui/coroutine/issue-57478.rs
index 5e479aaa9c1..494c2ee9843 100644
--- a/tests/ui/coroutine/issue-57478.rs
+++ b/tests/ui/coroutine/issue-57478.rs
@@ -1,16 +1,19 @@
 //@ check-pass
 
-#![feature(negative_impls, coroutines)]
+#![feature(negative_impls, coroutines, stmt_expr_attributes)]
 
 struct Foo;
 impl !Send for Foo {}
 
 fn main() {
-    assert_send(|| {
-        let guard = Foo;
-        drop(guard);
-        yield;
-    })
+    assert_send(
+        #[coroutine]
+        || {
+            let guard = Foo;
+            drop(guard);
+            yield;
+        },
+    )
 }
 
 fn assert_send<T: Send>(_: T) {}
diff --git a/tests/ui/coroutine/issue-58888.rs b/tests/ui/coroutine/issue-58888.rs
index ce45f22dd6e..6266f97ce8c 100644
--- a/tests/ui/coroutine/issue-58888.rs
+++ b/tests/ui/coroutine/issue-58888.rs
@@ -13,7 +13,7 @@ impl Database {
     }
 
     fn check_connection(&self) -> impl Coroutine<Yield = (), Return = ()> + '_ {
-        move || {
+        #[coroutine] move || {
             let iter = self.get_connection();
             for i in iter {
                 yield i
diff --git a/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs
index 6280b777201..6f513c250a5 100644
--- a/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs
+++ b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs
@@ -4,7 +4,7 @@
 //@ check-pass
 //@ edition:2018
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 
@@ -14,12 +14,14 @@ async fn drop_and_await() {
 }
 
 fn drop_and_yield() {
-    let x = || {
+    let x = #[coroutine]
+    || {
         String::new();
         yield;
     };
     Box::pin(x).as_mut().resume(());
-    let y = static || {
+    let y = #[coroutine]
+    static || {
         String::new();
         yield;
     };
diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.rs b/tests/ui/coroutine/issue-64620-yield-array-element.rs
index a9307d306a6..0d898d014e8 100644
--- a/tests/ui/coroutine/issue-64620-yield-array-element.rs
+++ b/tests/ui/coroutine/issue-64620-yield-array-element.rs
@@ -4,6 +4,7 @@
 
 pub fn crash(arr: [usize; 1]) {
     yield arr[0]; //~ ERROR: yield expression outside of coroutine literal
+    //~^ ERROR: `yield` can only be used in
 }
 
 fn main() {}
diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.stderr b/tests/ui/coroutine/issue-64620-yield-array-element.stderr
index 347532fb719..1c030c5248e 100644
--- a/tests/ui/coroutine/issue-64620-yield-array-element.stderr
+++ b/tests/ui/coroutine/issue-64620-yield-array-element.stderr
@@ -1,9 +1,20 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/issue-64620-yield-array-element.rs:6:5
+   |
+LL |     yield arr[0];
+   |     ^^^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] pub fn crash(arr: [usize; 1]) {
+   | ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/issue-64620-yield-array-element.rs:6:5
    |
 LL |     yield arr[0];
    |     ^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0627`.
diff --git a/tests/ui/coroutine/issue-68112.rs b/tests/ui/coroutine/issue-68112.rs
index ccec2acc976..b296772c905 100644
--- a/tests/ui/coroutine/issue-68112.rs
+++ b/tests/ui/coroutine/issue-68112.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     cell::RefCell,
@@ -30,7 +30,7 @@ fn make_non_send_coroutine() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
 }
 
 fn test1() {
-    let send_gen = || {
+    let send_gen = #[coroutine] || {
         let _non_send_gen = make_non_send_coroutine();
         //~^ NOTE not `Send`
         yield;
@@ -46,7 +46,7 @@ fn test1() {
 pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
 //~^ NOTE appears within the type
 //~| NOTE expansion of desugaring
-    || { //~ NOTE used within this coroutine
+    #[coroutine] || { //~ NOTE used within this coroutine
         yield;
         t
     }
@@ -57,7 +57,7 @@ fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> { //
 }
 
 fn test2() {
-    let send_gen = || { //~ NOTE used within this coroutine
+    let send_gen = #[coroutine] || { //~ NOTE used within this coroutine
         let _non_send_gen = make_non_send_coroutine2();
         yield;
     };
diff --git a/tests/ui/coroutine/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr
index 443195d36a3..bcfcb5ec6e6 100644
--- a/tests/ui/coroutine/issue-68112.stderr
+++ b/tests/ui/coroutine/issue-68112.stderr
@@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:33:20: 33:22}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:33:33: 33:35}: Send`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/issue-68112.rs:36:9
@@ -26,14 +26,14 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:60:20: 60:22}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:60:33: 60:35}: 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 coroutine
-  --> $DIR/issue-68112.rs:49:5
+  --> $DIR/issue-68112.rs:49:18
    |
-LL |     || {
-   |     ^^
+LL |     #[coroutine] || {
+   |                  ^^
 note: required because it appears within the type `impl Coroutine<Return = Arc<RefCell<i32>>>`
   --> $DIR/issue-68112.rs:46:30
    |
@@ -45,10 +45,10 @@ note: required because it appears within the type `impl Coroutine<Return = Arc<R
 LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it's used within this coroutine
-  --> $DIR/issue-68112.rs:60:20
+  --> $DIR/issue-68112.rs:60:33
    |
-LL |     let send_gen = || {
-   |                    ^^
+LL |     let send_gen = #[coroutine] || {
+   |                                 ^^
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:22:25
    |
diff --git a/tests/ui/coroutine/issue-69017.rs b/tests/ui/coroutine/issue-69017.rs
index 09bbf63a986..bf69e1dfdb1 100644
--- a/tests/ui/coroutine/issue-69017.rs
+++ b/tests/ui/coroutine/issue-69017.rs
@@ -10,6 +10,7 @@
 use std::ops::Coroutine;
 
 fn gen() -> impl Coroutine<usize> {
+    #[coroutine]
     |_: usize| {
         println!("-> {}", yield);
     }
diff --git a/tests/ui/coroutine/issue-69039.rs b/tests/ui/coroutine/issue-69039.rs
index fd12414c3d8..13cb50e5828 100644
--- a/tests/ui/coroutine/issue-69039.rs
+++ b/tests/ui/coroutine/issue-69039.rs
@@ -9,6 +9,7 @@ fn mkstr(my_name: String, my_mood: String) -> String {
 }
 
 fn my_scenario() -> impl Coroutine<String, Yield = &'static str, Return = String> {
+    #[coroutine]
     |_arg: String| {
         let my_name = yield "What is your name?";
         let my_mood = yield "How are you feeling?";
diff --git a/tests/ui/coroutine/issue-87142.rs b/tests/ui/coroutine/issue-87142.rs
index f5c3805842c..6c22ba3dd75 100644
--- a/tests/ui/coroutine/issue-87142.rs
+++ b/tests/ui/coroutine/issue-87142.rs
@@ -22,6 +22,7 @@ pub struct Context<G: 'static + CoroutineProviderAlt> {
 impl CoroutineProviderAlt for () {
     type Coro = impl Coroutine<(), Return = (), Yield = ()>;
     fn start(ctx: Context<Self>) -> Self::Coro {
+        #[coroutine]
         move || {
             match ctx {
                 _ => (),
diff --git a/tests/ui/coroutine/issue-88653.rs b/tests/ui/coroutine/issue-88653.rs
index ec4c2054758..3afd12a2093 100644
--- a/tests/ui/coroutine/issue-88653.rs
+++ b/tests/ui/coroutine/issue-88653.rs
@@ -11,6 +11,7 @@ fn foo(bar: bool) -> impl Coroutine<(bool,)> {
     //~| NOTE: expected coroutine signature `fn((bool,)) -> _`
     //~| NOTE: in this expansion of desugaring of `impl Trait`
     //~| NOTE: in this expansion of desugaring of `impl Trait`
+    #[coroutine]
     |bar| {
         //~^ NOTE: found signature defined here
         if bar {
diff --git a/tests/ui/coroutine/issue-91477.rs b/tests/ui/coroutine/issue-91477.rs
index c98546f7971..c215fd7948f 100644
--- a/tests/ui/coroutine/issue-91477.rs
+++ b/tests/ui/coroutine/issue-91477.rs
@@ -2,6 +2,7 @@
 
 fn foo() -> impl Sized {
     yield 1; //~ ERROR E0627
+    //~^ ERROR: `yield` can only be used in
 }
 
 fn main() {}
diff --git a/tests/ui/coroutine/issue-91477.stderr b/tests/ui/coroutine/issue-91477.stderr
index ca8e43d8a26..5e2151c4c35 100644
--- a/tests/ui/coroutine/issue-91477.stderr
+++ b/tests/ui/coroutine/issue-91477.stderr
@@ -1,9 +1,20 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/issue-91477.rs:4:5
+   |
+LL |     yield 1;
+   |     ^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] fn foo() -> impl Sized {
+   | ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/issue-91477.rs:4:5
    |
 LL |     yield 1;
    |     ^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0627`.
diff --git a/tests/ui/coroutine/iterator-count.rs b/tests/ui/coroutine/iterator-count.rs
index bb202ab2d33..1ca8ceaed2a 100644
--- a/tests/ui/coroutine/iterator-count.rs
+++ b/tests/ui/coroutine/iterator-count.rs
@@ -21,6 +21,7 @@ impl<T: Coroutine<(), Return = ()> + Unpin> Iterator for W<T> {
 }
 
 fn test() -> impl Coroutine<(), Return = (), Yield = u8> + Unpin {
+    #[coroutine]
     || {
         for i in 1..6 {
             yield i
@@ -32,6 +33,7 @@ fn main() {
     let end = 11;
 
     let closure_test = |start| {
+        #[coroutine]
         move || {
             for i in start..end {
                 yield i
diff --git a/tests/ui/coroutine/live-upvar-across-yield.rs b/tests/ui/coroutine/live-upvar-across-yield.rs
index 86c4716c951..d13d480dcdc 100644
--- a/tests/ui/coroutine/live-upvar-across-yield.rs
+++ b/tests/ui/coroutine/live-upvar-across-yield.rs
@@ -1,13 +1,13 @@
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
     let b = |_| 3;
-    let mut a = || {
+    let mut a = #[coroutine] || {
         b(yield);
     };
     Pin::new(&mut a).resume(());
diff --git a/tests/ui/coroutine/match-bindings.rs b/tests/ui/coroutine/match-bindings.rs
index 9ea1deaab36..2a0cd9af9f3 100644
--- a/tests/ui/coroutine/match-bindings.rs
+++ b/tests/ui/coroutine/match-bindings.rs
@@ -9,7 +9,7 @@ enum Enum {
 }
 
 fn main() {
-    || { //~ WARN unused coroutine that must be used
+    #[coroutine] || { //~ WARN unused coroutine that must be used
         loop {
             if let true = true {
                 match Enum::A(String::new()) {
diff --git a/tests/ui/coroutine/match-bindings.stderr b/tests/ui/coroutine/match-bindings.stderr
index a7aa6eadb95..5525bfed116 100644
--- a/tests/ui/coroutine/match-bindings.stderr
+++ b/tests/ui/coroutine/match-bindings.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/match-bindings.rs:12:5
+  --> $DIR/match-bindings.rs:12:18
    |
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         loop {
 LL | |             if let true = true {
 LL | |                 match Enum::A(String::new()) {
diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed b/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed
new file mode 100644
index 00000000000..128f09a1184
--- /dev/null
+++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed
@@ -0,0 +1,8 @@
+//@ run-rustfix
+
+#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[coroutine] || yield;
+    //~^ ERROR `yield` can only be used
+}
diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs b/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs
new file mode 100644
index 00000000000..dc952591496
--- /dev/null
+++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs
@@ -0,0 +1,8 @@
+//@ run-rustfix
+
+#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
+
+fn main() {
+    let _ = || yield;
+    //~^ ERROR `yield` can only be used
+}
diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr b/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr
new file mode 100644
index 00000000000..8d92471a361
--- /dev/null
+++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr
@@ -0,0 +1,13 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/missing_coroutine_attr_suggestion.rs:6:16
+   |
+LL |     let _ = || yield;
+   |                ^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL |     let _ = #[coroutine] || yield;
+   |             ++++++++++++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/coroutine/nested_coroutine.rs b/tests/ui/coroutine/nested_coroutine.rs
index 7ff97abf4bb..2c12ab2adad 100644
--- a/tests/ui/coroutine/nested_coroutine.rs
+++ b/tests/ui/coroutine/nested_coroutine.rs
@@ -1,13 +1,15 @@
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let _coroutine = || {
-        let mut sub_coroutine = || {
+    let _coroutine = #[coroutine]
+    || {
+        let mut sub_coroutine = #[coroutine]
+        || {
             yield 2;
         };
 
diff --git a/tests/ui/coroutine/niche-in-coroutine.rs b/tests/ui/coroutine/niche-in-coroutine.rs
index 45b920ab927..117ee9e6f03 100644
--- a/tests/ui/coroutine/niche-in-coroutine.rs
+++ b/tests/ui/coroutine/niche-in-coroutine.rs
@@ -2,7 +2,7 @@
 
 //@ run-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 use std::mem::size_of_val;
 
@@ -10,7 +10,7 @@ fn take<T>(_: T) {}
 
 fn main() {
     let x = false;
-    let gen1 = || {
+    let gen1 = #[coroutine] || {
         yield;
         take(x);
     };
diff --git a/tests/ui/coroutine/non-static-is-unpin.rs b/tests/ui/coroutine/non-static-is-unpin.rs
index 616a78d5fe2..b28bf197714 100644
--- a/tests/ui/coroutine/non-static-is-unpin.rs
+++ b/tests/ui/coroutine/non-static-is-unpin.rs
@@ -3,7 +3,7 @@
 //@[next] compile-flags: -Znext-solver
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 #![allow(dropping_copy_types)]
 
 use std::marker::PhantomPinned;
@@ -14,7 +14,7 @@ fn assert_unpin<G: Unpin>(_: G) {
 fn main() {
     // Even though this coroutine holds a `PhantomPinned` in its environment, it
     // remains `Unpin`.
-    assert_unpin(|| {
+    assert_unpin(#[coroutine] || {
         let pinned = PhantomPinned;
         yield;
         drop(pinned);
diff --git a/tests/ui/coroutine/not-send-sync.rs b/tests/ui/coroutine/not-send-sync.rs
index dd6182c10de..a46dcd14e88 100644
--- a/tests/ui/coroutine/not-send-sync.rs
+++ b/tests/ui/coroutine/not-send-sync.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(negative_impls)]
 
 struct NotSend;
@@ -11,14 +11,14 @@ fn main() {
     fn assert_sync<T: Sync>(_: T) {}
     fn assert_send<T: Send>(_: T) {}
 
-    assert_sync(|| {
+    assert_sync(#[coroutine] || {
         //~^ ERROR: coroutine cannot be shared between threads safely
         let a = NotSync;
         yield;
         drop(a);
     });
 
-    assert_send(|| {
+    assert_send(#[coroutine] || {
         //~^ ERROR: coroutine cannot be sent between threads safely
         let a = NotSend;
         yield;
diff --git a/tests/ui/coroutine/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr
index 9228340c710..0f9cbdec130 100644
--- a/tests/ui/coroutine/not-send-sync.stderr
+++ b/tests/ui/coroutine/not-send-sync.stderr
@@ -1,7 +1,7 @@
 error: coroutine cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:14:5
    |
-LL | /     assert_sync(|| {
+LL | /     assert_sync(#[coroutine] || {
 LL | |
 LL | |         let a = NotSync;
 LL | |         yield;
@@ -9,7 +9,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Sync`
    |
-   = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}: Sync`
+   = help: within `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}: Sync`
 note: coroutine is not `Sync` as this value is used across a yield
   --> $DIR/not-send-sync.rs:17:9
    |
@@ -26,7 +26,7 @@ LL |     fn assert_sync<T: Sync>(_: T) {}
 error: coroutine cannot be sent between threads safely
   --> $DIR/not-send-sync.rs:21:5
    |
-LL | /     assert_send(|| {
+LL | /     assert_send(#[coroutine] || {
 LL | |
 LL | |         let a = NotSend;
 LL | |         yield;
@@ -34,7 +34,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}: Send`
+   = help: within `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/not-send-sync.rs:24:9
    |
diff --git a/tests/ui/coroutine/overlap-locals.rs b/tests/ui/coroutine/overlap-locals.rs
index eea8595ed06..9cfa6e2a76d 100644
--- a/tests/ui/coroutine/overlap-locals.rs
+++ b/tests/ui/coroutine/overlap-locals.rs
@@ -1,9 +1,10 @@
 //@ run-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let a = || {
+    let a = #[coroutine]
+    || {
         {
             let w: i32 = 4;
             yield;
diff --git a/tests/ui/coroutine/panic-drops-resume.rs b/tests/ui/coroutine/panic-drops-resume.rs
index 6d026e6edc8..b23666b7885 100644
--- a/tests/ui/coroutine/panic-drops-resume.rs
+++ b/tests/ui/coroutine/panic-drops-resume.rs
@@ -3,7 +3,7 @@
 //@ run-pass
 //@ needs-unwind
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -21,7 +21,7 @@ impl Drop for Dropper {
 }
 
 fn main() {
-    let mut gen = |_arg| {
+    let mut gen = #[coroutine] |_arg| {
         if true {
             panic!();
         }
diff --git a/tests/ui/coroutine/panic-drops.rs b/tests/ui/coroutine/panic-drops.rs
index c99abdc7246..8c2cf560f2a 100644
--- a/tests/ui/coroutine/panic-drops.rs
+++ b/tests/ui/coroutine/panic-drops.rs
@@ -1,8 +1,7 @@
 //@ run-pass
 //@ needs-unwind
 
-
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::panic;
@@ -25,7 +24,8 @@ fn bool_true() -> bool {
 
 fn main() {
     let b = B;
-    let mut foo = || {
+    let mut foo = #[coroutine]
+    || {
         if bool_true() {
             panic!();
         }
@@ -34,13 +34,12 @@ fn main() {
     };
 
     assert_eq!(A.load(Ordering::SeqCst), 0);
-    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        Pin::new(&mut foo).resume(())
-    }));
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Pin::new(&mut foo).resume(())));
     assert!(res.is_err());
     assert_eq!(A.load(Ordering::SeqCst), 1);
 
-    let mut foo = || {
+    let mut foo = #[coroutine]
+    || {
         if bool_true() {
             panic!();
         }
@@ -49,9 +48,7 @@ fn main() {
     };
 
     assert_eq!(A.load(Ordering::SeqCst), 1);
-    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        Pin::new(&mut foo).resume(())
-    }));
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Pin::new(&mut foo).resume(())));
     assert!(res.is_err());
     assert_eq!(A.load(Ordering::SeqCst), 1);
 }
diff --git a/tests/ui/coroutine/panic-safe.rs b/tests/ui/coroutine/panic-safe.rs
index 89dd09bf520..6b9b4cb33c3 100644
--- a/tests/ui/coroutine/panic-safe.rs
+++ b/tests/ui/coroutine/panic-safe.rs
@@ -2,14 +2,14 @@
 //@ needs-unwind
 
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 use std::panic;
 
 fn main() {
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         if true {
             panic!();
         }
diff --git a/tests/ui/coroutine/parent-expression.rs b/tests/ui/coroutine/parent-expression.rs
index 4d40192c07a..0f4d99c8936 100644
--- a/tests/ui/coroutine/parent-expression.rs
+++ b/tests/ui/coroutine/parent-expression.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, negative_impls, rustc_attrs)]
+#![feature(coroutines, negative_impls, rustc_attrs, stmt_expr_attributes)]
 
 macro_rules! type_combinations {
     (
@@ -14,7 +14,7 @@ macro_rules! type_combinations {
         // Struct update syntax. This fails because the Client used in the update is considered
         // dropped *after* the yield.
         {
-            let g = move || match drop($name::Client { ..$name::Client::default() }) {
+            let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
             //~^ `significant_drop::Client` which is not `Send`
             //~| `insignificant_dtor::Client` which is not `Send`
             //~| `derived_drop::Client` which is not `Send`
@@ -29,7 +29,7 @@ macro_rules! type_combinations {
         // Simple owned value. This works because the Client is considered moved into `drop`,
         // even though the temporary expression doesn't end until after the yield.
         {
-            let g = move || match drop($name::Client::default()) {
+            let g = #[coroutine] move || match drop($name::Client::default()) {
                 _ => yield,
             };
             assert_send(g);
diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr
index 5b3737069e6..2d817f1bfd9 100644
--- a/tests/ui/coroutine/parent-expression.stderr
+++ b/tests/ui/coroutine/parent-expression.stderr
@@ -13,12 +13,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `derived_drop::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `derived_drop::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
@@ -53,12 +53,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `significant_drop::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `significant_drop::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
@@ -93,12 +93,12 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
-LL |               let g = move || match drop($name::Client { ..$name::Client::default() }) {
-   |                                                            ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+LL |               let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) {
+   |                                                                         ------------------------ has type `insignificant_dtor::Client` which is not `Send`
 ...
 LL |                   _ => yield,
    |                        ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
diff --git a/tests/ui/coroutine/partial-drop.rs b/tests/ui/coroutine/partial-drop.rs
index ba13544712f..9efb551c9c1 100644
--- a/tests/ui/coroutine/partial-drop.rs
+++ b/tests/ui/coroutine/partial-drop.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![feature(negative_impls, coroutines)]
+#![feature(negative_impls, coroutines, stmt_expr_attributes)]
 
 struct Foo;
 impl !Send for Foo {}
@@ -10,25 +10,34 @@ struct Bar {
 }
 
 fn main() {
-    assert_send(|| {
-        let guard = Bar { foo: Foo, x: 42 };
-        drop(guard.foo);
-        yield;
-    });
+    assert_send(
+        #[coroutine]
+        || {
+            let guard = Bar { foo: Foo, x: 42 };
+            drop(guard.foo);
+            yield;
+        },
+    );
 
-    assert_send(|| {
-        let mut guard = Bar { foo: Foo, x: 42 };
-        drop(guard);
-        guard = Bar { foo: Foo, x: 23 };
-        yield;
-    });
+    assert_send(
+        #[coroutine]
+        || {
+            let mut guard = Bar { foo: Foo, x: 42 };
+            drop(guard);
+            guard = Bar { foo: Foo, x: 23 };
+            yield;
+        },
+    );
 
-    assert_send(|| {
-        let guard = Bar { foo: Foo, x: 42 };
-        let Bar { foo, x } = guard;
-        drop(foo);
-        yield;
-    });
+    assert_send(
+        #[coroutine]
+        || {
+            let guard = Bar { foo: Foo, x: 42 };
+            let Bar { foo, x } = guard;
+            drop(foo);
+            yield;
+        },
+    );
 }
 
 fn assert_send<T: Send>(_: T) {}
diff --git a/tests/ui/coroutine/partial-initialization-across-yield.rs b/tests/ui/coroutine/partial-initialization-across-yield.rs
index 75ad5a22804..ab6f9c5b1e9 100644
--- a/tests/ui/coroutine/partial-initialization-across-yield.rs
+++ b/tests/ui/coroutine/partial-initialization-across-yield.rs
@@ -1,13 +1,13 @@
 // Test that we don't allow yielding from a coroutine while a local is partially
 // initialized.
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 struct S { x: i32, y: i32 }
 struct T(i32, i32);
 
 fn test_tuple() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut t: (i32, i32);
         t.0 = 42; //~ ERROR E0381
         yield;
@@ -17,7 +17,7 @@ fn test_tuple() {
 }
 
 fn test_tuple_struct() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut t: T;
         t.0 = 42; //~ ERROR E0381
         yield;
@@ -27,7 +27,7 @@ fn test_tuple_struct() {
 }
 
 fn test_struct() {
-    let _ = || {
+    let _ = #[coroutine] || {
         let mut t: S;
         t.x = 42; //~ ERROR E0381
         yield;
diff --git a/tests/ui/coroutine/pattern-borrow.rs b/tests/ui/coroutine/pattern-borrow.rs
index 76084433d47..46547504abc 100644
--- a/tests/ui/coroutine/pattern-borrow.rs
+++ b/tests/ui/coroutine/pattern-borrow.rs
@@ -5,7 +5,7 @@ enum Test { A(i32), B, }
 fn main() { }
 
 fn fun(test: Test) {
-    move || {
+    #[coroutine] move || {
         if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when coroutine yields
             yield ();
             _a.use_ref();
diff --git a/tests/ui/coroutine/pin-box-coroutine.rs b/tests/ui/coroutine/pin-box-coroutine.rs
index 1ee6393d1d8..d030f3ef214 100644
--- a/tests/ui/coroutine/pin-box-coroutine.rs
+++ b/tests/ui/coroutine/pin-box-coroutine.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 
@@ -8,6 +8,6 @@ fn assert_coroutine<G: Coroutine>(_: G) {
 }
 
 fn main() {
-    assert_coroutine(static || yield);
-    assert_coroutine(Box::pin(static || yield));
+    assert_coroutine(#[coroutine] static || yield);
+    assert_coroutine(Box::pin(#[coroutine] static || yield));
 }
diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs
index 21aa3c7aafd..5123bf412b5 100644
--- a/tests/ui/coroutine/polymorphize-args.rs
+++ b/tests/ui/coroutine/polymorphize-args.rs
@@ -1,14 +1,15 @@
 //@ compile-flags: -Zpolymorphize=on
 //@ build-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 use std::thread;
 
 fn main() {
-    let mut foo = || yield;
+    let mut foo = #[coroutine]
+    || yield;
     thread::spawn(move || match Pin::new(&mut foo).resume(()) {
         s => panic!("bad state: {:?}", s),
     })
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.rs b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs
index 73106328618..dc0165c9194 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-1.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs
@@ -2,7 +2,7 @@
 
 // Same as: tests/ui/coroutine/issue-68112.stderr
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     cell::RefCell,
@@ -30,7 +30,7 @@ fn make_non_send_coroutine() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
 }
 
 fn test1() {
-    let send_gen = || {
+    let send_gen = #[coroutine] || {
         let _non_send_gen = make_non_send_coroutine();
         yield;
     };
@@ -39,7 +39,7 @@ fn test1() {
 }
 
 pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
-    || {
+    #[coroutine] || {
         yield;
         t
     }
@@ -49,7 +49,7 @@ fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
 }
 
 fn test2() {
-    let send_gen = || {
+    let send_gen = #[coroutine] || {
         let _non_send_gen = make_non_send_coroutine2();
         yield;
     };
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
index 37db83d57f7..934ab08cf17 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
@@ -29,10 +29,10 @@ LL |     require_send(send_gen);
    = 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 coroutine
-  --> $DIR/coroutine-print-verbose-1.rs:42:5
+  --> $DIR/coroutine-print-verbose-1.rs:42:18
    |
-LL |     || {
-   |     ^^
+LL |     #[coroutine] || {
+   |                  ^^
 note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
   --> $DIR/coroutine-print-verbose-1.rs:41:30
    |
@@ -44,10 +44,10 @@ note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine
 LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it's used within this coroutine
-  --> $DIR/coroutine-print-verbose-1.rs:52:20
+  --> $DIR/coroutine-print-verbose-1.rs:52:33
    |
-LL |     let send_gen = || {
-   |                    ^^
+LL |     let send_gen = #[coroutine] || {
+   |                                 ^^
 note: required by a bound in `require_send`
   --> $DIR/coroutine-print-verbose-1.rs:26:25
    |
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.rs b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs
index f9ea68a8cd9..ef7199cafdd 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-2.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: -Zverbose-internals
 
 // Same as test/ui/coroutine/not-send-sync.rs
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(negative_impls)]
 
 struct NotSend;
@@ -14,14 +14,14 @@ fn main() {
     fn assert_sync<T: Sync>(_: T) {}
     fn assert_send<T: Send>(_: T) {}
 
-    assert_sync(|| {
+    assert_sync(#[coroutine] || {
         //~^ ERROR: coroutine cannot be shared between threads safely
         let a = NotSync;
         yield;
         drop(a);
     });
 
-    assert_send(|| {
+    assert_send(#[coroutine] || {
         //~^ ERROR: coroutine cannot be sent between threads safely
         let a = NotSend;
         yield;
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
index 26c9c27743c..0de53d9e1d7 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
@@ -1,7 +1,7 @@
 error: coroutine cannot be shared between threads safely
   --> $DIR/coroutine-print-verbose-2.rs:17:5
    |
-LL | /     assert_sync(|| {
+LL | /     assert_sync(#[coroutine] || {
 LL | |
 LL | |         let a = NotSync;
 LL | |         yield;
@@ -26,7 +26,7 @@ LL |     fn assert_sync<T: Sync>(_: T) {}
 error: coroutine cannot be sent between threads safely
   --> $DIR/coroutine-print-verbose-2.rs:24:5
    |
-LL | /     assert_send(|| {
+LL | /     assert_send(#[coroutine] || {
 LL | |
 LL | |         let a = NotSend;
 LL | |         yield;
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.rs b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs
index be6dbad9e1c..5dd15fc1b95 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-3.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs
@@ -1,12 +1,13 @@
 //@ compile-flags: -Zverbose-internals
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
     let x = "Type mismatch test";
-    let coroutine :() = || {
-    //~^ ERROR mismatched types
+    let coroutine: () = #[coroutine]
+    || {
+        //~^ ERROR mismatched types
         yield 1i32;
-        return x
+        return x;
     };
 }
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
index e2973cde6d3..dce45aeae56 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
@@ -1,13 +1,12 @@
 error[E0308]: mismatched types
-  --> $DIR/coroutine-print-verbose-3.rs:7:25
+  --> $DIR/coroutine-print-verbose-3.rs:8:5
    |
-LL |       let coroutine :() = || {
-   |  ____________________--___^
-   | |                    |
-   | |                    expected due to this
+LL |       let coroutine: () = #[coroutine]
+   |                      -- expected due to this
+LL | /     || {
 LL | |
 LL | |         yield 1i32;
-LL | |         return x
+LL | |         return x;
 LL | |     };
    | |_____^ expected `()`, found coroutine
    |
diff --git a/tests/ui/coroutine/reborrow-mut-upvar.rs b/tests/ui/coroutine/reborrow-mut-upvar.rs
index e1f6211baeb..716781e365c 100644
--- a/tests/ui/coroutine/reborrow-mut-upvar.rs
+++ b/tests/ui/coroutine/reborrow-mut-upvar.rs
@@ -3,7 +3,7 @@
 #![feature(coroutines)]
 
 fn _run(bar: &mut i32) {
-    || { //~ WARN unused coroutine that must be used
+    #[coroutine] || { //~ WARN unused coroutine that must be used
         {
             let _baz = &*bar;
             yield;
diff --git a/tests/ui/coroutine/reborrow-mut-upvar.stderr b/tests/ui/coroutine/reborrow-mut-upvar.stderr
index 5b614ac4be8..a05e84c5f3e 100644
--- a/tests/ui/coroutine/reborrow-mut-upvar.stderr
+++ b/tests/ui/coroutine/reborrow-mut-upvar.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/reborrow-mut-upvar.rs:6:5
+  --> $DIR/reborrow-mut-upvar.rs:6:18
    |
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         {
 LL | |             let _baz = &*bar;
 LL | |             yield;
diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
index a9c13188ff3..0f9c56786da 100644
--- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
@@ -1,16 +1,17 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn foo(x: &i32) {
     // In this case, a reference to `b` escapes the coroutine, but not
     // because of a yield. We see that there is no yield in the scope of
     // `b` and give the more generic error message.
     let mut a = &3;
-    let mut b = move || {
-        yield();
+    let mut b = #[coroutine]
+    move || {
+        yield ();
         let b = 5;
         a = &b;
         //~^ ERROR borrowed data escapes outside of coroutine
     };
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
index 8811faf2fad..6fa7082c0b8 100644
--- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
@@ -1,5 +1,5 @@
 error[E0521]: borrowed data escapes outside of coroutine
-  --> $DIR/ref-escapes-but-not-over-yield.rs:11:9
+  --> $DIR/ref-escapes-but-not-over-yield.rs:12:9
    |
 LL |     let mut a = &3;
    |         ----- `a` declared here, outside of the coroutine body
diff --git a/tests/ui/coroutine/ref-upvar-not-send.rs b/tests/ui/coroutine/ref-upvar-not-send.rs
index 487fdeea2da..89bb5e5495f 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.rs
+++ b/tests/ui/coroutine/ref-upvar-not-send.rs
@@ -1,7 +1,7 @@
 // For `Send` coroutines, suggest a `T: Sync` requirement for `&T` upvars,
 // and suggest a `T: Send` requirement for `&mut T` upvars.
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn assert_send<T: Send>(_: T) {}
 //~^ NOTE required by a bound in `assert_send`
@@ -12,7 +12,7 @@ fn assert_send<T: Send>(_: T) {}
 fn main() {
     let x: &*mut () = &std::ptr::null_mut();
     let y: &mut *mut () = &mut std::ptr::null_mut();
-    assert_send(move || {
+    assert_send(#[coroutine] move || {
         //~^ ERROR coroutine cannot be sent between threads safely
         //~| NOTE coroutine is not `Send`
         yield;
@@ -20,7 +20,7 @@ fn main() {
     });
     //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
     //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
-    assert_send(move || {
+    assert_send(#[coroutine] move || {
         //~^ ERROR coroutine cannot be sent between threads safely
         //~| NOTE coroutine is not `Send`
         yield;
diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr
index 0f91bcf4053..4c7deab3f4c 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.stderr
+++ b/tests/ui/coroutine/ref-upvar-not-send.stderr
@@ -1,8 +1,8 @@
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:15:17
+  --> $DIR/ref-upvar-not-send.rs:15:30
    |
-LL |       assert_send(move || {
-   |  _________________^
+LL |       assert_send(#[coroutine] move || {
+   |  ______________________________^
 LL | |
 LL | |
 LL | |         yield;
@@ -10,7 +10,7 @@ LL | |         let _x = x;
 LL | |     });
    | |_____^ coroutine is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:17: 15:24}: Send`
+   = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:30: 15:37}: Send`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
   --> $DIR/ref-upvar-not-send.rs:19:18
    |
@@ -23,10 +23,10 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:23:17
+  --> $DIR/ref-upvar-not-send.rs:23:30
    |
-LL |       assert_send(move || {
-   |  _________________^
+LL |       assert_send(#[coroutine] move || {
+   |  ______________________________^
 LL | |
 LL | |
 LL | |         yield;
@@ -34,7 +34,7 @@ LL | |         let _y = y;
 LL | |     });
    | |_____^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}: Send`
+   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}: Send`
 note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
   --> $DIR/ref-upvar-not-send.rs:27:18
    |
diff --git a/tests/ui/coroutine/reinit-in-match-guard.rs b/tests/ui/coroutine/reinit-in-match-guard.rs
index 4a584204773..0a97d9fbcb2 100644
--- a/tests/ui/coroutine/reinit-in-match-guard.rs
+++ b/tests/ui/coroutine/reinit-in-match-guard.rs
@@ -1,11 +1,11 @@
 //@ build-pass
 
-#![feature(coroutines)]
-
+#![feature(coroutines, stmt_expr_attributes)]
 #![allow(unused_assignments, dead_code)]
 
 fn main() {
-    let _ = || {
+    let _ = #[coroutine]
+    || {
         let mut x = vec![22_usize];
         std::mem::drop(x);
         match y() {
diff --git a/tests/ui/coroutine/resume-after-return.rs b/tests/ui/coroutine/resume-after-return.rs
index 81f86de641f..7028e1e81e5 100644
--- a/tests/ui/coroutine/resume-after-return.rs
+++ b/tests/ui/coroutine/resume-after-return.rs
@@ -1,17 +1,17 @@
 //@ run-pass
 //@ needs-unwind
 
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
-#![feature(coroutines, coroutine_trait)]
-
-use std::ops::{CoroutineState, Coroutine};
-use std::pin::Pin;
+use std::ops::{Coroutine, CoroutineState};
 use std::panic;
+use std::pin::Pin;
 
 fn main() {
-    let mut foo = || {
+    let mut foo = #[coroutine]
+    || {
         if true {
-            return
+            return;
         }
         yield;
     };
diff --git a/tests/ui/coroutine/resume-arg-late-bound.rs b/tests/ui/coroutine/resume-arg-late-bound.rs
index 3c2ab41047e..e84184da631 100644
--- a/tests/ui/coroutine/resume-arg-late-bound.rs
+++ b/tests/ui/coroutine/resume-arg-late-bound.rs
@@ -1,14 +1,14 @@
 //! Tests that we cannot produce a coroutine that accepts a resume argument
 //! with any lifetime and then stores it across a `yield`.
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 
 fn test(a: impl for<'a> Coroutine<&'a mut bool>) {}
 
 fn main() {
-    let gen = |arg: &mut bool| {
+    let gen = #[coroutine] |arg: &mut bool| {
         yield ();
         *arg = true;
     };
diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr
index 4a4ee08c529..646abaf4f7b 100644
--- a/tests/ui/coroutine/resume-arg-late-bound.stderr
+++ b/tests/ui/coroutine/resume-arg-late-bound.stderr
@@ -4,7 +4,7 @@ error: implementation of `Coroutine` is not general enough
 LL |     test(gen);
    |     ^^^^^^^^^ implementation of `Coroutine` is not general enough
    |
-   = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:15: 11:31}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`...
+   = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:28: 11:44}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`...
    = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coroutine/resume-arg-size.rs b/tests/ui/coroutine/resume-arg-size.rs
index 81e96975c98..59740a28f42 100644
--- a/tests/ui/coroutine/resume-arg-size.rs
+++ b/tests/ui/coroutine/resume-arg-size.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![allow(dropping_copy_types)]
 
 //@ run-pass
@@ -7,7 +7,8 @@ use std::mem::size_of_val;
 
 fn main() {
     // Coroutine taking a `Copy`able resume arg.
-    let gen_copy = |mut x: usize| {
+    let gen_copy = #[coroutine]
+    |mut x: usize| {
         loop {
             drop(x);
             x = yield;
@@ -15,7 +16,8 @@ fn main() {
     };
 
     // Coroutine taking a non-`Copy` resume arg.
-    let gen_move = |mut x: Box<usize>| {
+    let gen_move = #[coroutine]
+    |mut x: Box<usize>| {
         loop {
             drop(x);
             x = yield;
diff --git a/tests/ui/coroutine/resume-live-across-yield.rs b/tests/ui/coroutine/resume-live-across-yield.rs
index 45851411daa..b67619ee70f 100644
--- a/tests/ui/coroutine/resume-live-across-yield.rs
+++ b/tests/ui/coroutine/resume-live-across-yield.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
@@ -18,7 +18,8 @@ impl Drop for Dropper {
 }
 
 fn main() {
-    let mut g = |mut _d| {
+    let mut g = #[coroutine]
+    |mut _d| {
         _d = yield;
         _d
     };
diff --git a/tests/ui/coroutine/retain-resume-ref.rs b/tests/ui/coroutine/retain-resume-ref.rs
index c9f995ab0cf..6e688c33979 100644
--- a/tests/ui/coroutine/retain-resume-ref.rs
+++ b/tests/ui/coroutine/retain-resume-ref.rs
@@ -1,6 +1,6 @@
 //! This test ensures that a mutable reference cannot be passed as a resume argument twice.
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::marker::Unpin;
 use std::ops::{
@@ -12,7 +12,8 @@ use std::pin::Pin;
 fn main() {
     let mut thing = String::from("hello");
 
-    let mut gen = |r| {
+    let mut gen = #[coroutine]
+    |r| {
         if false {
             yield r;
         }
diff --git a/tests/ui/coroutine/retain-resume-ref.stderr b/tests/ui/coroutine/retain-resume-ref.stderr
index eb8b78df6c9..e23023c6e23 100644
--- a/tests/ui/coroutine/retain-resume-ref.stderr
+++ b/tests/ui/coroutine/retain-resume-ref.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `thing` as mutable more than once at a time
-  --> $DIR/retain-resume-ref.rs:23:25
+  --> $DIR/retain-resume-ref.rs:24:25
    |
 LL |     gen.as_mut().resume(&mut thing);
    |                         ---------- first mutable borrow occurs here
diff --git a/tests/ui/coroutine/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs
index eb5210087a0..0f800de8454 100644
--- a/tests/ui/coroutine/size-moved-locals.rs
+++ b/tests/ui/coroutine/size-moved-locals.rs
@@ -24,6 +24,7 @@ impl Drop for Foo {
 }
 
 fn move_before_yield() -> impl Coroutine<Yield = (), Return = ()> {
+    #[coroutine]
     static || {
         let first = Foo([0; FOO_SIZE]);
         let _second = first;
@@ -35,6 +36,7 @@ fn move_before_yield() -> impl Coroutine<Yield = (), Return = ()> {
 fn noop() {}
 
 fn move_before_yield_with_noop() -> impl Coroutine<Yield = (), Return = ()> {
+    #[coroutine]
     static || {
         let first = Foo([0; FOO_SIZE]);
         noop();
@@ -47,6 +49,7 @@ fn move_before_yield_with_noop() -> impl Coroutine<Yield = (), Return = ()> {
 // Today we don't have NRVO (we allocate space for both `first` and `second`,)
 // but we can overlap `first` with `_third`.
 fn overlap_move_points() -> impl Coroutine<Yield = (), Return = ()> {
+    #[coroutine]
     static || {
         let first = Foo([0; FOO_SIZE]);
         yield;
@@ -58,6 +61,7 @@ fn overlap_move_points() -> impl Coroutine<Yield = (), Return = ()> {
 }
 
 fn overlap_x_and_y() -> impl Coroutine<Yield = (), Return = ()> {
+    #[coroutine]
     static || {
         let x = Foo([0; FOO_SIZE]);
         yield;
diff --git a/tests/ui/coroutine/sized-yield.rs b/tests/ui/coroutine/sized-yield.rs
index 1368c88b522..a4c91fafe6c 100644
--- a/tests/ui/coroutine/sized-yield.rs
+++ b/tests/ui/coroutine/sized-yield.rs
@@ -1,11 +1,12 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
     let s = String::from("foo");
-    let mut gen = move || {
+    let mut gen = #[coroutine]
+    move || {
         //~^ ERROR the size for values of type
         yield s[..];
     };
diff --git a/tests/ui/coroutine/sized-yield.stderr b/tests/ui/coroutine/sized-yield.stderr
index 4e8dc13201d..5d5dd6803c8 100644
--- a/tests/ui/coroutine/sized-yield.stderr
+++ b/tests/ui/coroutine/sized-yield.stderr
@@ -1,8 +1,7 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/sized-yield.rs:8:19
+  --> $DIR/sized-yield.rs:9:5
    |
-LL |       let mut gen = move || {
-   |  ___________________^
+LL | /     move || {
 LL | |
 LL | |         yield s[..];
 LL | |     };
@@ -12,7 +11,7 @@ LL | |     };
    = note: the yield type of a coroutine must have a statically known size
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/sized-yield.rs:12:24
+  --> $DIR/sized-yield.rs:13:24
    |
 LL |     Pin::new(&mut gen).resume(());
    |                        ^^^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/coroutine/smoke-resume-args.rs b/tests/ui/coroutine/smoke-resume-args.rs
index 7d20cd2293d..209c4814001 100644
--- a/tests/ui/coroutine/smoke-resume-args.rs
+++ b/tests/ui/coroutine/smoke-resume-args.rs
@@ -3,7 +3,7 @@
 //@ revisions: default nomiropt
 //@[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::fmt::Debug;
 use std::ops::{
@@ -50,7 +50,7 @@ fn expect_drops<T>(expected_drops: usize, f: impl FnOnce() -> T) -> T {
 
 fn main() {
     drain(
-        &mut |mut b| {
+        &mut #[coroutine] |mut b| {
             while b != 0 {
                 b = yield (b + 1);
             }
@@ -59,21 +59,24 @@ fn main() {
         vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))],
     );
 
-    expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))]));
+    expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))]));
 
     expect_drops(6, || {
         drain(
-            &mut |a| yield yield a,
+            &mut #[coroutine] |a| yield yield a,
             vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))],
         )
     });
 
     #[allow(unreachable_code)]
-    expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))]));
+    expect_drops(2, || drain(
+        &mut #[coroutine] |a| yield return a,
+        vec![(DropMe, Complete(DropMe))]
+    ));
 
     expect_drops(2, || {
         drain(
-            &mut |a: DropMe| {
+            &mut #[coroutine] |a: DropMe| {
                 if false { yield () } else { a }
             },
             vec![(DropMe, Complete(DropMe))],
@@ -83,7 +86,7 @@ fn main() {
     expect_drops(4, || {
         drain(
             #[allow(unused_assignments, unused_variables)]
-            &mut |mut a: DropMe| {
+            &mut #[coroutine] |mut a: DropMe| {
                 a = yield;
                 a = yield;
                 a = yield;
diff --git a/tests/ui/coroutine/smoke.rs b/tests/ui/coroutine/smoke.rs
index 17d98a52a1c..bfb183fde93 100644
--- a/tests/ui/coroutine/smoke.rs
+++ b/tests/ui/coroutine/smoke.rs
@@ -6,7 +6,7 @@
 //@ needs-threads
 //@ compile-flags: --test
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
@@ -14,7 +14,7 @@ use std::thread;
 
 #[test]
 fn simple() {
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         if false {
             yield;
         }
@@ -29,7 +29,7 @@ fn simple() {
 #[test]
 fn return_capture() {
     let a = String::from("foo");
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         if false {
             yield;
         }
@@ -44,7 +44,7 @@ fn return_capture() {
 
 #[test]
 fn simple_yield() {
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield;
     };
 
@@ -61,7 +61,7 @@ fn simple_yield() {
 #[test]
 fn yield_capture() {
     let b = String::from("foo");
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield b;
     };
 
@@ -77,7 +77,7 @@ fn yield_capture() {
 
 #[test]
 fn simple_yield_value() {
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield String::from("bar");
         return String::from("foo")
     };
@@ -95,7 +95,7 @@ fn simple_yield_value() {
 #[test]
 fn return_after_yield() {
     let a = String::from("foo");
-    let mut foo = || {
+    let mut foo = #[coroutine] || {
         yield;
         return a
     };
@@ -112,34 +112,34 @@ fn return_after_yield() {
 
 #[test]
 fn send_and_sync() {
-    assert_send_sync(|| {
+    assert_send_sync(#[coroutine] || {
         yield
     });
-    assert_send_sync(|| {
+    assert_send_sync(#[coroutine] || {
         yield String::from("foo");
     });
-    assert_send_sync(|| {
+    assert_send_sync(#[coroutine] || {
         yield;
         return String::from("foo");
     });
     let a = 3;
-    assert_send_sync(|| {
+    assert_send_sync(#[coroutine] || {
         yield a;
         return
     });
     let a = 3;
-    assert_send_sync(move || {
+    assert_send_sync(#[coroutine] move || {
         yield a;
         return
     });
     let a = String::from("a");
-    assert_send_sync(|| {
+    assert_send_sync(#[coroutine] || {
         yield ;
         drop(a);
         return
     });
     let a = String::from("a");
-    assert_send_sync(move || {
+    assert_send_sync(#[coroutine] move || {
         yield ;
         drop(a);
         return
@@ -150,7 +150,7 @@ fn send_and_sync() {
 
 #[test]
 fn send_over_threads() {
-    let mut foo = || { yield };
+    let mut foo = #[coroutine] || { yield };
     thread::spawn(move || {
         match Pin::new(&mut foo).resume(()) {
             CoroutineState::Yielded(()) => {}
@@ -163,7 +163,7 @@ fn send_over_threads() {
     }).join().unwrap();
 
     let a = String::from("a");
-    let mut foo = || { yield a };
+    let mut foo = #[coroutine] || { yield a };
     thread::spawn(move || {
         match Pin::new(&mut foo).resume(()) {
             CoroutineState::Yielded(ref s) if *s == "a" => {}
diff --git a/tests/ui/coroutine/static-coroutine.rs b/tests/ui/coroutine/static-coroutine.rs
index 9beaef3e4de..eba6336d342 100644
--- a/tests/ui/coroutine/static-coroutine.rs
+++ b/tests/ui/coroutine/static-coroutine.rs
@@ -1,12 +1,13 @@
 //@ run-pass
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
-use std::pin::Pin;
 use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = static || {
+    let mut coroutine = #[coroutine]
+    static || {
         let a = true;
         let b = &a;
         yield;
diff --git a/tests/ui/coroutine/static-mut-reference-across-yield.rs b/tests/ui/coroutine/static-mut-reference-across-yield.rs
index 0d8042ed852..40d5fdf2d57 100644
--- a/tests/ui/coroutine/static-mut-reference-across-yield.rs
+++ b/tests/ui/coroutine/static-mut-reference-across-yield.rs
@@ -1,6 +1,6 @@
 //@ build-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 static mut A: [i32; 5] = [1, 2, 3, 4, 5];
 
@@ -8,13 +8,15 @@ fn is_send_sync<T: Send + Sync>(_: T) {}
 
 fn main() {
     unsafe {
-        let gen_index = static || {
+        let gen_index = #[coroutine]
+        static || {
             let u = A[{
                 yield;
                 1
             }];
         };
-        let gen_match = static || match A {
+        let gen_match = #[coroutine]
+        static || match A {
             i if {
                 yield;
                 true
diff --git a/tests/ui/coroutine/static-not-unpin.current.stderr b/tests/ui/coroutine/static-not-unpin.current.stderr
index 518abdd62c7..7d6260ac569 100644
--- a/tests/ui/coroutine/static-not-unpin.current.stderr
+++ b/tests/ui/coroutine/static-not-unpin.current.stderr
@@ -1,8 +1,8 @@
-error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned
   --> $DIR/static-not-unpin.rs:18:18
    |
 LL |     assert_unpin(coroutine);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -11,7 +11,7 @@ LL |     assert_unpin(coroutine);
 note: required by a bound in `assert_unpin`
   --> $DIR/static-not-unpin.rs:11:20
    |
-LL | fn assert_unpin<T: Unpin>(_: T) {
+LL | fn assert_unpin<T: Unpin>(_: T) {}
    |                    ^^^^^ required by this bound in `assert_unpin`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coroutine/static-not-unpin.next.stderr b/tests/ui/coroutine/static-not-unpin.next.stderr
index 518abdd62c7..7d6260ac569 100644
--- a/tests/ui/coroutine/static-not-unpin.next.stderr
+++ b/tests/ui/coroutine/static-not-unpin.next.stderr
@@ -1,8 +1,8 @@
-error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned
   --> $DIR/static-not-unpin.rs:18:18
    |
 LL |     assert_unpin(coroutine);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -11,7 +11,7 @@ LL |     assert_unpin(coroutine);
 note: required by a bound in `assert_unpin`
   --> $DIR/static-not-unpin.rs:11:20
    |
-LL | fn assert_unpin<T: Unpin>(_: T) {
+LL | fn assert_unpin<T: Unpin>(_: T) {}
    |                    ^^^^^ required by this bound in `assert_unpin`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coroutine/static-not-unpin.rs b/tests/ui/coroutine/static-not-unpin.rs
index 3704cca7729..2bc25e3796d 100644
--- a/tests/ui/coroutine/static-not-unpin.rs
+++ b/tests/ui/coroutine/static-not-unpin.rs
@@ -2,17 +2,17 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 //@ normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin"
 
 use std::marker::Unpin;
 
-fn assert_unpin<T: Unpin>(_: T) {
-}
+fn assert_unpin<T: Unpin>(_: T) {}
 
 fn main() {
-    let mut coroutine = static || {
+    let mut coroutine = #[coroutine]
+    static || {
         yield;
     };
     assert_unpin(coroutine); //~ ERROR E0277
diff --git a/tests/ui/coroutine/static-reference-across-yield.rs b/tests/ui/coroutine/static-reference-across-yield.rs
index cf19ccb54d5..e7ff658ebf6 100644
--- a/tests/ui/coroutine/static-reference-across-yield.rs
+++ b/tests/ui/coroutine/static-reference-across-yield.rs
@@ -4,10 +4,10 @@
 static A: [i32; 5] = [1, 2, 3, 4, 5];
 
 fn main() {
-    static || {
+    #[coroutine] static || {
         let u = A[{yield; 1}];
     };
-    static || {
+    #[coroutine] static || {
         match A {
             i if { yield; true } => (),
             _ => (),
diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.rs b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs
index 382e7ff3814..1c689ef7cef 100644
--- a/tests/ui/coroutine/too-live-local-in-immovable-gen.rs
+++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs
@@ -5,7 +5,7 @@
 
 fn main() {
     unsafe {
-        static move || { //~ WARN unused coroutine that must be used
+        #[coroutine] static move || { //~ WARN unused coroutine that must be used
             // Tests that the coroutine transformation finds out that `a` is not live
             // during the yield expression. Type checking will also compute liveness
             // and it should also find out that `a` is not live.
diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
index 4a67dbe71e1..48df5c5beac 100644
--- a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
+++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/too-live-local-in-immovable-gen.rs:8:9
+  --> $DIR/too-live-local-in-immovable-gen.rs:8:22
    |
-LL | /         static move || {
+LL |           #[coroutine] static move || {
+   |  ______________________^
 LL | |             // Tests that the coroutine transformation finds out that `a` is not live
 LL | |             // during the yield expression. Type checking will also compute liveness
 LL | |             // and it should also find out that `a` is not live.
diff --git a/tests/ui/coroutine/too-many-parameters.rs b/tests/ui/coroutine/too-many-parameters.rs
index 377d80c7b22..3baaf062347 100644
--- a/tests/ui/coroutine/too-many-parameters.rs
+++ b/tests/ui/coroutine/too-many-parameters.rs
@@ -1,6 +1,7 @@
 #![feature(coroutines)]
 
 fn main() {
+    #[coroutine]
     |(), ()| {
         //~^ error: too many parameters for a coroutine
         yield;
diff --git a/tests/ui/coroutine/too-many-parameters.stderr b/tests/ui/coroutine/too-many-parameters.stderr
index c0917c7225b..45dad8e349e 100644
--- a/tests/ui/coroutine/too-many-parameters.stderr
+++ b/tests/ui/coroutine/too-many-parameters.stderr
@@ -1,5 +1,5 @@
 error[E0628]: too many parameters for a coroutine (expected 0 or 1 parameters)
-  --> $DIR/too-many-parameters.rs:4:5
+  --> $DIR/too-many-parameters.rs:5:5
    |
 LL |     |(), ()| {
    |     ^^^^^^^^
diff --git a/tests/ui/coroutine/type-mismatch-error.rs b/tests/ui/coroutine/type-mismatch-error.rs
index 0d04c21484c..ee4e27c20da 100644
--- a/tests/ui/coroutine/type-mismatch-error.rs
+++ b/tests/ui/coroutine/type-mismatch-error.rs
@@ -1,7 +1,7 @@
 //! Test that we get the expected type mismatch error instead of "closure is expected to take 0
 //! arguments" (which got introduced after implementing resume arguments).
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 
@@ -9,6 +9,7 @@ fn f<G: Coroutine>(_: G, _: G::Return) {}
 
 fn main() {
     f(
+        #[coroutine]
         |a: u8| {
             if false {
                 yield ();
diff --git a/tests/ui/coroutine/type-mismatch-error.stderr b/tests/ui/coroutine/type-mismatch-error.stderr
index 737d9afdd79..f10c30e2590 100644
--- a/tests/ui/coroutine/type-mismatch-error.stderr
+++ b/tests/ui/coroutine/type-mismatch-error.stderr
@@ -1,5 +1,5 @@
 error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/type-mismatch-error.rs:16:17
+  --> $DIR/type-mismatch-error.rs:17:17
    |
 LL | /             if false {
 LL | |                 yield ();
diff --git a/tests/ui/coroutine/type-mismatch-signature-deduction.rs b/tests/ui/coroutine/type-mismatch-signature-deduction.rs
index d4ca622e80f..5b04b3efaaa 100644
--- a/tests/ui/coroutine/type-mismatch-signature-deduction.rs
+++ b/tests/ui/coroutine/type-mismatch-signature-deduction.rs
@@ -4,6 +4,7 @@ use std::ops::Coroutine;
 
 fn foo() -> impl Coroutine<Return = i32> {
     //~^ ERROR type mismatch
+    #[coroutine]
     || {
         if false {
             return Ok(6);
diff --git a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
index f26e30a8e74..08927196037 100644
--- a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
+++ b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch-signature-deduction.rs:14:9
+  --> $DIR/type-mismatch-signature-deduction.rs:15:9
    |
 LL |         5
    |         ^ expected `Result<{integer}, _>`, found integer
@@ -7,7 +7,7 @@ LL |         5
    = note: expected enum `Result<{integer}, _>`
               found type `{integer}`
 note: return type inferred to be `Result<{integer}, _>` here
-  --> $DIR/type-mismatch-signature-deduction.rs:9:20
+  --> $DIR/type-mismatch-signature-deduction.rs:10:20
    |
 LL |             return Ok(6);
    |                    ^^^^^
@@ -18,7 +18,7 @@ LL |         Ok(5)
 LL |         Err(5)
    |         ++++ +
 
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7} as Coroutine>::Return == i32`
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-deduction.rs:8:5: 8:7} as Coroutine>::Return == i32`
   --> $DIR/type-mismatch-signature-deduction.rs:5:13
    |
 LL | fn foo() -> impl Coroutine<Return = i32> {
diff --git a/tests/ui/coroutine/uninhabited-field.rs b/tests/ui/coroutine/uninhabited-field.rs
index 79776d653b1..d6ada07ce0c 100644
--- a/tests/ui/coroutine/uninhabited-field.rs
+++ b/tests/ui/coroutine/uninhabited-field.rs
@@ -3,7 +3,7 @@
 #![allow(unused)]
 #![feature(assert_matches)]
 #![feature(coroutine_trait)]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(never_type)]
 use std::assert_matches::assert_matches;
 use std::ops::Coroutine;
@@ -13,7 +13,7 @@ use std::pin::Pin;
 fn conjure<T>() -> T { loop {} }
 
 fn run<T>(x: bool, y: bool) {
-    let mut c = || {
+    let mut c = #[coroutine] || {
         if x {
             let a : T;
             if y {
diff --git a/tests/ui/coroutine/unsized-capture-across-yield.rs b/tests/ui/coroutine/unsized-capture-across-yield.rs
index ef9cbc1d677..c86b1823aaf 100644
--- a/tests/ui/coroutine/unsized-capture-across-yield.rs
+++ b/tests/ui/coroutine/unsized-capture-across-yield.rs
@@ -7,6 +7,7 @@ use std::ops::Coroutine;
 
 fn capture() -> impl Coroutine {
     let b: [u8] = *(Box::new([]) as Box<[u8]>);
+    #[coroutine]
     move || {
         println!("{:?}", &b);
         //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/tests/ui/coroutine/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr
index 436f0901a97..03551f1bbff 100644
--- a/tests/ui/coroutine/unsized-capture-across-yield.stderr
+++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-capture-across-yield.rs:11:27
+  --> $DIR/unsized-capture-across-yield.rs:12:27
    |
 LL |     move || {
    |          -- this closure captures all values by move
diff --git a/tests/ui/coroutine/unsized-local-across-yield.rs b/tests/ui/coroutine/unsized-local-across-yield.rs
index 7a8ed60e46a..cb8ced13a11 100644
--- a/tests/ui/coroutine/unsized-local-across-yield.rs
+++ b/tests/ui/coroutine/unsized-local-across-yield.rs
@@ -6,6 +6,7 @@
 use std::ops::Coroutine;
 
 fn across() -> impl Coroutine {
+    #[coroutine]
     move || {
         let b: [u8] = *(Box::new([]) as Box<[u8]>);
         //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/tests/ui/coroutine/unsized-local-across-yield.stderr b/tests/ui/coroutine/unsized-local-across-yield.stderr
index c4c3be77ac2..4fe0f135a9d 100644
--- a/tests/ui/coroutine/unsized-local-across-yield.stderr
+++ b/tests/ui/coroutine/unsized-local-across-yield.stderr
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-local-across-yield.rs:10:13
+  --> $DIR/unsized-local-across-yield.rs:11:13
    |
 LL |         let b: [u8] = *(Box::new([]) as Box<[u8]>);
    |             ^ doesn't have a size known at compile-time
diff --git a/tests/ui/coroutine/yield-in-args-rev.rs b/tests/ui/coroutine/yield-in-args-rev.rs
index b074e2bc939..29d79df25fb 100644
--- a/tests/ui/coroutine/yield-in-args-rev.rs
+++ b/tests/ui/coroutine/yield-in-args-rev.rs
@@ -10,7 +10,7 @@
 fn foo(_a: (), _b: &bool) {}
 
 fn bar() {
-    || { //~ WARN unused coroutine that must be used
+    #[coroutine] || { //~ WARN unused coroutine that must be used
         let b = true;
         foo(yield, &b);
     };
diff --git a/tests/ui/coroutine/yield-in-args-rev.stderr b/tests/ui/coroutine/yield-in-args-rev.stderr
index dbf46739e8b..10829d66185 100644
--- a/tests/ui/coroutine/yield-in-args-rev.stderr
+++ b/tests/ui/coroutine/yield-in-args-rev.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/yield-in-args-rev.rs:13:5
+  --> $DIR/yield-in-args-rev.rs:13:18
    |
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         let b = true;
 LL | |         foo(yield, &b);
 LL | |     };
diff --git a/tests/ui/coroutine/yield-in-args.rs b/tests/ui/coroutine/yield-in-args.rs
index b2827148d77..bc9909b310c 100644
--- a/tests/ui/coroutine/yield-in-args.rs
+++ b/tests/ui/coroutine/yield-in-args.rs
@@ -3,6 +3,7 @@
 fn foo(_b: &bool, _a: ()) {}
 
 fn main() {
+    #[coroutine]
     || {
         let b = true;
         foo(&b, yield); //~ ERROR
diff --git a/tests/ui/coroutine/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr
index 7233f47884b..1d2c54f9bdb 100644
--- a/tests/ui/coroutine/yield-in-args.stderr
+++ b/tests/ui/coroutine/yield-in-args.stderr
@@ -1,5 +1,5 @@
 error[E0626]: borrow may still be in use when coroutine yields
-  --> $DIR/yield-in-args.rs:8:13
+  --> $DIR/yield-in-args.rs:9:13
    |
 LL |         foo(&b, yield);
    |             ^^  ----- possible yield occurs here
diff --git a/tests/ui/coroutine/yield-in-const.rs b/tests/ui/coroutine/yield-in-const.rs
index 22651f32cf8..dc1b30155b9 100644
--- a/tests/ui/coroutine/yield-in-const.rs
+++ b/tests/ui/coroutine/yield-in-const.rs
@@ -2,5 +2,6 @@
 
 const A: u8 = { yield 3u8; 3u8};
 //~^ ERROR yield expression outside
+//~| ERROR `yield` can only be used in
 
 fn main() {}
diff --git a/tests/ui/coroutine/yield-in-const.stderr b/tests/ui/coroutine/yield-in-const.stderr
index d5748b05337..f02729412cc 100644
--- a/tests/ui/coroutine/yield-in-const.stderr
+++ b/tests/ui/coroutine/yield-in-const.stderr
@@ -1,9 +1,15 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/yield-in-const.rs:3:17
+   |
+LL | const A: u8 = { yield 3u8; 3u8};
+   |                 ^^^^^^^^^
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-const.rs:3:17
    |
 LL | const A: u8 = { yield 3u8; 3u8};
    |                 ^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0627`.
diff --git a/tests/ui/coroutine/yield-in-function.rs b/tests/ui/coroutine/yield-in-function.rs
index a99312043bd..427c5d0e7f5 100644
--- a/tests/ui/coroutine/yield-in-function.rs
+++ b/tests/ui/coroutine/yield-in-function.rs
@@ -2,3 +2,4 @@
 
 fn main() { yield; }
 //~^ ERROR yield expression outside
+//~| ERROR `yield` can only be used in
diff --git a/tests/ui/coroutine/yield-in-function.stderr b/tests/ui/coroutine/yield-in-function.stderr
index b9d4708bb8d..dbebf310b04 100644
--- a/tests/ui/coroutine/yield-in-function.stderr
+++ b/tests/ui/coroutine/yield-in-function.stderr
@@ -1,9 +1,20 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/yield-in-function.rs:3:13
+   |
+LL | fn main() { yield; }
+   |             ^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] fn main() { yield; }
+   | ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-function.rs:3:13
    |
 LL | fn main() { yield; }
    |             ^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0627`.
diff --git a/tests/ui/coroutine/yield-in-initializer.rs b/tests/ui/coroutine/yield-in-initializer.rs
index 19218926b8a..3caefac013e 100644
--- a/tests/ui/coroutine/yield-in-initializer.rs
+++ b/tests/ui/coroutine/yield-in-initializer.rs
@@ -3,7 +3,7 @@
 #![feature(coroutines)]
 
 fn main() {
-    static || { //~ WARN unused coroutine that must be used
+    #[coroutine] static || { //~ WARN unused coroutine that must be used
         loop {
             // Test that `opt` is not live across the yield, even when borrowed in a loop
             // See https://github.com/rust-lang/rust/issues/52792
diff --git a/tests/ui/coroutine/yield-in-initializer.stderr b/tests/ui/coroutine/yield-in-initializer.stderr
index 614df43f2f5..1e22b787668 100644
--- a/tests/ui/coroutine/yield-in-initializer.stderr
+++ b/tests/ui/coroutine/yield-in-initializer.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/yield-in-initializer.rs:6:5
+  --> $DIR/yield-in-initializer.rs:6:18
    |
-LL | /     static || {
+LL |       #[coroutine] static || {
+   |  __________________^
 LL | |         loop {
 LL | |             // Test that `opt` is not live across the yield, even when borrowed in a loop
 LL | |             // See https://github.com/rust-lang/rust/issues/52792
diff --git a/tests/ui/coroutine/yield-in-static.rs b/tests/ui/coroutine/yield-in-static.rs
index 45e0380d46d..99d08913e64 100644
--- a/tests/ui/coroutine/yield-in-static.rs
+++ b/tests/ui/coroutine/yield-in-static.rs
@@ -2,5 +2,6 @@
 
 static B: u8 = { yield 3u8; 3u8};
 //~^ ERROR yield expression outside
+//~| ERROR `yield` can only be used in
 
 fn main() {}
diff --git a/tests/ui/coroutine/yield-in-static.stderr b/tests/ui/coroutine/yield-in-static.stderr
index b56283cab66..d1fd4eab0fc 100644
--- a/tests/ui/coroutine/yield-in-static.stderr
+++ b/tests/ui/coroutine/yield-in-static.stderr
@@ -1,9 +1,15 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/yield-in-static.rs:3:18
+   |
+LL | static B: u8 = { yield 3u8; 3u8};
+   |                  ^^^^^^^^^
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-static.rs:3:18
    |
 LL | static B: u8 = { yield 3u8; 3u8};
    |                  ^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0627`.
diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs
index 31025c33b1a..6833bc99012 100644
--- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs
+++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs
@@ -4,4 +4,5 @@ fn main() {
     yield || for i in 0 { }
     //~^ ERROR yield expression outside of coroutine literal
     //~| ERROR `{integer}` is not an iterator
+    //~| ERROR `yield` can only be used in
 }
diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
index 8f8bec99458..921e8d5d47a 100644
--- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
+++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
@@ -1,3 +1,14 @@
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/yield-outside-coroutine-issue-78653.rs:4:5
+   |
+LL |     yield || for i in 0 { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] fn main() {
+   | ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-outside-coroutine-issue-78653.rs:4:5
    |
@@ -14,7 +25,7 @@ LL |     yield || for i in 0 { }
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `{integer}` to implement `IntoIterator`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0627.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/coroutine/yield-subtype.rs b/tests/ui/coroutine/yield-subtype.rs
index 271f8362f17..adee5075e83 100644
--- a/tests/ui/coroutine/yield-subtype.rs
+++ b/tests/ui/coroutine/yield-subtype.rs
@@ -8,7 +8,7 @@ fn bar<'a>() {
     let a: &'static str = "hi";
     let b: &'a str = a;
 
-    || { //~ WARN unused coroutine that must be used
+    #[coroutine] || { //~ WARN unused coroutine that must be used
         yield a;
         yield b;
     };
diff --git a/tests/ui/coroutine/yield-subtype.stderr b/tests/ui/coroutine/yield-subtype.stderr
index 5e7ae9f581e..973415327a5 100644
--- a/tests/ui/coroutine/yield-subtype.stderr
+++ b/tests/ui/coroutine/yield-subtype.stderr
@@ -1,7 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/yield-subtype.rs:11:5
+  --> $DIR/yield-subtype.rs:11:18
    |
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         yield a;
 LL | |         yield b;
 LL | |     };
diff --git a/tests/ui/coroutine/yield-while-iterating.rs b/tests/ui/coroutine/yield-while-iterating.rs
index 66ac6d3922a..77f601e4f2c 100644
--- a/tests/ui/coroutine/yield-while-iterating.rs
+++ b/tests/ui/coroutine/yield-while-iterating.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{CoroutineState, Coroutine};
 use std::cell::Cell;
@@ -9,7 +9,7 @@ fn yield_during_iter_owned_data(x: Vec<i32>) {
     // reference to it.  This winds up becoming a rather confusing
     // regionck error -- in particular, we would freeze with the
     // reference in scope, and it doesn't live long enough.
-    let _b = move || {
+    let _b =#[coroutine]  move || {
         for p in &x { //~ ERROR
             yield();
         }
@@ -17,7 +17,7 @@ fn yield_during_iter_owned_data(x: Vec<i32>) {
 }
 
 fn yield_during_iter_borrowed_slice(x: &[i32]) {
-    let _b = move || {
+    let _b = #[coroutine] move || {
         for p in x {
             yield();
         }
@@ -26,7 +26,7 @@ fn yield_during_iter_borrowed_slice(x: &[i32]) {
 
 fn yield_during_iter_borrowed_slice_2() {
     let mut x = vec![22_i32];
-    let _b = || {
+    let _b = #[coroutine] || {
         for p in &x {
             yield();
         }
@@ -38,7 +38,7 @@ fn yield_during_iter_borrowed_slice_3() {
     // OK to take a mutable ref to `x` and yield
     // up pointers from it:
     let mut x = vec![22_i32];
-    let mut b = || {
+    let mut b = #[coroutine] || {
         for p in &mut x {
             yield p;
         }
@@ -50,7 +50,7 @@ fn yield_during_iter_borrowed_slice_4() {
     // ...but not OK to do that while reading
     // from `x` too
     let mut x = vec![22_i32];
-    let mut b = || {
+    let mut b = #[coroutine] || {
         for p in &mut x {
             yield p;
         }
@@ -61,7 +61,7 @@ fn yield_during_iter_borrowed_slice_4() {
 
 fn yield_during_range_iter() {
     // Should be OK.
-    let mut b = || {
+    let mut b = #[coroutine] || {
         let v = vec![1,2,3];
         let len = v.len();
         for i in 0..len {
diff --git a/tests/ui/coroutine/yield-while-iterating.stderr b/tests/ui/coroutine/yield-while-iterating.stderr
index 5330121f372..f81c914c4bd 100644
--- a/tests/ui/coroutine/yield-while-iterating.stderr
+++ b/tests/ui/coroutine/yield-while-iterating.stderr
@@ -9,8 +9,8 @@ LL |             yield();
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/yield-while-iterating.rs:58:20
    |
-LL |     let mut b = || {
-   |                 -- mutable borrow occurs here
+LL |     let mut b = #[coroutine] || {
+   |                              -- mutable borrow occurs here
 LL |         for p in &mut x {
    |                       - first borrow occurs due to use of `x` in coroutine
 ...
diff --git a/tests/ui/coroutine/yield-while-local-borrowed.rs b/tests/ui/coroutine/yield-while-local-borrowed.rs
index 7f8d1d4543d..3db30c36712 100644
--- a/tests/ui/coroutine/yield-while-local-borrowed.rs
+++ b/tests/ui/coroutine/yield-while-local-borrowed.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::cell::Cell;
 use std::ops::{Coroutine, CoroutineState};
@@ -9,7 +9,7 @@ fn borrow_local_inline() {
     //
     // (This error occurs because the region shows up in the type of
     // `b` and gets extended by region inference.)
-    let mut b = move || {
+    let mut b = #[coroutine] move || {
         let a = &mut 3;
         //~^ ERROR borrow may still be in use when coroutine yields
         yield ();
@@ -20,7 +20,7 @@ fn borrow_local_inline() {
 
 fn borrow_local_inline_done() {
     // No error here -- `a` is not in scope at the point of `yield`.
-    let mut b = move || {
+    let mut b = #[coroutine] move || {
         {
             let a = &mut 3;
         }
@@ -34,7 +34,7 @@ fn borrow_local() {
     //
     // (This error occurs because the region shows up in the type of
     // `b` and gets extended by region inference.)
-    let mut b = move || {
+    let mut b = #[coroutine] move || {
         let a = 3;
         {
             let b = &a;
diff --git a/tests/ui/coroutine/yield-while-ref-reborrowed.rs b/tests/ui/coroutine/yield-while-ref-reborrowed.rs
index 07c59175858..2600d0b4124 100644
--- a/tests/ui/coroutine/yield-while-ref-reborrowed.rs
+++ b/tests/ui/coroutine/yield-while-ref-reborrowed.rs
@@ -1,15 +1,16 @@
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
-use std::ops::{CoroutineState, Coroutine};
 use std::cell::Cell;
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn reborrow_shared_ref(x: &i32) {
     // This is OK -- we have a borrow live over the yield, but it's of
     // data that outlives the coroutine.
-    let mut b = move || {
+    let mut b = #[coroutine]
+    move || {
         let a = &*x;
-        yield();
+        yield ();
         println!("{}", a);
     };
     Pin::new(&mut b).resume(());
@@ -18,9 +19,10 @@ fn reborrow_shared_ref(x: &i32) {
 fn reborrow_mutable_ref(x: &mut i32) {
     // This is OK -- we have a borrow live over the yield, but it's of
     // data that outlives the coroutine.
-    let mut b = move || {
+    let mut b = #[coroutine]
+    move || {
         let a = &mut *x;
-        yield();
+        yield ();
         println!("{}", a);
     };
     Pin::new(&mut b).resume(());
@@ -28,13 +30,14 @@ fn reborrow_mutable_ref(x: &mut i32) {
 
 fn reborrow_mutable_ref_2(x: &mut i32) {
     // ...but not OK to go on using `x`.
-    let mut b = || {
+    let mut b = #[coroutine]
+    || {
         let a = &mut *x;
-        yield();
+        yield ();
         println!("{}", a);
     };
     println!("{}", x); //~ ERROR
     Pin::new(&mut b).resume(());
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr
index 62ac0265311..7c9b766457d 100644
--- a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr
+++ b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr
@@ -1,8 +1,8 @@
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/yield-while-ref-reborrowed.rs:36:20
+  --> $DIR/yield-while-ref-reborrowed.rs:39:20
    |
-LL |     let mut b = || {
-   |                 -- coroutine construction occurs here
+LL |     || {
+   |     -- coroutine construction occurs here
 LL |         let a = &mut *x;
    |                      -- first borrow occurs due to use of `x` in coroutine
 ...
diff --git a/tests/ui/delegation/auxiliary/fn-header-aux.rs b/tests/ui/delegation/auxiliary/fn-header-aux.rs
new file mode 100644
index 00000000000..d26209a4f78
--- /dev/null
+++ b/tests/ui/delegation/auxiliary/fn-header-aux.rs
@@ -0,0 +1,9 @@
+//@ edition:2018
+
+#![feature(c_variadic)]
+
+pub unsafe fn unsafe_fn_extern() {}
+pub extern "C" fn extern_fn_extern() {}
+pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
+pub const fn const_fn_extern() {}
+pub async fn async_fn_extern() {}
diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs
new file mode 100644
index 00000000000..db20e1058e0
--- /dev/null
+++ b/tests/ui/delegation/fn-header.rs
@@ -0,0 +1,57 @@
+//@ check-pass
+//@ edition:2018
+//@ aux-crate:fn_header_aux=fn-header-aux.rs
+
+#![feature(c_variadic)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+#![deny(unused_unsafe)]
+
+mod to_reuse {
+    pub unsafe fn unsafe_fn() {}
+    pub extern "C" fn extern_fn() {}
+    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+    pub const fn const_fn() {}
+    pub async fn async_fn() {}
+}
+
+reuse to_reuse::unsafe_fn;
+reuse to_reuse::extern_fn;
+reuse to_reuse::variadic_fn;
+reuse to_reuse::const_fn;
+reuse to_reuse::async_fn;
+
+reuse fn_header_aux::unsafe_fn_extern;
+reuse fn_header_aux::extern_fn_extern;
+reuse fn_header_aux::variadic_fn_extern;
+reuse fn_header_aux::const_fn_extern;
+reuse fn_header_aux::async_fn_extern;
+
+const fn const_check() {
+    const_fn();
+    const_fn_extern();
+}
+
+async fn async_check() {
+    async_fn().await;
+    async_fn_extern().await;
+}
+
+fn main() {
+    unsafe {
+        unsafe_fn();
+        unsafe_fn_extern();
+    }
+    extern_fn();
+    extern_fn_extern();
+    let _: extern "C" fn() = extern_fn;
+    let _: extern "C" fn() = extern_fn_extern;
+    unsafe {
+        variadic_fn(0);
+        variadic_fn(0, 1);
+        variadic_fn_extern(0);
+        variadic_fn_extern(0, 1);
+    }
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
+}
diff --git a/tests/ui/delegation/impl-trait.rs b/tests/ui/delegation/impl-trait.rs
new file mode 100644
index 00000000000..13df0155485
--- /dev/null
+++ b/tests/ui/delegation/impl-trait.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub fn foo() -> impl Clone { 0 }
+}
+
+reuse to_reuse::foo;
+
+trait Trait {
+    fn bar() -> impl Clone { 1 }
+}
+
+struct S;
+impl Trait for S {}
+
+impl S {
+    reuse to_reuse::foo;
+    reuse <S as Trait>::bar;
+}
+
+fn main() {
+    foo().clone();
+    <S>::bar().clone();
+}
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 9dccb12b57a..5f78de97638 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -14,9 +14,9 @@ mod generics {
         fn foo3<'a: 'a>(_: &'a u32) {}
 
         reuse GenericTrait::bar;
-        //~^ delegation with early bound generics is not supported yet
+        //~^ ERROR delegation with early bound generics is not supported yet
         reuse GenericTrait::bar1;
-        //~^ delegation with early bound generics is not supported yet
+        //~^ ERROR delegation with early bound generics is not supported yet
     }
 
     struct F;
@@ -73,26 +73,18 @@ mod opaque {
     }
     reuse to_reuse::opaque_arg;
     //~^ ERROR delegation with early bound generics is not supported yet
-    reuse to_reuse::opaque_ret;
-    //~^ ERROR delegation to a function with opaque type is not supported yet
-}
 
-mod fn_header {
-    mod to_reuse {
-        pub unsafe fn unsafe_fn() {}
-        pub extern "C" fn extern_fn() {}
-        pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
-        pub const fn const_fn() {}
+    trait ToReuse {
+        fn opaque_ret() -> impl Trait { unimplemented!() }
     }
 
-    reuse to_reuse::unsafe_fn;
-    //~^ ERROR delegation to unsafe functions is not supported yet
-    reuse to_reuse::extern_fn;
-    //~^ ERROR delegation to non Rust ABI functions is not supported yet
-    reuse to_reuse::variadic_fn;
-    //~^ ERROR delegation to variadic functions is not supported yet
-    reuse to_reuse::const_fn;
-    //~^ ERROR delegation to const functions is not supported yet
+    // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
+    impl ToReuse for u8 {
+        reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
+    }
+    impl ToReuse for u16 {
+        reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
+    }
 }
 
 mod recursive {
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index f6c49366899..e2cb04f977b 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -115,53 +115,46 @@ LL |         pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
 LL |     reuse to_reuse::opaque_arg;
    |                     ^^^^^^^^^^
 
-error: delegation to a function with opaque type is not supported yet
-  --> $DIR/not-supported.rs:76:21
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`
+  --> $DIR/not-supported.rs:83:25
    |
-LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
-   |         --------------------------------- callee defined here
-...
-LL |     reuse to_reuse::opaque_ret;
-   |                     ^^^^^^^^^^
-
-error: delegation to unsafe functions is not supported yet
-  --> $DIR/not-supported.rs:88:21
+LL |         reuse to_reuse::opaque_ret;
+   |                         ^^^^^^^^^^
    |
-LL |         pub unsafe fn unsafe_fn() {}
-   |         ------------------------- callee defined here
-...
-LL |     reuse to_reuse::unsafe_fn;
-   |                     ^^^^^^^^^
-
-error: delegation to non Rust ABI functions is not supported yet
-  --> $DIR/not-supported.rs:90:21
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+  --> $DIR/not-supported.rs:83:25
    |
-LL |         pub extern "C" fn extern_fn() {}
-   |         ----------------------------- callee defined here
-...
-LL |     reuse to_reuse::extern_fn;
-   |                     ^^^^^^^^^
-
-error: delegation to variadic functions is not supported yet
-  --> $DIR/not-supported.rs:92:21
+LL |         reuse to_reuse::opaque_ret;
+   |                         ^^^^^^^^^^
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>` is well-formed
+  --> $DIR/not-supported.rs:82:5
    |
-LL |         pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
-   |         ------------------------------------------------------------- callee defined here
-...
-LL |     reuse to_reuse::variadic_fn;
-   |                     ^^^^^^^^^^^
+LL |     impl ToReuse for u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error: delegation to const functions is not supported yet
-  --> $DIR/not-supported.rs:94:21
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`
+  --> $DIR/not-supported.rs:86:24
    |
-LL |         pub const fn const_fn() {}
-   |         ----------------------- callee defined here
-...
-LL |     reuse to_reuse::const_fn;
-   |                     ^^^^^^^^
+LL |         reuse ToReuse::opaque_ret;
+   |                        ^^^^^^^^^^
+   |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+  --> $DIR/not-supported.rs:86:24
+   |
+LL |         reuse ToReuse::opaque_ret;
+   |                        ^^^^^^^^^^
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>` is well-formed
+  --> $DIR/not-supported.rs:85:5
+   |
+LL |     impl ToReuse for u16 {
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: recursive delegation is not supported yet
-  --> $DIR/not-supported.rs:107:22
+  --> $DIR/not-supported.rs:99:22
    |
 LL |         pub reuse to_reuse2::foo;
    |                              --- callee defined here
@@ -169,7 +162,7 @@ LL |         pub reuse to_reuse2::foo;
 LL |     reuse to_reuse1::foo;
    |                      ^^^
 
-error: aborting due to 19 previous errors
+error: aborting due to 16 previous errors
 
-Some errors have detailed explanations: E0049, E0195.
+Some errors have detailed explanations: E0049, E0195, E0391.
 For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/rename.rs b/tests/ui/delegation/rename.rs
new file mode 100644
index 00000000000..f4b3da76c56
--- /dev/null
+++ b/tests/ui/delegation/rename.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub fn a() {}
+}
+
+reuse to_reuse::a as b;
+
+struct S;
+impl S {
+    reuse to_reuse::a as b;
+}
+
+fn main() {
+    b();
+    S::b();
+}
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index 26ac532263f..a8523d25cab 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -40,7 +40,10 @@ note: if `Y` implemented `Clone`, you could clone the value
   --> $DIR/deriving-with-repr-packed.rs:16:1
    |
 LL | struct Y(usize);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL | struct X(Y);
+   |          - you could clone this value
    = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/tests/ui/drop/dynamic-drop.rs b/tests/ui/drop/dynamic-drop.rs
index f848a1a340b..b695b5702d9 100644
--- a/tests/ui/drop/dynamic-drop.rs
+++ b/tests/ui/drop/dynamic-drop.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ needs-unwind
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 #![feature(if_let_guard)]
 
 #![allow(unused_assignments)]
@@ -176,7 +176,7 @@ fn vec_simple(a: &Allocator) {
 fn coroutine(a: &Allocator, run_count: usize) {
     assert!(run_count < 4);
 
-    let mut gen = || {
+    let mut gen = #[coroutine] || {
         (a.alloc(),
          yield a.alloc(),
          a.alloc(),
diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr
index 900cb706bd9..343bca9a72e 100644
--- a/tests/ui/error-codes/E0504.stderr
+++ b/tests/ui/error-codes/E0504.stderr
@@ -18,7 +18,10 @@ note: if `FancyNum` implemented `Clone`, you could clone the value
   --> $DIR/E0504.rs:1:1
    |
 LL | struct FancyNum {
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let fancy_ref = &fancy_num;
+   |                     ---------- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr
index ce01298a70d..266df9ea32a 100644
--- a/tests/ui/error-codes/E0505.stderr
+++ b/tests/ui/error-codes/E0505.stderr
@@ -15,7 +15,10 @@ note: if `Value` implemented `Clone`, you could clone the value
   --> $DIR/E0505.rs:1:1
    |
 LL | struct Value {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let _ref_to_val: &Value = &x;
+   |                                   -- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr
index 60a4daa9d38..70d99ea2cce 100644
--- a/tests/ui/error-codes/E0507.stderr
+++ b/tests/ui/error-codes/E0507.stderr
@@ -15,7 +15,10 @@ note: if `TheDarkKnight` implemented `Clone`, you could clone the value
   --> $DIR/E0507.rs:3:1
    |
 LL | struct TheDarkKnight;
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     x.borrow().nothing_is_true();
+   |     ---------- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr
index 96d3bcb67a5..fcfac399e0d 100644
--- a/tests/ui/error-codes/E0508-fail.stderr
+++ b/tests/ui/error-codes/E0508-fail.stderr
@@ -11,7 +11,10 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/E0508-fail.rs:1:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let _value = array[0];
+   |                  -------- you could clone this value
 help: consider borrowing here
    |
 LL |     let _value = &array[0];
diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr
index c1b622e2432..b9fa0f4d17a 100644
--- a/tests/ui/error-codes/E0508.stderr
+++ b/tests/ui/error-codes/E0508.stderr
@@ -11,7 +11,10 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/E0508.rs:1:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let _value = array[0];
+   |                  -------- you could clone this value
 help: consider borrowing here
    |
 LL |     let _value = &array[0];
diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr
index 75c372d0440..628a253e085 100644
--- a/tests/ui/error-codes/E0509.stderr
+++ b/tests/ui/error-codes/E0509.stderr
@@ -11,7 +11,10 @@ note: if `FancyNum` implemented `Clone`, you could clone the value
   --> $DIR/E0509.rs:1:1
    |
 LL | struct FancyNum {
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let fancy_field = drop_struct.fancy;
+   |                       ----------------- you could clone this value
 help: consider borrowing here
    |
 LL |     let fancy_field = &drop_struct.fancy;
diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs
index 93bf83ecf53..d90fb765a23 100644
--- a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs
+++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs
@@ -4,6 +4,6 @@
 
 fn main() {
     let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures
-    let _coroutine = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures
+    let _coroutine = #[coroutine] #[track_caller] || { yield; }; //~ `#[track_caller]` on closures
     let _future = #[track_caller] async {}; //~ `#[track_caller]` on closures
 }
diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr
index 17b5e6016a4..0b12b73fd1f 100644
--- a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr
+++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr
@@ -9,10 +9,10 @@ LL |     let _closure = #[track_caller] || {};
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `#[track_caller]` on closures is currently unstable
-  --> $DIR/feature-gate-closure_track_caller.rs:7:22
+  --> $DIR/feature-gate-closure_track_caller.rs:7:35
    |
-LL |     let _coroutine = #[track_caller] || { yield; };
-   |                      ^^^^^^^^^^^^^^^
+LL |     let _coroutine = #[coroutine] #[track_caller] || { yield; };
+   |                                   ^^^^^^^^^^^^^^^
    |
    = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
    = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
index 1cef163cef5..3bb48e4a37a 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
@@ -8,8 +8,19 @@ LL |     yield true;
    = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/feature-gate-coroutines.rs:5:5
+   |
+LL |     yield true;
+   |     ^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] fn main() {
+   | ++++++++++++
+
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-coroutines.rs:9:16
+  --> $DIR/feature-gate-coroutines.rs:10:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
@@ -18,13 +29,24 @@ LL |     let _ = || yield true;
    = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/feature-gate-coroutines.rs:10:16
+   |
+LL |     let _ = || yield true;
+   |                ^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/feature-gate-coroutines.rs:5:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0627, E0658.
 For more information about an error, try `rustc --explain E0627`.
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
index 403f0549aef..65e7737ef84 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
@@ -9,7 +9,7 @@ LL |     yield true;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-coroutines.rs:9:16
+  --> $DIR/feature-gate-coroutines.rs:10:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     let _ = || yield true;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-coroutines.rs:16:5
+  --> $DIR/feature-gate-coroutines.rs:18:5
    |
 LL |     yield;
    |     ^^^^^
@@ -29,7 +29,7 @@ LL |     yield;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-coroutines.rs:17:5
+  --> $DIR/feature-gate-coroutines.rs:19:5
    |
 LL |     yield 0;
    |     ^^^^^^^
@@ -49,8 +49,19 @@ LL |     yield true;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/feature-gate-coroutines.rs:5:5
+   |
+LL |     yield true;
+   |     ^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL | #[coroutine] fn main() {
+   | ++++++++++++
+
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-coroutines.rs:9:16
+  --> $DIR/feature-gate-coroutines.rs:10:16
    |
 LL |     let _ = || yield true;
    |                ^^^^^^^^^^
@@ -60,13 +71,24 @@ LL |     let _ = || yield true;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
+  --> $DIR/feature-gate-coroutines.rs:10:16
+   |
+LL |     let _ = || yield true;
+   |                ^^^^^^^^^^
+   |
+help: use `#[coroutine]` to make this closure a coroutine
+   |
+LL |     let _ = #[coroutine] || yield true;
+   |             ++++++++++++
+
 error[E0627]: yield expression outside of coroutine literal
   --> $DIR/feature-gate-coroutines.rs:5:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0627, E0658.
 For more information about an error, try `rustc --explain E0627`.
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs
index b3df2351b68..28dce8596d3 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.rs
+++ b/tests/ui/feature-gates/feature-gate-coroutines.rs
@@ -5,9 +5,11 @@ fn main() {
     yield true; //~ ERROR yield syntax is experimental
                 //~^ ERROR yield expression outside of coroutine literal
                 //[none]~^^ ERROR yield syntax is experimental
+                //~^^^ ERROR `yield` can only be used
 
     let _ = || yield true; //~ ERROR yield syntax is experimental
     //[none]~^ ERROR yield syntax is experimental
+    //~^^ ERROR `yield` can only be used
 }
 
 #[cfg(FALSE)]
diff --git a/tests/ui/feature-gates/feature-gate-inline_const.rs b/tests/ui/feature-gates/feature-gate-inline_const.rs
deleted file mode 100644
index 43ff90d234c..00000000000
--- a/tests/ui/feature-gates/feature-gate-inline_const.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let _ = const {
-        //~^ ERROR inline-const is experimental [E0658]
-        true
-    };
-}
diff --git a/tests/ui/feature-gates/feature-gate-inline_const.stderr b/tests/ui/feature-gates/feature-gate-inline_const.stderr
deleted file mode 100644
index 6cf675065f3..00000000000
--- a/tests/ui/feature-gates/feature-gate-inline_const.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: inline-const is experimental
-  --> $DIR/feature-gate-inline_const.rs:2:13
-   |
-LL |     let _ = const {
-   |             ^^^^^
-   |
-   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
-   = help: add `#![feature(inline_const)]` 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/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs
new file mode 100644
index 00000000000..313be6f28cd
--- /dev/null
+++ b/tests/ui/fn/fn_def_coercion.rs
@@ -0,0 +1,58 @@
+//! Test that coercing between function items of the same function,
+//! but with different generic args succeeds in typeck, but then fails
+//! in borrowck when the lifetimes can't actually be merged.
+
+fn foo<T>(t: T) -> T {
+    t
+}
+
+fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough
+    x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough
+    x = foo::<&'c ()>;
+    x(a);
+    x(b);
+    x(c);
+}
+
+fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let x = foo::<&'c ()>;
+    let _: &'c () = x(a); //~ ERROR lifetime may not live long enough
+}
+
+fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let x = foo::<&'a ()>;
+    let _: &'a () = x(c);
+}
+
+fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let mut x = foo::<&'c ()>;
+    x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough
+    x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough
+    x(a);
+    x(b);
+    x(c);
+}
+
+fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let x = match true {
+        true => foo::<&'b ()>,  //~ ERROR lifetime may not live long enough
+        false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
+    };
+    x(a);
+    x(b);
+    x(c);
+}
+
+fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+    let x = match true {
+        true => foo::<&'c ()>,
+        false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
+    };
+
+    x(a);
+    x(b); //~ ERROR lifetime may not live long enough
+    x(c);
+}
+
+fn main() {}
diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr
new file mode 100644
index 00000000000..ec4a1bde7fd
--- /dev/null
+++ b/tests/ui/fn/fn_def_coercion.stderr
@@ -0,0 +1,154 @@
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:10:17
+   |
+LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     let mut x = foo::<&'a ()>;
+   |                 ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:11:5
+   |
+LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     let mut x = foo::<&'a ()>;
+LL |     x = foo::<&'b ()>;
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:20:12
+   |
+LL | fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --      -- lifetime `'c` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     let x = foo::<&'c ()>;
+LL |     let _: &'c () = x(a);
+   |            ^^^^^^ type annotation requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:30:5
+   |
+LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     let mut x = foo::<&'c ()>;
+LL |     x = foo::<&'b ()>;
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:31:5
+   |
+LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+...
+LL |     x = foo::<&'a ()>;
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:39:17
+   |
+LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     let x = match true {
+LL |         true => foo::<&'b ()>,
+   |                 ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:40:18
+   |
+LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+...
+LL |         false => foo::<&'a ()>,
+   |                  ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:50:18
+   |
+LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --      -- lifetime `'c` defined here
+   |      |
+   |      lifetime `'a` defined here
+...
+LL |         false => foo::<&'a ()>,
+   |                  ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/fn_def_coercion.rs:54:5
+   |
+LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+...
+LL |     x(b);
+   |     ^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: add bound `'a: 'c`
+   = help: add bound `'b: 'a`
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/fn/fn_def_opaque_coercion.rs b/tests/ui/fn/fn_def_opaque_coercion.rs
new file mode 100644
index 00000000000..0a8810cf4f8
--- /dev/null
+++ b/tests/ui/fn/fn_def_opaque_coercion.rs
@@ -0,0 +1,69 @@
+//! Test that coercing between function items of the same function,
+//! but with different generic args works.
+
+//@check-pass
+
+#![feature(type_alias_impl_trait)]
+
+fn foo<T>(t: T) -> T {
+    t
+}
+
+type F = impl Sized;
+
+fn f(a: F) {
+    let mut x = foo::<F>;
+    x = foo::<()>;
+    x(a);
+    x(());
+}
+
+type G = impl Sized;
+
+fn g(a: G) {
+    let x = foo::<()>;
+    let _: () = x(a);
+}
+
+type H = impl Sized;
+
+fn h(a: H) {
+    let x = foo::<H>;
+    let _: H = x(());
+}
+
+type I = impl Sized;
+
+fn i(a: I) {
+    let mut x = foo::<()>;
+    x = foo::<I>;
+    x(a);
+    x(());
+}
+
+type J = impl Sized;
+
+fn j(a: J) {
+    let x = match true {
+        true => foo::<J>,
+        false => foo::<()>,
+    };
+    x(a);
+    x(());
+}
+
+fn k() -> impl Sized {
+    fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F {
+        f
+    }
+    let x = match true {
+        true => {
+            let f = foo;
+            bind(k(), f)
+        }
+        false => foo::<()>,
+    };
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs
index 81f20272867..30e25ca8edc 100644
--- a/tests/ui/fn/suggest-return-closure.rs
+++ b/tests/ui/fn/suggest-return-closure.rs
@@ -18,6 +18,7 @@ fn fn_mut() -> _ {
     //~| NOTE for more information on `Fn` traits and closure types
     let x = String::new();
     //~^ HELP: consider changing this to be mutable
+    //~| NOTE binding `x` declared here
     |c| { //~ NOTE: value captured here
         x.push(c);
         //~^ ERROR: does not live long enough
diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr
index 8e80a11fe1b..d276ce8be2b 100644
--- a/tests/ui/fn/suggest-return-closure.stderr
+++ b/tests/ui/fn/suggest-return-closure.stderr
@@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ {
    = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/suggest-return-closure.rs:31:13
+  --> $DIR/suggest-return-closure.rs:32:13
    |
 LL | fn fun() -> _ {
    |             ^
@@ -32,7 +32,7 @@ LL | fn fun() -> _ {
    = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/suggest-return-closure.rs:22:9
+  --> $DIR/suggest-return-closure.rs:23:9
    |
 LL |     let x = String::new();
    |         - help: consider changing this to be mutable: `mut x`
@@ -41,8 +41,11 @@ LL |         x.push(c);
    |         ^ cannot borrow as mutable
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/suggest-return-closure.rs:22:9
+  --> $DIR/suggest-return-closure.rs:23:9
    |
+LL |     let x = String::new();
+   |         - binding `x` declared here
+...
 LL |     |c| {
    |     --- value captured here
 LL |         x.push(c);
diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs
index 4f7a35e81b8..856e1297e58 100644
--- a/tests/ui/impl-trait/issues/issue-58504.rs
+++ b/tests/ui/impl-trait/issues/issue-58504.rs
@@ -3,7 +3,7 @@
 use std::ops::Coroutine;
 
 fn mk_gen() -> impl Coroutine<Return=!, Yield=()> {
-    || { loop { yield; } }
+    #[coroutine] || { loop { yield; } }
 }
 
 fn main() {
diff --git a/tests/ui/impl-trait/lifetimes.rs b/tests/ui/impl-trait/lifetimes.rs
index 93a4801fa40..df64b685eab 100644
--- a/tests/ui/impl-trait/lifetimes.rs
+++ b/tests/ui/impl-trait/lifetimes.rs
@@ -115,7 +115,7 @@ impl<'unnecessary_lifetime> MyVec {
     }
 
     fn coroutine_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized {
-        || yield
+        #[coroutine] || yield
     }
 }
 
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs
index ccd073b8070..422c2e439cf 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.rs
+++ b/tests/ui/impl-trait/normalize-tait-in-const.rs
@@ -3,7 +3,6 @@
 #![feature(type_alias_impl_trait)]
 #![feature(const_trait_impl)]
 #![feature(const_refs_to_cell)]
-#![feature(inline_const)]
 
 use std::marker::Destruct;
 
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 7ae8306d74d..fbd41b61730 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -1,11 +1,11 @@
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/normalize-tait-in-const.rs:25:42
+  --> $DIR/normalize-tait-in-const.rs:24:42
    |
 LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
    |                                          ^^^^^^^^^^^^^^^^^
 
 error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/normalize-tait-in-const.rs:26:5
+  --> $DIR/normalize-tait-in-const.rs:25:5
    |
 LL |     fun(filter_positive());
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL + #![feature(effects)]
    |
 
 error[E0493]: destructor of `F` cannot be evaluated at compile-time
-  --> $DIR/normalize-tait-in-const.rs:25:79
+  --> $DIR/normalize-tait-in-const.rs:24:79
    |
 LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
    |                                                                               ^^^ the destructor for this type cannot be evaluated in constant functions
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
index c0b399746ea..96db2030a40 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/recursive-coroutine-boxed.rs:14:23
+  --> $DIR/recursive-coroutine-boxed.rs:15:23
    |
 LL |         let mut gen = Box::pin(foo());
    |                       ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
@@ -13,7 +13,7 @@ LL |         let mut gen = Box::<T>::pin(foo());
    |                          +++++
 
 error[E0308]: mismatched types
-  --> $DIR/recursive-coroutine-boxed.rs:13:5
+  --> $DIR/recursive-coroutine-boxed.rs:14:18
    |
 LL |   fn foo() -> impl Coroutine<Yield = (), Return = ()> {
    |               ---------------------------------------
@@ -21,7 +21,8 @@ LL |   fn foo() -> impl Coroutine<Yield = (), Return = ()> {
    |               the expected opaque type
    |               expected `impl Coroutine<Yield = (), Return = ()>` because of return type
 ...
-LL | /     || {
+LL |       #[coroutine] || {
+   |  __________________^
 LL | |         let mut gen = Box::pin(foo());
 LL | |
 LL | |         let mut r = gen.as_mut().resume(());
@@ -31,7 +32,7 @@ LL | |     }
    | |_____^ types differ
    |
    = note: expected opaque type `impl Coroutine<Yield = (), Return = ()>`
-                found coroutine `{coroutine@$DIR/recursive-coroutine-boxed.rs:13:5: 13:7}`
+                found coroutine `{coroutine@$DIR/recursive-coroutine-boxed.rs:14:18: 14:20}`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
index 02c75be0f3a..24a77d73114 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
@@ -10,7 +10,8 @@ fn foo() -> impl Coroutine<Yield = (), Return = ()> {
     // FIXME(-Znext-solver): this fails with a mismatched types as the
     // hidden type of the opaque ends up as {type error}. We should not
     // emit errors for such goals.
-    || { //[next]~ ERROR mismatched types
+
+    #[coroutine] || { //[next]~ ERROR mismatched types
         let mut gen = Box::pin(foo());
         //[next]~^ ERROR type annotations needed
         let mut r = gen.as_mut().resume(());
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
index ee87c483d0d..9814187e179 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
@@ -1,8 +1,8 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:11:5
+  --> $DIR/recursive-coroutine-indirect.rs:11:18
    |
-LL |     move || {
-   |     ^^^^^^^
+LL |     #[coroutine] move || {
+   |                  ^^^^^^^
 LL |         let x = coroutine_hold();
    |             - recursive call here
 
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
index ee87c483d0d..9814187e179 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
@@ -1,8 +1,8 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:11:5
+  --> $DIR/recursive-coroutine-indirect.rs:11:18
    |
-LL |     move || {
-   |     ^^^^^^^
+LL |     #[coroutine] move || {
+   |                  ^^^^^^^
 LL |         let x = coroutine_hold();
    |             - recursive call here
 
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
index bba9792fe3c..cec2176049b 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
@@ -8,7 +8,7 @@
 #![feature(coroutines)]
 #![allow(unconditional_recursion)]
 fn coroutine_hold() -> impl Sized {
-    move || { //~ ERROR recursion in a coroutine requires boxing
+    #[coroutine] move || { //~ ERROR recursion in a coroutine requires boxing
         let x = coroutine_hold();
         yield;
         x;
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index 432f80a1763..8b9dac0e29b 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -57,6 +57,8 @@ fn coroutine_sig() -> impl Sized {
 fn coroutine_capture() -> impl Sized {
     //~^ ERROR
     let x = coroutine_capture();
+
+    #[coroutine]
     move || {
         yield;
         x;
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index d5b8c531fd6..2d2731e4368 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -98,10 +98,10 @@ LL | |         yield;
 LL | |         x;
    | |         - coroutine captures itself here
 LL | |     }
-   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:60:5: 60:12}`
+   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:66:35
+  --> $DIR/recursive-impl-trait-type-indirect.rs:68:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
    |                                   ^^^^^^^^^^ recursive opaque type
@@ -110,7 +110,7 @@ LL |     (substs_change::<&T>(),)
    |     ------------------------ returning here with type `(impl Sized,)`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:76:26
+  --> $DIR/recursive-impl-trait-type-indirect.rs:78:26
    |
 LL | fn mutual_recursion() -> impl Sync {
    |                          ^^^^^^^^^ recursive opaque type
@@ -122,7 +122,7 @@ LL | fn mutual_recursion_b() -> impl Sized {
    |                            ---------- returning this opaque type `impl Sized`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:81:28
+  --> $DIR/recursive-impl-trait-type-indirect.rs:83:28
    |
 LL | fn mutual_recursion() -> impl Sync {
    |                          --------- returning this opaque type `impl Sync`
diff --git a/tests/ui/inline-const/const-expr-array-init.rs b/tests/ui/inline-const/const-expr-array-init.rs
index 075c27c1cc9..eb126b61f2d 100644
--- a/tests/ui/inline-const/const-expr-array-init.rs
+++ b/tests/ui/inline-const/const-expr-array-init.rs
@@ -1,7 +1,5 @@
 //@ build-pass
 
-#![feature(inline_const)]
-
 use std::cell::Cell;
 
 fn main() {
diff --git a/tests/ui/inline-const/const-expr-basic.rs b/tests/ui/inline-const/const-expr-basic.rs
index 6a19cc656d0..7f769d2b5c3 100644
--- a/tests/ui/inline-const/const-expr-basic.rs
+++ b/tests/ui/inline-const/const-expr-basic.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(inline_const)]
-
 fn foo() -> i32 {
     const {
         let x = 5 + 10;
diff --git a/tests/ui/inline-const/const-expr-generic-err.rs b/tests/ui/inline-const/const-expr-generic-err.rs
index 3c4bbcb3dc9..3249e826a96 100644
--- a/tests/ui/inline-const/const-expr-generic-err.rs
+++ b/tests/ui/inline-const/const-expr-generic-err.rs
@@ -1,5 +1,4 @@
 //@ build-fail
-#![feature(inline_const)]
 
 fn foo<T>() {
     const { assert!(std::mem::size_of::<T>() == 0); } //~ ERROR E0080
diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr
index 7331c7f18e9..dcd6b62bbfc 100644
--- a/tests/ui/inline-const/const-expr-generic-err.stderr
+++ b/tests/ui/inline-const/const-expr-generic-err.stderr
@@ -1,37 +1,37 @@
 error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
-  --> $DIR/const-expr-generic-err.rs:5:13
+  --> $DIR/const-expr-generic-err.rs:4:13
    |
 LL |     const { assert!(std::mem::size_of::<T>() == 0); }
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:5:13
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::<T>() == 0', $DIR/const-expr-generic-err.rs:4:13
    |
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant encountered
-  --> $DIR/const-expr-generic-err.rs:5:5
+  --> $DIR/const-expr-generic-err.rs:4:5
    |
 LL |     const { assert!(std::mem::size_of::<T>() == 0); }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: the above error was encountered while instantiating `fn foo::<i32>`
-  --> $DIR/const-expr-generic-err.rs:13:5
+  --> $DIR/const-expr-generic-err.rs:12:5
    |
 LL |     foo::<i32>();
    |     ^^^^^^^^^^^^
 
 error[E0080]: evaluation of `bar::<0>::{constant#0}` failed
-  --> $DIR/const-expr-generic-err.rs:9:13
+  --> $DIR/const-expr-generic-err.rs:8:13
    |
 LL |     const { N - 1 }
    |             ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
 
 note: erroneous constant encountered
-  --> $DIR/const-expr-generic-err.rs:9:5
+  --> $DIR/const-expr-generic-err.rs:8:5
    |
 LL |     const { N - 1 }
    |     ^^^^^^^^^^^^^^^
 
 note: erroneous constant encountered
-  --> $DIR/const-expr-generic-err.rs:9:5
+  --> $DIR/const-expr-generic-err.rs:8:5
    |
 LL |     const { N - 1 }
    |     ^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL |     const { N - 1 }
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn bar::<0>`
-  --> $DIR/const-expr-generic-err.rs:14:5
+  --> $DIR/const-expr-generic-err.rs:13:5
    |
 LL |     bar::<0>();
    |     ^^^^^^^^^^
diff --git a/tests/ui/inline-const/const-expr-generic-err2.rs b/tests/ui/inline-const/const-expr-generic-err2.rs
index e097cbe9dd6..49cbdbfda5d 100644
--- a/tests/ui/inline-const/const-expr-generic-err2.rs
+++ b/tests/ui/inline-const/const-expr-generic-err2.rs
@@ -1,5 +1,3 @@
-#![feature(inline_const)]
-
 fn foo<T>() {
     let _ = [0u8; const { std::mem::size_of::<T>() }];
     //~^ ERROR: constant expression depends on a generic parameter
diff --git a/tests/ui/inline-const/const-expr-generic-err2.stderr b/tests/ui/inline-const/const-expr-generic-err2.stderr
index 5876a6c9e19..c6d77593c46 100644
--- a/tests/ui/inline-const/const-expr-generic-err2.stderr
+++ b/tests/ui/inline-const/const-expr-generic-err2.stderr
@@ -1,5 +1,5 @@
 error: constant expression depends on a generic parameter
-  --> $DIR/const-expr-generic-err2.rs:4:19
+  --> $DIR/const-expr-generic-err2.rs:2:19
    |
 LL |     let _ = [0u8; const { std::mem::size_of::<T>() }];
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/inline-const/const-expr-generic.rs b/tests/ui/inline-const/const-expr-generic.rs
index e634e1d4a47..0c33b02d3a2 100644
--- a/tests/ui/inline-const/const-expr-generic.rs
+++ b/tests/ui/inline-const/const-expr-generic.rs
@@ -1,5 +1,4 @@
 //@ check-pass
-#![feature(inline_const)]
 
 fn foo<T>() -> usize {
     const { std::mem::size_of::<T>() }
diff --git a/tests/ui/inline-const/const-expr-inference.rs b/tests/ui/inline-const/const-expr-inference.rs
index f3b97d3430e..99cea3204a1 100644
--- a/tests/ui/inline-const/const-expr-inference.rs
+++ b/tests/ui/inline-const/const-expr-inference.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(inline_const)]
-
 pub fn todo<T>() -> T {
     const { todo!() }
 }
diff --git a/tests/ui/inline-const/const-expr-lifetime-err.rs b/tests/ui/inline-const/const-expr-lifetime-err.rs
index 0a032a7338a..df1e5fcb473 100644
--- a/tests/ui/inline-const/const-expr-lifetime-err.rs
+++ b/tests/ui/inline-const/const-expr-lifetime-err.rs
@@ -1,5 +1,4 @@
 #![feature(const_mut_refs)]
-#![feature(inline_const)]
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr
index 75877bc093a..f97e2d25e6c 100644
--- a/tests/ui/inline-const/const-expr-lifetime-err.stderr
+++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `y` does not live long enough
-  --> $DIR/const-expr-lifetime-err.rs:23:30
+  --> $DIR/const-expr-lifetime-err.rs:22:30
    |
 LL | fn foo<'a>() {
    |        -- lifetime `'a` defined here
diff --git a/tests/ui/inline-const/const-expr-lifetime.rs b/tests/ui/inline-const/const-expr-lifetime.rs
index 5dac17645d7..071e724a0fa 100644
--- a/tests/ui/inline-const/const-expr-lifetime.rs
+++ b/tests/ui/inline-const/const-expr-lifetime.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 
 #![feature(const_mut_refs)]
-#![feature(inline_const)]
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/inline-const/const-expr-macro.rs b/tests/ui/inline-const/const-expr-macro.rs
index bf3cb3c3320..cf07eb12f5a 100644
--- a/tests/ui/inline-const/const-expr-macro.rs
+++ b/tests/ui/inline-const/const-expr-macro.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(inline_const)]
-
 macro_rules! do_const_block{
     ($val:block) => { const $val }
 }
diff --git a/tests/ui/inline-const/const-expr-reference.rs b/tests/ui/inline-const/const-expr-reference.rs
index b3753b0d371..208271e37c3 100644
--- a/tests/ui/inline-const/const-expr-reference.rs
+++ b/tests/ui/inline-const/const-expr-reference.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(inline_const)]
-
 const fn bar() -> i32 {
     const {
         2 + 3
diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs
index f909e68e7be..590c426c773 100644
--- a/tests/ui/inline-const/const-match-pat-lifetime.rs
+++ b/tests/ui/inline-const/const-match-pat-lifetime.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 
 #![feature(const_mut_refs)]
-#![feature(inline_const)]
 #![feature(inline_const_pat)]
 
 use std::marker::PhantomData;
diff --git a/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs
index a1c3c61484a..e0a889ac347 100644
--- a/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs
+++ b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(inline_const)]
-
 fn main() {
     let _my_usize = const {
         let a = 10_usize;
diff --git a/tests/ui/inline-const/expr-unsafe-err.rs b/tests/ui/inline-const/expr-unsafe-err.rs
index a05a2945168..d53d84b944f 100644
--- a/tests/ui/inline-const/expr-unsafe-err.rs
+++ b/tests/ui/inline-const/expr-unsafe-err.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const)]
 const unsafe fn require_unsafe() -> usize {
     1
 }
diff --git a/tests/ui/inline-const/expr-unsafe-err.stderr b/tests/ui/inline-const/expr-unsafe-err.stderr
index 45f850d1f99..13a408b971c 100644
--- a/tests/ui/inline-const/expr-unsafe-err.stderr
+++ b/tests/ui/inline-const/expr-unsafe-err.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
-  --> $DIR/expr-unsafe-err.rs:8:9
+  --> $DIR/expr-unsafe-err.rs:7:9
    |
 LL |         require_unsafe();
    |         ^^^^^^^^^^^^^^^^ call to unsafe function
diff --git a/tests/ui/inline-const/expr-unsafe.rs b/tests/ui/inline-const/expr-unsafe.rs
index f9d1450503e..cdd101f3e08 100644
--- a/tests/ui/inline-const/expr-unsafe.rs
+++ b/tests/ui/inline-const/expr-unsafe.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
 #![warn(unused_unsafe)]
-#![feature(inline_const)]
+
 const unsafe fn require_unsafe() -> usize { 1 }
 
 fn main() {
diff --git a/tests/ui/inline-const/expr-with-block-err.rs b/tests/ui/inline-const/expr-with-block-err.rs
index f7547742ddc..6f850757558 100644
--- a/tests/ui/inline-const/expr-with-block-err.rs
+++ b/tests/ui/inline-const/expr-with-block-err.rs
@@ -1,5 +1,3 @@
-#![feature(inline_const)]
-
 fn main() {
     const { 2 } - const { 1 };
     //~^ ERROR mismatched types
diff --git a/tests/ui/inline-const/expr-with-block-err.stderr b/tests/ui/inline-const/expr-with-block-err.stderr
index a46d7395045..f127c11e9b7 100644
--- a/tests/ui/inline-const/expr-with-block-err.stderr
+++ b/tests/ui/inline-const/expr-with-block-err.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/expr-with-block-err.rs:4:13
+  --> $DIR/expr-with-block-err.rs:2:13
    |
 LL |     const { 2 } - const { 1 };
    |             ^ expected `()`, found integer
diff --git a/tests/ui/inline-const/expr-with-block.rs b/tests/ui/inline-const/expr-with-block.rs
index 07a1c9a10f5..a32afbcffad 100644
--- a/tests/ui/inline-const/expr-with-block.rs
+++ b/tests/ui/inline-const/expr-with-block.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![feature(inline_const)]
+
 fn main() {
     match true {
         true => const {}
diff --git a/tests/ui/inline-const/instance-doesnt-depend-on-type.rs b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs
index e69106a43af..c53aab60b06 100644
--- a/tests/ui/inline-const/instance-doesnt-depend-on-type.rs
+++ b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 // issue: 114660
 
-#![feature(inline_const)]
-
 fn main() {
     const { core::mem::transmute::<u8, u8> };
     // Don't resolve the instance of this inline constant to be an intrinsic,
diff --git a/tests/ui/inline-const/interpolated.rs b/tests/ui/inline-const/interpolated.rs
index 582900e7aa0..38ed2a042e0 100644
--- a/tests/ui/inline-const/interpolated.rs
+++ b/tests/ui/inline-const/interpolated.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(inline_const)]
-
 // This used to be unsupported since the parser first tries to check if we have
 // any nested items, and then checks for statements (and expressions). The heuristic
 // that we were using to detect the beginning of a const item was incorrect, so
diff --git a/tests/ui/inline-const/promotion.rs b/tests/ui/inline-const/promotion.rs
index 242959c6b51..2cfb8a0d19f 100644
--- a/tests/ui/inline-const/promotion.rs
+++ b/tests/ui/inline-const/promotion.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const)]
 #![allow(arithmetic_overflow, unconditional_panic)]
 
 // The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
diff --git a/tests/ui/inline-const/promotion.stderr b/tests/ui/inline-const/promotion.stderr
index 7f06b97818b..4e914c9e087 100644
--- a/tests/ui/inline-const/promotion.stderr
+++ b/tests/ui/inline-const/promotion.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promotion.rs:17:37
+  --> $DIR/promotion.rs:16:37
    |
 LL |             let _x: &'static i32 = &div_by_zero();
    |                     ------------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs
index 3de0ab2a0c0..8f640e933d0 100644
--- a/tests/ui/inline-const/required-const.rs
+++ b/tests/ui/inline-const/required-const.rs
@@ -1,6 +1,5 @@
 //@ build-fail
 //@ compile-flags: -Zmir-opt-level=3
-#![feature(inline_const)]
 
 fn foo<T>() {
     if false {
diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr
index 2a13d18547c..6ca4c250223 100644
--- a/tests/ui/inline-const/required-const.stderr
+++ b/tests/ui/inline-const/required-const.stderr
@@ -1,13 +1,13 @@
 error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
-  --> $DIR/required-const.rs:7:17
+  --> $DIR/required-const.rs:6:17
    |
 LL |         const { panic!() }
-   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17
+   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:6:17
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant encountered
-  --> $DIR/required-const.rs:7:9
+  --> $DIR/required-const.rs:6:9
    |
 LL |         const { panic!() }
    |         ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/invalid-compile-flags/print.rs b/tests/ui/invalid-compile-flags/print.rs
new file mode 100644
index 00000000000..0d0a9d22750
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/print.rs
@@ -0,0 +1 @@
+//@ compile-flags: --print yyyy
diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr
new file mode 100644
index 00000000000..0a032aabdfe
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/print.stderr
@@ -0,0 +1,4 @@
+error: unknown print request: `yyyy`
+  |
+  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+
diff --git a/tests/ui/issues/issue-17385.stderr b/tests/ui/issues/issue-17385.stderr
index 988db0fb1fc..3c451a859e9 100644
--- a/tests/ui/issues/issue-17385.stderr
+++ b/tests/ui/issues/issue-17385.stderr
@@ -12,7 +12,10 @@ note: if `X` implemented `Clone`, you could clone the value
   --> $DIR/issue-17385.rs:1:1
    |
 LL | struct X(isize);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     drop(foo);
+   |          --- you could clone this value
 
 error[E0382]: use of moved value: `e`
   --> $DIR/issue-17385.rs:25:11
@@ -28,7 +31,10 @@ note: if `Enum` implemented `Clone`, you could clone the value
   --> $DIR/issue-17385.rs:3:1
    |
 LL | enum Enum {
-   | ^^^^^^^^^
+   | ^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     drop(e);
+   |          - you could clone this value
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-24357.rs b/tests/ui/issues/issue-24357.rs
index d1a9e37251e..63c061594d8 100644
--- a/tests/ui/issues/issue-24357.rs
+++ b/tests/ui/issues/issue-24357.rs
@@ -1,10 +1,12 @@
 struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value
+//~^ NOTE consider implementing `Clone` for this type
 fn main() {
    let x = NoCopy;
    //~^ NOTE move occurs because `x` has type `NoCopy`
    let f = move || { let y = x; };
    //~^ NOTE value moved into closure here
    //~| NOTE variable moved due to use in closure
+   //~| NOTE you could clone this value
    let z = x;
    //~^ ERROR use of moved value: `x`
    //~| NOTE value used here after move
diff --git a/tests/ui/issues/issue-24357.stderr b/tests/ui/issues/issue-24357.stderr
index 6d50eea7e21..2d85077fe4c 100644
--- a/tests/ui/issues/issue-24357.stderr
+++ b/tests/ui/issues/issue-24357.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/issue-24357.rs:8:12
+  --> $DIR/issue-24357.rs:10:12
    |
 LL |    let x = NoCopy;
    |        - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
@@ -16,7 +16,10 @@ note: if `NoCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-24357.rs:1:1
    |
 LL | struct NoCopy;
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |    let f = move || { let y = x; };
+   |                              - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-4335.stderr b/tests/ui/issues/issue-4335.stderr
index 8b4aff54dc3..14b5cfa9f9a 100644
--- a/tests/ui/issues/issue-4335.stderr
+++ b/tests/ui/issues/issue-4335.stderr
@@ -7,6 +7,14 @@ LL |     id(Box::new(|| *v))
    |                 -- ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait
    |                 |
    |                 captured by this `FnMut` closure
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/issue-4335.rs:5:10
+   |
+LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
+   |          ^ consider constraining this type parameter with `Clone`
+LL |     id(Box::new(|| *v))
+   |                    -- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs
index a2461cff932..3bc87b9d480 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.rs
+++ b/tests/ui/lifetimes/unusual-rib-combinations.rs
@@ -1,5 +1,3 @@
-#![feature(inline_const)]
-
 struct S<'a>(&'a u8);
 fn foo() {}
 
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 320e64a2f77..2857fc72ea1 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -1,11 +1,11 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/unusual-rib-combinations.rs:24:15
+  --> $DIR/unusual-rib-combinations.rs:22:15
    |
 LL | fn d<const C: S>() {}
    |               ^ expected named lifetime parameter
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/unusual-rib-combinations.rs:29:22
+  --> $DIR/unusual-rib-combinations.rs:27:22
    |
 LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
    |                      ^^ the type must not depend on the parameter `'a`
@@ -13,25 +13,25 @@ LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
    = note: lifetime parameters may not be used in the type of const parameters
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:7:16
+  --> $DIR/unusual-rib-combinations.rs:5:16
    |
 LL | fn a() -> [u8; foo::()] {
    |                ^^^^^^^ only `Fn` traits may use parentheses
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:14:15
+  --> $DIR/unusual-rib-combinations.rs:12:15
    |
 LL | fn b<const C: u8()>() {}
    |               ^^^^ only `Fn` traits may use parentheses
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:18:10
+  --> $DIR/unusual-rib-combinations.rs:16:10
    |
 LL | fn c<T = u8()>() {}
    |          ^^^^ only `Fn` traits may use parentheses
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/unusual-rib-combinations.rs:18:6
+  --> $DIR/unusual-rib-combinations.rs:16:6
    |
 LL | fn c<T = u8()>() {}
    |      ^^^^^^^^
@@ -41,7 +41,7 @@ LL | fn c<T = u8()>() {}
    = note: `#[deny(invalid_type_param_default)]` on by default
 
 error[E0308]: mismatched types
-  --> $DIR/unusual-rib-combinations.rs:7:16
+  --> $DIR/unusual-rib-combinations.rs:5:16
    |
 LL | fn a() -> [u8; foo::()] {
    |                ^^^^^^^ expected `usize`, found fn item
@@ -50,7 +50,7 @@ LL | fn a() -> [u8; foo::()] {
            found fn item `fn() {foo}`
 
 error: `S<'_>` is forbidden as the type of a const generic parameter
-  --> $DIR/unusual-rib-combinations.rs:24:15
+  --> $DIR/unusual-rib-combinations.rs:22:15
    |
 LL | fn d<const C: S>() {}
    |               ^
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
index e87afe9094c..2d1822a54ac 100644
--- a/tests/ui/lint/invalid_from_utf8.rs
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 
-#![feature(inline_const)]
 #![feature(concat_bytes)]
 
 #![warn(invalid_from_utf8_unchecked)]
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
index 884165d4f12..07616e11801 100644
--- a/tests/ui/lint/invalid_from_utf8.stderr
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:21:9
+  --> $DIR/invalid_from_utf8.rs:20:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -7,13 +7,13 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112
    |                                                the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:6:9
+  --> $DIR/invalid_from_utf8.rs:5:9
    |
 LL | #![warn(invalid_from_utf8_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:23:9
+  --> $DIR/invalid_from_utf8.rs:22:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -21,7 +21,7 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i',
    |                                                the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:41:9
+  --> $DIR/invalid_from_utf8.rs:40:9
    |
 LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -29,7 +29,7 @@ LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:43:9
+  --> $DIR/invalid_from_utf8.rs:42:9
    |
 LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -37,7 +37,7 @@ LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:45:9
+  --> $DIR/invalid_from_utf8.rs:44:9
    |
 LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
@@ -45,7 +45,7 @@ LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:47:9
+  --> $DIR/invalid_from_utf8.rs:46:9
    |
 LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -53,7 +53,7 @@ LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:64:9
+  --> $DIR/invalid_from_utf8.rs:63:9
    |
 LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -61,13 +61,13 @@ LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |                                      the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:7:9
+  --> $DIR/invalid_from_utf8.rs:6:9
    |
 LL | #![warn(invalid_from_utf8)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:66:9
+  --> $DIR/invalid_from_utf8.rs:65:9
    |
 LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -75,7 +75,7 @@ LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p'
    |                                      the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:84:9
+  --> $DIR/invalid_from_utf8.rs:83:9
    |
 LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -83,7 +83,7 @@ LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:86:9
+  --> $DIR/invalid_from_utf8.rs:85:9
    |
 LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -91,7 +91,7 @@ LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y'])
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:88:9
+  --> $DIR/invalid_from_utf8.rs:87:9
    |
 LL |         std::str::from_utf8(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^-------------^
@@ -99,7 +99,7 @@ LL |         std::str::from_utf8(b"cl\x82ippy");
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:90:9
+  --> $DIR/invalid_from_utf8.rs:89:9
    |
 LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -107,7 +107,7 @@ LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:97:5
+  --> $DIR/invalid_from_utf8.rs:96:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -115,7 +115,7 @@ LL |     std::str::from_utf8_mut(&mut a);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:101:5
+  --> $DIR/invalid_from_utf8.rs:100:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -124,7 +124,7 @@ LL |     std::str::from_utf8_mut(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:104:5
+  --> $DIR/invalid_from_utf8.rs:103:5
    |
 LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
    |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -132,7 +132,7 @@ LL |     std::str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:107:5
+  --> $DIR/invalid_from_utf8.rs:106:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -140,7 +140,7 @@ LL |     std::str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:110:5
+  --> $DIR/invalid_from_utf8.rs:109:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -148,7 +148,7 @@ LL |     std::str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:113:5
+  --> $DIR/invalid_from_utf8.rs:112:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -156,7 +156,7 @@ LL |     std::str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with a invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:116:5
+  --> $DIR/invalid_from_utf8.rs:115:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
index 2f3c5d9ea29..ec409925d72 100644
--- a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
+++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
@@ -1,7 +1,8 @@
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 fn main() {
-    let _coroutine = || {
+    let _coroutine = #[coroutine]
+    || {
         yield ((), ((), ()));
         yield ((), ());
         //~^ ERROR mismatched types
diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
index 3adf26cfee2..102eadd7aff 100644
--- a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
+++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/tuple-mismatch.rs:6:20
+  --> $DIR/tuple-mismatch.rs:7:20
    |
 LL |         yield ((), ());
    |                    ^^ expected `((), ())`, found `()`
diff --git a/tests/ui/lint/non-local-defs/consts.rs b/tests/ui/lint/non-local-defs/consts.rs
index 2652447dcf5..d8a497e43e5 100644
--- a/tests/ui/lint/non-local-defs/consts.rs
+++ b/tests/ui/lint/non-local-defs/consts.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ rustc-env:CARGO_CRATE_NAME=non_local_def
 
-#![feature(inline_const)]
-
 struct Test;
 
 trait Uto {}
diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr
index 5563ea9d93f..d15b452b004 100644
--- a/tests/ui/lint/non-local-defs/consts.stderr
+++ b/tests/ui/lint/non-local-defs/consts.stderr
@@ -1,5 +1,5 @@
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:15:5
+  --> $DIR/consts.rs:13:5
    |
 LL | const Z: () = {
    |       - help: use a const-anon item to suppress this lint: `_`
@@ -14,7 +14,7 @@ LL |     impl Uto for &Test {}
    = note: `#[warn(non_local_definitions)]` on by default
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:26:5
+  --> $DIR/consts.rs:24:5
    |
 LL |     impl Uto2 for Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     impl Uto2 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:34:5
+  --> $DIR/consts.rs:32:5
    |
 LL |     impl Uto3 for Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     impl Uto3 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:45:5
+  --> $DIR/consts.rs:43:5
    |
 LL | /     impl Test {
 LL | |
@@ -50,7 +50,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:52:9
+  --> $DIR/consts.rs:50:9
    |
 LL | /         impl Test {
 LL | |
@@ -64,7 +64,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:61:9
+  --> $DIR/consts.rs:59:9
    |
 LL | /         impl Test {
 LL | |
@@ -78,7 +78,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:74:9
+  --> $DIR/consts.rs:72:9
    |
 LL |         impl Uto9 for Test {}
    |         ^^^^^^^^^^^^^^^^^^^^^
@@ -89,7 +89,7 @@ LL |         impl Uto9 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/consts.rs:81:9
+  --> $DIR/consts.rs:79:9
    |
 LL |         impl Uto10 for Test {}
    |         ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.rs b/tests/ui/lint/non-local-defs/from-local-for-global.rs
index 0ab3a6b1988..fea9679d737 100644
--- a/tests/ui/lint/non-local-defs/from-local-for-global.rs
+++ b/tests/ui/lint/non-local-defs/from-local-for-global.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 //@ edition:2021
 
-#![feature(inline_const)]
-
 struct Cat;
 struct Wrap<T>(T);
 
diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr
index bd592a72157..0cd385049aa 100644
--- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr
+++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr
@@ -1,5 +1,5 @@
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/from-local-for-global.rs:10:5
+  --> $DIR/from-local-for-global.rs:8:5
    |
 LL | /     impl From<Cat> for () {
 LL | |
@@ -16,7 +16,7 @@ LL | |     }
    = note: `#[warn(non_local_definitions)]` on by default
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/from-local-for-global.rs:20:5
+  --> $DIR/from-local-for-global.rs:18:5
    |
 LL | /     impl From<Wrap<Wrap<Elephant>>> for () {
 LL | |
@@ -32,7 +32,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/from-local-for-global.rs:34:5
+  --> $DIR/from-local-for-global.rs:32:5
    |
 LL |     impl StillNonLocal for &Foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ LL |     impl StillNonLocal for &Foo {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/from-local-for-global.rs:42:5
+  --> $DIR/from-local-for-global.rs:40:5
    |
 LL | /     impl From<Local1> for GlobalSameFunction {
 LL | |
@@ -59,7 +59,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/from-local-for-global.rs:50:5
+  --> $DIR/from-local-for-global.rs:48:5
    |
 LL | /     impl From<Local2> for GlobalSameFunction {
 LL | |
diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs
index c5dd281cb4e..12e2bcb898c 100644
--- a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs
+++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs
@@ -1,12 +1,12 @@
 #![feature(coroutine_trait)]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![deny(unused_braces, unused_parens)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
-    let mut x = |_| {
+    let mut x = #[coroutine] |_| {
         while let Some(_) = (yield) {}
         while let Some(_) = {yield} {}
 
diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs
index 9106edee653..4633038cc9b 100644
--- a/tests/ui/lint/unused/unused-closure.rs
+++ b/tests/ui/lint/unused/unused-closure.rs
@@ -2,7 +2,7 @@
 //@ edition:2018
 
 #![feature(async_closure)]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![deny(unused_must_use)]
 
 fn unused() {
@@ -26,7 +26,7 @@ fn unused() {
 
 fn ignored() {
     let _ = || {};
-    let _ = || yield 42;
+    let _ = #[coroutine] || yield 42;
 }
 
 fn main() {
diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs
index 7898b978882..f76efba3e6b 100644
--- a/tests/ui/liveness/liveness-upvars.rs
+++ b/tests/ui/liveness/liveness-upvars.rs
@@ -1,6 +1,6 @@
 //@ edition:2018
 //@ check-pass
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![warn(unused)]
 #![allow(unreachable_code)]
 
@@ -131,7 +131,7 @@ pub fn async_coroutine() {
 
 pub fn coroutine() {
     let mut s: u32 = 0;
-    let _ = |_| {
+    let _ = #[coroutine] |_| {
         s = 0;
         yield ();
         s = 1; //~ WARN value assigned to `s` is never read
diff --git a/tests/ui/loops/dont-suggest-break-thru-item.rs b/tests/ui/loops/dont-suggest-break-thru-item.rs
index 34a9a57bfed..b4262ec02bf 100644
--- a/tests/ui/loops/dont-suggest-break-thru-item.rs
+++ b/tests/ui/loops/dont-suggest-break-thru-item.rs
@@ -1,7 +1,5 @@
 //@ edition:2021
 
-#![feature(inline_const)]
-
 fn closure() {
     loop {
         let closure = || {
diff --git a/tests/ui/loops/dont-suggest-break-thru-item.stderr b/tests/ui/loops/dont-suggest-break-thru-item.stderr
index c84a98198f5..642578ade60 100644
--- a/tests/ui/loops/dont-suggest-break-thru-item.stderr
+++ b/tests/ui/loops/dont-suggest-break-thru-item.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-break-thru-item.rs:9:17
+  --> $DIR/dont-suggest-break-thru-item.rs:7:17
    |
 LL | /             if true {
 LL | |                 Err(1)
@@ -17,7 +17,7 @@ LL |                 return Err(1);
    |                 ++++++       +
 
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-break-thru-item.rs:23:17
+  --> $DIR/dont-suggest-break-thru-item.rs:21:17
    |
 LL | /             if true {
 LL | |                 Err(1)
@@ -35,7 +35,7 @@ LL |                 return Err(1);
    |                 ++++++       +
 
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-break-thru-item.rs:37:17
+  --> $DIR/dont-suggest-break-thru-item.rs:35:17
    |
 LL | /             if true {
 LL | |                 Err(1)
@@ -48,7 +48,7 @@ LL | |             }
                    found enum `Result<_, {integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-break-thru-item.rs:49:17
+  --> $DIR/dont-suggest-break-thru-item.rs:47:17
    |
 LL | /             if true {
 LL | |                 Err(1)
diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr
index 838eaffb5a0..162d7ac031a 100644
--- a/tests/ui/mir/issue-102389.stderr
+++ b/tests/ui/mir/issue-102389.stderr
@@ -8,7 +8,10 @@ note: if `Enum` implemented `Clone`, you could clone the value
   --> $DIR/issue-102389.rs:1:1
    |
 LL | enum Enum { A, B, C }
-   | ^^^^^^^^^
+   | ^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     array[*inbounds as usize]
+   |           --------- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/borrow-closures-instead-of-move.rs b/tests/ui/moves/borrow-closures-instead-of-move.rs
index 51771ced7f2..e4bca54e995 100644
--- a/tests/ui/moves/borrow-closures-instead-of-move.rs
+++ b/tests/ui/moves/borrow-closures-instead-of-move.rs
@@ -1,4 +1,4 @@
-fn takes_fn(f: impl Fn()) {
+fn takes_fn(f: impl Fn()) { //~ HELP if `impl Fn()` implemented `Clone`
     loop {
         takes_fnonce(f);
         //~^ ERROR use of moved value
@@ -6,7 +6,7 @@ fn takes_fn(f: impl Fn()) {
     }
 }
 
-fn takes_fn_mut(m: impl FnMut()) {
+fn takes_fn_mut(m: impl FnMut()) { //~ HELP if `impl FnMut()` implemented `Clone`
     if maybe() {
         takes_fnonce(m);
         //~^ HELP consider mutably borrowing
diff --git a/tests/ui/moves/borrow-closures-instead-of-move.stderr b/tests/ui/moves/borrow-closures-instead-of-move.stderr
index 9a84ddef7e6..ab6ff417efb 100644
--- a/tests/ui/moves/borrow-closures-instead-of-move.stderr
+++ b/tests/ui/moves/borrow-closures-instead-of-move.stderr
@@ -15,6 +15,14 @@ LL | fn takes_fnonce(_: impl FnOnce()) {}
    |    ------------    ^^^^^^^^^^^^^ this parameter takes ownership of the value
    |    |
    |    in this function
+help: if `impl Fn()` implemented `Clone`, you could clone the value
+  --> $DIR/borrow-closures-instead-of-move.rs:1:16
+   |
+LL | fn takes_fn(f: impl Fn()) {
+   |                ^^^^^^^^^ consider constraining this type parameter with `Clone`
+LL |     loop {
+LL |         takes_fnonce(f);
+   |                      - you could clone this value
 help: consider borrowing `f`
    |
 LL |         takes_fnonce(&f);
@@ -39,6 +47,14 @@ LL | fn takes_fnonce(_: impl FnOnce()) {}
    |    ------------    ^^^^^^^^^^^^^ this parameter takes ownership of the value
    |    |
    |    in this function
+help: if `impl FnMut()` implemented `Clone`, you could clone the value
+  --> $DIR/borrow-closures-instead-of-move.rs:9:20
+   |
+LL | fn takes_fn_mut(m: impl FnMut()) {
+   |                    ^^^^^^^^^^^^ consider constraining this type parameter with `Clone`
+LL |     if maybe() {
+LL |         takes_fnonce(m);
+   |                      - you could clone this value
 help: consider mutably borrowing `m`
    |
 LL |         takes_fnonce(&mut m);
diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs
index 86f389cb3af..8f2e01bdf1a 100644
--- a/tests/ui/moves/issue-72649-uninit-in-loop.rs
+++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs
@@ -7,6 +7,10 @@ struct NonCopy;
 //~| NOTE if `NonCopy` implemented `Clone`
 //~| NOTE if `NonCopy` implemented `Clone`
 //~| NOTE if `NonCopy` implemented `Clone`
+//~| NOTE consider implementing `Clone` for this type
+//~| NOTE consider implementing `Clone` for this type
+//~| NOTE consider implementing `Clone` for this type
+//~| NOTE consider implementing `Clone` for this type
 
 fn good() {
     loop {
@@ -21,6 +25,7 @@ fn moved_here_1() {
         //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
         let _used = value;
         //~^ NOTE value moved here
+        //~| NOTE you could clone this value
         let _used2 = value; //~ ERROR use of moved value: `value`
         //~^ NOTE value used here after move
     }
@@ -32,6 +37,7 @@ fn moved_here_2() {
     loop { //~ NOTE inside of this loop
         let _used = value;
         //~^ NOTE value moved here
+        //~| NOTE you could clone this value
         loop {
             let _used2 = value; //~ ERROR use of moved value: `value`
             //~^ NOTE value used here after move
@@ -45,6 +51,7 @@ fn moved_loop_1() {
     loop { //~ NOTE inside of this loop
         let _used = value; //~ ERROR use of moved value: `value`
         //~^ NOTE value moved here, in previous iteration of loop
+        //~| NOTE you could clone this value
     }
 }
 
@@ -56,6 +63,7 @@ fn moved_loop_2() {
     loop { //~ NOTE inside of this loop
         let _used2 = value; //~ ERROR use of moved value: `value`
         //~^ NOTE value moved here, in previous iteration of loop
+        //~| NOTE you could clone this value
     }
 }
 
diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
index a613f35a35e..3a93769ac45 100644
--- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -1,12 +1,12 @@
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:24:22
+  --> $DIR/issue-72649-uninit-in-loop.rs:29:22
    |
 LL |         let value = NonCopy{};
    |             ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
 LL |
 LL |         let _used = value;
    |                     ----- value moved here
-LL |
+...
 LL |         let _used2 = value;
    |                      ^^^^^ value used here after move
    |
@@ -14,10 +14,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-72649-uninit-in-loop.rs:5:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let _used = value;
+   |                     ----- you could clone this value
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:36:26
+  --> $DIR/issue-72649-uninit-in-loop.rs:42:26
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -34,10 +37,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-72649-uninit-in-loop.rs:5:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let _used = value;
+   |                     ----- you could clone this value
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:46:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:52:21
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -51,10 +57,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-72649-uninit-in-loop.rs:5:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let _used = value;
+   |                     ----- you could clone this value
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:57:22
+  --> $DIR/issue-72649-uninit-in-loop.rs:64:22
    |
 LL |     let mut value = NonCopy{};
    |         --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -68,10 +77,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-72649-uninit-in-loop.rs:5:1
    |
 LL | struct NonCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let _used2 = value;
+   |                      ----- you could clone this value
 
 error[E0381]: used binding `value` isn't initialized
-  --> $DIR/issue-72649-uninit-in-loop.rs:65:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:73:21
    |
 LL |         let value: NonCopy;
    |             ----- binding declared here but left uninitialized
@@ -84,7 +96,7 @@ LL |         let value: NonCopy = /* value */;
    |                            +++++++++++++
 
 error[E0381]: used binding `value` isn't initialized
-  --> $DIR/issue-72649-uninit-in-loop.rs:73:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:81:21
    |
 LL |     let mut value: NonCopy;
    |         --------- binding declared here but left uninitialized
diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr
index b6ad906bbdb..815e91b0f4d 100644
--- a/tests/ui/moves/issue-75904-move-closure-loop.stderr
+++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr
@@ -15,7 +15,10 @@ note: if `NotCopy` implemented `Clone`, you could clone the value
   --> $DIR/issue-75904-move-closure-loop.rs:5:1
    |
 LL | struct NotCopy;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |             a;
+   |             - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr
index e6bf52276ac..f2c6008d27e 100644
--- a/tests/ui/moves/move-fn-self-receiver.stderr
+++ b/tests/ui/moves/move-fn-self-receiver.stderr
@@ -106,7 +106,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/move-fn-self-receiver.rs:5:1
    |
 LL | struct Foo;
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let ret = mut_foo.use_mut_self();
+   |               ------- you could clone this value
 
 error[E0382]: use of moved value: `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:55:5
@@ -142,7 +145,10 @@ note: if `Foo` implemented `Clone`, you could clone the value
   --> $DIR/move-fn-self-receiver.rs:5:1
    |
 LL | struct Foo;
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     foo_add + Foo;
+   |     ------- you could clone this value
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr
index 9e4a08e0cef..8a030f02192 100644
--- a/tests/ui/moves/move-out-of-array-1.stderr
+++ b/tests/ui/moves/move-out-of-array-1.stderr
@@ -11,7 +11,10 @@ note: if `D` implemented `Clone`, you could clone the value
   --> $DIR/move-out-of-array-1.rs:5:1
    |
 LL | struct D { _x: u8 }
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     a[i]
+   |     ---- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
index 4759b45892c..a8473bb8198 100644
--- a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
+++ b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
@@ -17,6 +17,13 @@ LL |     let mut r = R {c: Box::new(f)};
 LL |     f(&mut r, false)
    |     ^ value borrowed here after move
    |
+help: if `F` implemented `Clone`, you could clone the value
+  --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:30:16
+   |
+LL | fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
+   |                ^ consider constraining this type parameter with `Clone`
+LL |     let mut r = R {c: Box::new(f)};
+   |                                - you could clone this value
 help: consider mutably borrowing `f`
    |
 LL |     let mut r = R {c: Box::new(&mut f)};
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
index e726c8145c3..bfb855c7fb1 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed
@@ -3,6 +3,7 @@
 
 fn duplicate_t<T: Copy>(t: T) -> (T, T) {
     //~^ HELP consider restricting type parameter `T`
+    //~| HELP if `T` implemented `Clone`, you could clone the value
     (t, t) //~ use of moved value: `t`
 }
 
@@ -72,10 +73,11 @@ where
 #[rustfmt::skip]
 fn existing_colon<T: Copy>(t: T) {
     //~^ HELP consider restricting type parameter `T`
+    //~| HELP if `T` implemented `Clone`, you could clone the value
     [t, t]; //~ use of moved value: `t`
 }
 
-fn existing_colon_in_where<T>(t: T)
+fn existing_colon_in_where<T>(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value
 where
     T:, T: Copy
     //~^ HELP consider further restricting type parameter `T`
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
index ee08ce0fa5b..fbe5a1d74c3 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs
@@ -3,6 +3,7 @@
 
 fn duplicate_t<T>(t: T) -> (T, T) {
     //~^ HELP consider restricting type parameter `T`
+    //~| HELP if `T` implemented `Clone`, you could clone the value
     (t, t) //~ use of moved value: `t`
 }
 
@@ -72,10 +73,11 @@ where
 #[rustfmt::skip]
 fn existing_colon<T:>(t: T) {
     //~^ HELP consider restricting type parameter `T`
+    //~| HELP if `T` implemented `Clone`, you could clone the value
     [t, t]; //~ use of moved value: `t`
 }
 
-fn existing_colon_in_where<T>(t: T)
+fn existing_colon_in_where<T>(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value
 where
     T:,
     //~^ HELP consider further restricting type parameter `T`
diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
index 3e37fcb2141..c03204c7b9f 100644
--- a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
+++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr
@@ -1,21 +1,29 @@
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:6:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:7:9
    |
 LL | fn duplicate_t<T>(t: T) -> (T, T) {
    |                   - move occurs because `t` has type `T`, which does not implement the `Copy` trait
-LL |
+...
 LL |     (t, t)
    |      -  ^ value used here after move
    |      |
    |      value moved here
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:4:16
+   |
+LL | fn duplicate_t<T>(t: T) -> (T, T) {
+   |                ^ consider constraining this type parameter with `Clone`
+...
+LL |     (t, t)
+   |      - you could clone this value
 help: consider restricting type parameter `T`
    |
 LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) {
    |                 ++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:11:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:12:9
    |
 LL | fn duplicate_opt<T>(t: Option<T>) -> (Option<T>, Option<T>) {
    |                     - move occurs because `t` has type `Option<T>`, which does not implement the `Copy` trait
@@ -31,7 +39,7 @@ LL | fn duplicate_opt<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) {
    |                   ++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:16:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:17:9
    |
 LL | fn duplicate_tup1<T>(t: (T,)) -> ((T,), (T,)) {
    |                      - move occurs because `t` has type `(T,)`, which does not implement the `Copy` trait
@@ -47,7 +55,7 @@ LL | fn duplicate_tup1<T: Copy>(t: (T,)) -> ((T,), (T,)) {
    |                    ++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:21:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:22:9
    |
 LL | fn duplicate_tup2<A, B>(t: (A, B)) -> ((A, B), (A, B)) {
    |                         - move occurs because `t` has type `(A, B)`, which does not implement the `Copy` trait
@@ -63,7 +71,7 @@ LL | fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
    |                    ++++++   ++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:26:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:27:9
    |
 LL | fn duplicate_custom<T>(t: S<T>) -> (S<T>, S<T>) {
    |                        - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
@@ -79,7 +87,7 @@ LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
    |                      ++++++++++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:44:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:45:9
    |
 LL | fn duplicate_custom_1<T>(t: S<T>) -> (S<T>, S<T>) where {
    |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
@@ -95,7 +103,7 @@ LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
    |                        ++++++++++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:52:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:53:9
    |
 LL | fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
    |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
@@ -111,7 +119,7 @@ LL |     T: A + Copy + Trait,
    |          ++++++++++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:61:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:62:9
    |
 LL | fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
    |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
@@ -127,7 +135,7 @@ LL |     T: A + Copy + Trait,
    |          ++++++++++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:69:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:70:9
    |
 LL | fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
    |                             - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
@@ -143,23 +151,31 @@ LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
    |                            ++++++++++++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:75:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:77:9
    |
 LL | fn existing_colon<T:>(t: T) {
    |                       - move occurs because `t` has type `T`, which does not implement the `Copy` trait
-LL |
+...
 LL |     [t, t];
    |      -  ^ value used here after move
    |      |
    |      value moved here
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:74:19
+   |
+LL | fn existing_colon<T:>(t: T) {
+   |                   ^ consider constraining this type parameter with `Clone`
+...
+LL |     [t, t];
+   |      - you could clone this value
 help: consider restricting type parameter `T`
    |
 LL | fn existing_colon<T: Copy>(t: T) {
    |                      ++++
 
 error[E0382]: use of moved value: `t`
-  --> $DIR/use_of_moved_value_copy_suggestions.rs:83:9
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:85:9
    |
 LL | fn existing_colon_in_where<T>(t: T)
    |                               - move occurs because `t` has type `T`, which does not implement the `Copy` trait
@@ -169,6 +185,14 @@ LL |     [t, t];
    |      |
    |      value moved here
    |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:80:28
+   |
+LL | fn existing_colon_in_where<T>(t: T)
+   |                            ^ consider constraining this type parameter with `Clone`
+...
+LL |     [t, t];
+   |      - you could clone this value
 help: consider further restricting type parameter `T`
    |
 LL |     T:, T: Copy
diff --git a/tests/ui/nll/closure-borrow-spans.stderr b/tests/ui/nll/closure-borrow-spans.stderr
index cac22c2ecda..c466cad25d2 100644
--- a/tests/ui/nll/closure-borrow-spans.stderr
+++ b/tests/ui/nll/closure-borrow-spans.stderr
@@ -25,6 +25,8 @@ LL |     f.use_ref();
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:19:16
    |
+LL |         let x = 1;
+   |             - binding `x` declared here
 LL |         f = || x;
    |             -- ^ borrowed value does not live long enough
    |             |
@@ -85,6 +87,8 @@ LL |     f.use_ref();
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:52:16
    |
+LL |         let mut x = 1;
+   |             ----- binding `x` declared here
 LL |         f = || x = 0;
    |             -- ^ borrowed value does not live long enough
    |             |
@@ -145,6 +149,8 @@ LL |     f.use_ref();
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:86:16
    |
+LL |         let x = &mut z;
+   |             - binding `x` declared here
 LL |         f = || *x = 0;
    |             -- ^^ borrowed value does not live long enough
    |             |
diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr
index aa73e91cc77..8e47ab780f2 100644
--- a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -37,6 +37,9 @@ LL | fn test() {
 error[E0597]: `y` does not live long enough
   --> $DIR/escape-upvar-nested.rs:21:40
    |
+LL |         let y = 22;
+   |             - binding `y` declared here
+LL |
 LL |         let mut closure = || {
    |                           -- value captured here
 LL |             let mut closure1 = || p = &y;
diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 949dcc78703..c428150aa2f 100644
--- a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -23,6 +23,8 @@ LL | fn test() {
 error[E0597]: `y` does not live long enough
   --> $DIR/escape-upvar-ref.rs:23:35
    |
+LL |         let y = 22;
+   |             - binding `y` declared here
 LL |         let mut closure = || p = &y;
    |                           --      ^ borrowed value does not live long enough
    |                           |
diff --git a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr
index 81b5f09b041..15f48d88c37 100644
--- a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr
@@ -1,6 +1,8 @@
 error[E0597]: `local_arr` does not live long enough
   --> $DIR/propagate-multiple-requirements.rs:15:14
    |
+LL |     let local_arr = other_local_arr;
+   |         --------- binding `local_arr` declared here
 LL |     let mut out: &mut &'static [i32] = &mut (&[1] as _);
    |                  ------------------- type annotation requires that `local_arr` is borrowed for `'static`
 LL |     once(|mut z: &[i32], mut out_val: &mut &[i32]| {
diff --git a/tests/ui/nll/coroutine-distinct-lifetime.rs b/tests/ui/nll/coroutine-distinct-lifetime.rs
index ff94a3d54b7..471fad686c4 100644
--- a/tests/ui/nll/coroutine-distinct-lifetime.rs
+++ b/tests/ui/nll/coroutine-distinct-lifetime.rs
@@ -9,6 +9,7 @@
 //@ check-pass
 
 fn foo(x: &mut u32) {
+    #[coroutine]
     move || {
         let s = &mut *x;
         yield;
diff --git a/tests/ui/nll/coroutine-upvar-mutability.rs b/tests/ui/nll/coroutine-upvar-mutability.rs
index 12853b16b9b..a7d14173fb9 100644
--- a/tests/ui/nll/coroutine-upvar-mutability.rs
+++ b/tests/ui/nll/coroutine-upvar-mutability.rs
@@ -4,6 +4,8 @@
 
 fn mutate_upvar() {
     let x = 0;
+
+    #[coroutine]
     move || {
         x = 1;
         //~^ ERROR
diff --git a/tests/ui/nll/coroutine-upvar-mutability.stderr b/tests/ui/nll/coroutine-upvar-mutability.stderr
index 8922eae3151..8b9be877c8f 100644
--- a/tests/ui/nll/coroutine-upvar-mutability.stderr
+++ b/tests/ui/nll/coroutine-upvar-mutability.stderr
@@ -1,9 +1,9 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/coroutine-upvar-mutability.rs:8:9
+  --> $DIR/coroutine-upvar-mutability.rs:10:9
    |
 LL |     let x = 0;
    |         - help: consider changing this to be mutable: `mut x`
-LL |     move || {
+...
 LL |         x = 1;
    |         ^^^^^ cannot assign
 
diff --git a/tests/ui/nll/extra-unused-mut.rs b/tests/ui/nll/extra-unused-mut.rs
index 786ba98508f..b040dcc6e5d 100644
--- a/tests/ui/nll/extra-unused-mut.rs
+++ b/tests/ui/nll/extra-unused-mut.rs
@@ -18,6 +18,8 @@ fn mutable_upvar() {
 // #50897
 fn coroutine_mutable_upvar() {
     let mut x = 0;
+
+    #[coroutine]
     move || {
         x = 1;
         yield;
@@ -36,13 +38,13 @@ struct Expr {
 // #51904
 fn parse_dot_or_call_expr_with(mut attrs: Vec<u32>) {
     let x = Expr { attrs: vec![] };
-    Some(Some(x)).map(|expr|
+    Some(Some(x)).map(|expr| {
         expr.map(|mut expr| {
             attrs.push(666);
             expr.attrs = attrs;
             expr
         })
-    );
+    });
 }
 
 // Found when trying to bootstrap rustc
diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr
index 2aff375f0a7..496a298a36c 100644
--- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -32,7 +32,10 @@ note: if `S<Box<u32>>` implemented `Clone`, you could clone the value
   --> $DIR/issue-21232-partial-init-and-use.rs:15:1
    |
 LL | struct S<Y> {
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |                                      - you could clone this value
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:116:5
@@ -83,7 +86,10 @@ note: if `S<Box<u32>>` implemented `Clone`, you could clone the value
   --> $DIR/issue-21232-partial-init-and-use.rs:15:1
    |
 LL | struct S<Y> {
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |                                      - you could clone this value
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:142:5
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
new file mode 100644
index 00000000000..7692be7ccc8
--- /dev/null
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
@@ -0,0 +1,23 @@
+// Issue 27282: Example 1: This sidesteps the AST checks disallowing
+// mutable borrows in match guards by hiding the mutable borrow in a
+// guard behind a move (of the ref mut pattern id) within a closure.
+//@ run-rustfix
+#![feature(if_let_guard)]
+
+fn main() {
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
+        //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
+        //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+        Some(s) => std::process::exit(*s),
+    }
+}
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
index 833ca8afd61..f3d0a184e03 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
@@ -1,14 +1,14 @@
 // Issue 27282: Example 1: This sidesteps the AST checks disallowing
 // mutable borrows in match guards by hiding the mutable borrow in a
 // guard behind a move (of the ref mut pattern id) within a closure.
-
+//@ run-rustfix
 #![feature(if_let_guard)]
 
 fn main() {
     match Some(&4) {
         None => {},
         ref mut foo
-            if { (|| { let bar = foo; bar.take() })(); false } => {},
+            if { (|| { let mut bar = foo; bar.take() })(); false } => {},
         //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
         Some(s) => std::process::exit(*s),
     }
@@ -16,7 +16,7 @@ fn main() {
     match Some(&4) {
         None => {},
         ref mut foo
-            if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
+            if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {},
         //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
         Some(s) => std::process::exit(*s),
     }
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
index 4a512560c87..7781e77894b 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
@@ -1,22 +1,30 @@
 error[E0507]: cannot move out of `foo` in pattern guard
   --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19
    |
-LL |             if { (|| { let bar = foo; bar.take() })(); false } => {},
-   |                   ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+LL |             if { (|| { let mut bar = foo; bar.take() })(); false } => {},
+   |                   ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
    |                   |
    |                   `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
+   |                                         ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
   --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
    |
-LL |             if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
-   |                                  ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+LL |             if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {},
+   |                                  ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
    |                                  |
    |                                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
+   |                                                        ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
index 0b5d723172c..f73e4aaa489 100644
--- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr
+++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
@@ -7,6 +7,10 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |                 (|| { let bar = foo.clone(); bar.take() })();
+   |                                    ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
   --> $DIR/issue-27282-mutation-in-guard.rs:20:18
@@ -17,6 +21,10 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |                 (|| { let bar = foo.clone(); bar.take() })();
+   |                                    ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr
index f7a525ee9b0..e3f44467550 100644
--- a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr
+++ b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr
@@ -11,6 +11,8 @@ LL |     || doit(data);
 error[E0597]: `data` does not live long enough
   --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:6:13
    |
+LL | fn doit(data: &'static mut ()) {
+   |         ---- binding `data` declared here
 LL |     || doit(data);
    |     -- -----^^^^-
    |     |  |    |
diff --git a/tests/ui/nll/issue-48623-coroutine.rs b/tests/ui/nll/issue-48623-coroutine.rs
index 3a4a27855d9..63348a2047c 100644
--- a/tests/ui/nll/issue-48623-coroutine.rs
+++ b/tests/ui/nll/issue-48623-coroutine.rs
@@ -12,7 +12,7 @@ impl Drop for WithDrop {
 
 fn reborrow_from_coroutine(r: &mut ()) {
     let d = WithDrop;
-    move || { d; yield; &mut *r }; //~ WARN unused coroutine that must be used
+    #[coroutine] move || { d; yield; &mut *r }; //~ WARN unused coroutine that must be used
 }
 
 fn main() {}
diff --git a/tests/ui/nll/issue-48623-coroutine.stderr b/tests/ui/nll/issue-48623-coroutine.stderr
index 1b7b1735aac..4e4cd28ef2a 100644
--- a/tests/ui/nll/issue-48623-coroutine.stderr
+++ b/tests/ui/nll/issue-48623-coroutine.stderr
@@ -1,8 +1,8 @@
 warning: unused coroutine that must be used
-  --> $DIR/issue-48623-coroutine.rs:15:5
+  --> $DIR/issue-48623-coroutine.rs:15:18
    |
-LL |     move || { d; yield; &mut *r };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[coroutine] move || { d; yield; &mut *r };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/tests/ui/nll/issue-55850.rs b/tests/ui/nll/issue-55850.rs
index fc873af9463..bf1e2e7caef 100644
--- a/tests/ui/nll/issue-55850.rs
+++ b/tests/ui/nll/issue-55850.rs
@@ -23,7 +23,7 @@ where
 }
 
 fn bug<'a>() -> impl Iterator<Item = &'a str> {
-    GenIter(move || {
+    GenIter(#[coroutine] move || {
         let mut s = String::new();
         yield &s[..] //~ ERROR cannot yield value referencing local variable `s` [E0515]
         //~| ERROR borrow may still be in use when coroutine yields
diff --git a/tests/ui/nll/match-guards-always-borrow.fixed b/tests/ui/nll/match-guards-always-borrow.fixed
new file mode 100644
index 00000000000..56e743bf196
--- /dev/null
+++ b/tests/ui/nll/match-guards-always-borrow.fixed
@@ -0,0 +1,66 @@
+#![feature(if_let_guard)]
+#![allow(unused_mut)]
+//@ run-rustfix
+
+// Here is arielb1's basic example from rust-lang/rust#27282
+// that AST borrowck is flummoxed by:
+
+fn should_reject_destructive_mutate_in_guard() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if {
+            (|| { let mut bar = foo.clone(); bar.take() })();
+            //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+            false } => { },
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo if let Some(()) = {
+            (|| { let mut bar = foo.clone(); bar.take() })();
+            //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+            None } => { },
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we mutate in the arm
+// body.
+fn allow_mutate_in_arm_body() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if foo.is_some() => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo if let Some(_) = foo => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we move into the arm
+// body.
+fn allow_move_into_arm_body() {
+    match Some(&4) {
+        None => {},
+        mut foo if foo.is_some() => { foo.unwrap(); () }
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        mut foo if let Some(_) = foo => { foo.unwrap(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+fn main() {
+    should_reject_destructive_mutate_in_guard();
+    allow_mutate_in_arm_body();
+    allow_move_into_arm_body();
+}
diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs
index ff63cc09273..927d55c42a6 100644
--- a/tests/ui/nll/match-guards-always-borrow.rs
+++ b/tests/ui/nll/match-guards-always-borrow.rs
@@ -1,4 +1,6 @@
 #![feature(if_let_guard)]
+#![allow(unused_mut)]
+//@ run-rustfix
 
 // Here is arielb1's basic example from rust-lang/rust#27282
 // that AST borrowck is flummoxed by:
@@ -7,7 +9,7 @@ fn should_reject_destructive_mutate_in_guard() {
     match Some(&4) {
         None => {},
         ref mut foo if {
-            (|| { let bar = foo; bar.take() })();
+            (|| { let mut bar = foo; bar.take() })();
             //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
             false } => { },
         Some(s) => std::process::exit(*s),
@@ -16,7 +18,7 @@ fn should_reject_destructive_mutate_in_guard() {
     match Some(&4) {
         None => {},
         ref mut foo if let Some(()) = {
-            (|| { let bar = foo; bar.take() })();
+            (|| { let mut bar = foo; bar.take() })();
             //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
             None } => { },
         Some(s) => std::process::exit(*s),
diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr
index afd853c403e..bb0c5bd4c97 100644
--- a/tests/ui/nll/match-guards-always-borrow.stderr
+++ b/tests/ui/nll/match-guards-always-borrow.stderr
@@ -1,22 +1,30 @@
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/match-guards-always-borrow.rs:10:14
+  --> $DIR/match-guards-always-borrow.rs:12:14
    |
-LL |             (|| { let bar = foo; bar.take() })();
-   |              ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+LL |             (|| { let mut bar = foo; bar.take() })();
+   |              ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
    |              |
    |              `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             (|| { let mut bar = foo.clone(); bar.take() })();
+   |                                    ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/match-guards-always-borrow.rs:19:14
+  --> $DIR/match-guards-always-borrow.rs:21:14
    |
-LL |             (|| { let bar = foo; bar.take() })();
-   |              ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+LL |             (|| { let mut bar = foo; bar.take() })();
+   |              ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
    |              |
    |              `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             (|| { let mut bar = foo.clone(); bar.take() })();
+   |                                    ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr
index 842ecaf524b..d1384121379 100644
--- a/tests/ui/nll/move-errors.stderr
+++ b/tests/ui/nll/move-errors.stderr
@@ -8,7 +8,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let b = *a;
+   |             -- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let b = *a;
@@ -28,7 +31,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let b = a[0];
+   |             ---- you could clone this value
 help: consider borrowing here
    |
 LL |     let b = &a[0];
@@ -44,7 +50,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let s = **r;
+   |             --- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let s = **r;
@@ -61,7 +70,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let s = *r;
+   |             -- you could clone this value
 help: consider removing the dereference here
    |
 LL -     let s = *r;
@@ -81,7 +93,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let a = [A("".to_string())][0];
+   |             ---------------------- you could clone this value
 help: consider borrowing here
    |
 LL |     let a = &[A("".to_string())][0];
@@ -126,7 +141,10 @@ note: if `A` implemented `Clone`, you could clone the value
   --> $DIR/move-errors.rs:1:1
    |
 LL | struct A(String);
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     b = *a;
+   |         -- you could clone this value
 
 error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
   --> $DIR/move-errors.rs:74:11
diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr
index 5227ca8ec17..1d086c658df 100644
--- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr
+++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr
@@ -1,6 +1,8 @@
 error[E0597]: `a` does not live long enough
   --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18
    |
+LL |     let a = ();
+   |         - binding `a` declared here
 LL |     let b = |_| &a;
    |             --- -^
    |             |   ||
diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr
index 5227ca8ec17..1d086c658df 100644
--- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr
+++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr
@@ -1,6 +1,8 @@
 error[E0597]: `a` does not live long enough
   --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18
    |
+LL |     let a = ();
+   |         - binding `a` declared here
 LL |     let b = |_| &a;
    |             --- -^
    |             |   ||
diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
index c7c08c948ab..c42ea0172cf 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
@@ -33,7 +33,9 @@ error[E0597]: `a` does not live long enough
    |
 LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
    |                                              -- lifetime `'a` defined here
-...
+LL |     let a = 22;
+   |         - binding `a` declared here
+LL |     let b = 44;
 LL |     let _closure = || {
    |                    -- value captured here
 LL |         let c = 66;
diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
index b7861a3bd06..287337c7d52 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
@@ -34,7 +34,9 @@ error[E0597]: `b` does not live long enough
    |
 LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
    |                                              -- lifetime `'a` defined here
-...
+LL |     let a = 22;
+LL |     let b = 44;
+   |         - binding `b` declared here
 LL |     let _closure = || {
    |                    -- value captured here
 LL |         let c = 66;
diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs
index 037b8cb78b7..ba3dcb10c61 100644
--- a/tests/ui/packed/packed-struct-drop-aligned.rs
+++ b/tests/ui/packed/packed-struct-drop-aligned.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(coroutine_trait)]
 use std::cell::Cell;
 use std::mem;
@@ -7,13 +7,12 @@ use std::ops::Coroutine;
 use std::pin::Pin;
 
 struct Aligned<'a> {
-    drop_count: &'a Cell<usize>
+    drop_count: &'a Cell<usize>,
 }
 
 #[inline(never)]
 fn check_align(ptr: *const Aligned) {
-    assert_eq!(ptr as usize % mem::align_of::<Aligned>(),
-               0);
+    assert_eq!(ptr as usize % mem::align_of::<Aligned>(), 0);
 }
 
 impl<'a> Drop for Aligned<'a> {
@@ -39,7 +38,8 @@ fn main() {
     assert_eq!(drop_count.get(), 2);
 
     let drop_count = &Cell::new(0);
-    let mut g = || {
+    let mut g = #[coroutine]
+    || {
         let mut p = Packed(NotCopy(0), Aligned { drop_count });
         let _ = &p;
         p.1 = Aligned { drop_count };
diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs
index c3126a493e5..de41a07568f 100644
--- a/tests/ui/parser/bad-let-else-statement.rs
+++ b/tests/ui/parser/bad-let-else-statement.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete
 #![feature(explicit_tail_calls)]
diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr
index 12df8f849ab..3f7e176b3e3 100644
--- a/tests/ui/parser/bad-let-else-statement.stderr
+++ b/tests/ui/parser/bad-let-else-statement.stderr
@@ -1,5 +1,5 @@
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:10:5
+  --> $DIR/bad-let-else-statement.rs:9:5
    |
 LL |     } else {
    |     ^
@@ -13,7 +13,7 @@ LL ~     }) else {
    |
 
 error: `for...else` loops are not supported
-  --> $DIR/bad-let-else-statement.rs:19:7
+  --> $DIR/bad-let-else-statement.rs:18:7
    |
 LL |       let foo = for i in 1..2 {
    |                 --- `else` is attached to this loop
@@ -28,7 +28,7 @@ LL | |     };
    = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:31:5
+  --> $DIR/bad-let-else-statement.rs:30:5
    |
 LL |     } else {
    |     ^
@@ -43,7 +43,7 @@ LL ~     }) else {
    |
 
 error: `loop...else` loops are not supported
-  --> $DIR/bad-let-else-statement.rs:40:7
+  --> $DIR/bad-let-else-statement.rs:39:7
    |
 LL |       let foo = loop {
    |                 ---- `else` is attached to this loop
@@ -58,7 +58,7 @@ LL | |     };
    = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:51:5
+  --> $DIR/bad-let-else-statement.rs:50:5
    |
 LL |     } else {
    |     ^
@@ -73,7 +73,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:62:5
+  --> $DIR/bad-let-else-statement.rs:61:5
    |
 LL |     } else {
    |     ^
@@ -87,7 +87,7 @@ LL ~     }) else {
    |
 
 error: `while...else` loops are not supported
-  --> $DIR/bad-let-else-statement.rs:71:7
+  --> $DIR/bad-let-else-statement.rs:70:7
    |
 LL |       let foo = while false {
    |                 ----- `else` is attached to this loop
@@ -102,7 +102,7 @@ LL | |     };
    = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:81:5
+  --> $DIR/bad-let-else-statement.rs:80:5
    |
 LL |     } else {
    |     ^
@@ -116,7 +116,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:91:5
+  --> $DIR/bad-let-else-statement.rs:90:5
    |
 LL |     } else {
    |     ^
@@ -130,7 +130,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:102:5
+  --> $DIR/bad-let-else-statement.rs:101:5
    |
 LL |     } else {
    |     ^
@@ -144,7 +144,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:112:5
+  --> $DIR/bad-let-else-statement.rs:111:5
    |
 LL |     } else {
    |     ^
@@ -158,7 +158,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:122:5
+  --> $DIR/bad-let-else-statement.rs:121:5
    |
 LL |     } else {
    |     ^
@@ -172,7 +172,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:132:5
+  --> $DIR/bad-let-else-statement.rs:131:5
    |
 LL |     } else {
    |     ^
@@ -186,7 +186,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:142:5
+  --> $DIR/bad-let-else-statement.rs:141:5
    |
 LL |     } else {
    |     ^
@@ -200,7 +200,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:152:5
+  --> $DIR/bad-let-else-statement.rs:151:5
    |
 LL |     } else {
    |     ^
@@ -214,7 +214,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:162:5
+  --> $DIR/bad-let-else-statement.rs:161:5
    |
 LL |     } else {
    |     ^
@@ -228,7 +228,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:172:5
+  --> $DIR/bad-let-else-statement.rs:171:5
    |
 LL |     } else {
    |     ^
@@ -242,7 +242,7 @@ LL ~     }) else {
    |
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:182:31
+  --> $DIR/bad-let-else-statement.rs:181:31
    |
 LL |     let bad = format_args! {""} else { return; };
    |                               ^
@@ -253,7 +253,7 @@ LL |     let bad = format_args! ("") else { return; };
    |                            ~  ~
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/bad-let-else-statement.rs:199:25
+  --> $DIR/bad-let-else-statement.rs:198:25
    |
 LL |             let x = a! {} else { return; };
    |                         ^
@@ -268,7 +268,7 @@ LL |             let x = a! () else { return; };
    |                        ~~
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:7:5
+  --> $DIR/bad-let-else-statement.rs:6:5
    |
 LL | /     let foo = {
 LL | |
@@ -281,7 +281,7 @@ LL | |     } else {
    = note: `#[warn(irrefutable_let_patterns)]` on by default
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:26:5
+  --> $DIR/bad-let-else-statement.rs:25:5
    |
 LL | /     let foo = if true {
 LL | |
@@ -295,7 +295,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:47:5
+  --> $DIR/bad-let-else-statement.rs:46:5
    |
 LL | /     let foo = match true {
 LL | |
@@ -308,7 +308,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:59:5
+  --> $DIR/bad-let-else-statement.rs:58:5
    |
 LL | /     let foo = X {
 LL | |
@@ -320,7 +320,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:78:5
+  --> $DIR/bad-let-else-statement.rs:77:5
    |
 LL | /     let foo = const {
 LL | |
@@ -332,7 +332,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:88:5
+  --> $DIR/bad-let-else-statement.rs:87:5
    |
 LL | /     let foo = &{
 LL | |
@@ -344,7 +344,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:99:5
+  --> $DIR/bad-let-else-statement.rs:98:5
    |
 LL | /     let foo = bar = {
 LL | |
@@ -356,7 +356,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 error[E0384]: cannot assign twice to immutable variable `bar`
-  --> $DIR/bad-let-else-statement.rs:99:15
+  --> $DIR/bad-let-else-statement.rs:98:15
    |
 LL |       let bar = 0;
    |           ---
@@ -371,7 +371,7 @@ LL | |     } else {
    | |_____^ cannot assign twice to immutable variable
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:109:5
+  --> $DIR/bad-let-else-statement.rs:108:5
    |
 LL | /     let foo = 1 + {
 LL | |
@@ -383,7 +383,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:119:5
+  --> $DIR/bad-let-else-statement.rs:118:5
    |
 LL | /     let foo = 1..{
 LL | |
@@ -395,7 +395,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:129:5
+  --> $DIR/bad-let-else-statement.rs:128:5
    |
 LL | /     let foo = return {
 LL | |
@@ -407,7 +407,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:139:5
+  --> $DIR/bad-let-else-statement.rs:138:5
    |
 LL | /     let foo = -{
 LL | |
@@ -419,7 +419,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:149:5
+  --> $DIR/bad-let-else-statement.rs:148:5
    |
 LL | /     let foo = do yeet {
 LL | |
@@ -431,7 +431,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:159:5
+  --> $DIR/bad-let-else-statement.rs:158:5
    |
 LL | /     let foo = become {
 LL | |
@@ -443,7 +443,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:169:5
+  --> $DIR/bad-let-else-statement.rs:168:5
    |
 LL | /     let foo = |x: i32| {
 LL | |
@@ -455,7 +455,7 @@ LL | |     } else {
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:179:5
+  --> $DIR/bad-let-else-statement.rs:178:5
    |
 LL |     let ok = format_args!("") else { return; };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -464,7 +464,7 @@ LL |     let ok = format_args!("") else { return; };
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:182:5
+  --> $DIR/bad-let-else-statement.rs:181:5
    |
 LL |     let bad = format_args! {""} else { return; };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -473,7 +473,7 @@ LL |     let bad = format_args! {""} else { return; };
    = help: consider removing the `else` clause
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:189:19
+  --> $DIR/bad-let-else-statement.rs:188:19
    |
 LL |           () => { {} }
    |  ___________________^
@@ -493,7 +493,7 @@ LL |       b!(1); b!(2);
    = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: irrefutable `let...else` pattern
-  --> $DIR/bad-let-else-statement.rs:189:19
+  --> $DIR/bad-let-else-statement.rs:188:19
    |
 LL |           () => { {} }
    |  ___________________^
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index 00964cb8336..e925fe78f33 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -337,7 +337,10 @@ note: if `U` implemented `Clone`, you could clone the value
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
    |
 LL |     struct U;
-   |     ^^^^^^^^
+   |     ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |                                                                  - you could clone this value
 
 error[E0507]: cannot move out of `b` in pattern guard
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
@@ -350,7 +353,10 @@ note: if `U` implemented `Clone`, you could clone the value
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
    |
 LL |     struct U;
-   |     ^^^^^^^^
+   |     ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |                                                                  - you could clone this value
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0507]: cannot move out of `a` in pattern guard
diff --git a/tests/ui/polymorphization/coroutine.rs b/tests/ui/polymorphization/coroutine.rs
index a989947f787..22ceadfb194 100644
--- a/tests/ui/polymorphization/coroutine.rs
+++ b/tests/ui/polymorphization/coroutine.rs
@@ -32,6 +32,7 @@ where
 
 #[rustc_polymorphize_error]
 pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
+    #[coroutine]
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -41,6 +42,7 @@ pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
 
 #[rustc_polymorphize_error]
 pub fn used_type_in_yield<Y: Default>() -> impl Coroutine<(), Yield = Y, Return = u32> + Unpin {
+    #[coroutine]
     || {
         yield Y::default();
         2
@@ -49,6 +51,7 @@ pub fn used_type_in_yield<Y: Default>() -> impl Coroutine<(), Yield = Y, Return
 
 #[rustc_polymorphize_error]
 pub fn used_type_in_return<R: Default>() -> impl Coroutine<(), Yield = u32, Return = R> + Unpin {
+    #[coroutine]
     || {
         yield 3;
         R::default()
@@ -57,6 +60,7 @@ pub fn used_type_in_return<R: Default>() -> impl Coroutine<(), Yield = u32, Retu
 
 #[rustc_polymorphize_error]
 pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
+    #[coroutine]
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -67,6 +71,7 @@ pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return =
 #[rustc_polymorphize_error]
 pub fn used_const_in_yield<const Y: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
 {
+    #[coroutine]
     || {
         yield Y;
         2
@@ -76,6 +81,7 @@ pub fn used_const_in_yield<const Y: u32>() -> impl Coroutine<(), Yield = u32, Re
 #[rustc_polymorphize_error]
 pub fn used_const_in_return<const R: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
 {
+    #[coroutine]
     || {
         yield 4;
         R
diff --git a/tests/ui/polymorphization/coroutine.stderr b/tests/ui/polymorphization/coroutine.stderr
index 67b55a59883..07e29184226 100644
--- a/tests/ui/polymorphization/coroutine.stderr
+++ b/tests/ui/polymorphization/coroutine.stderr
@@ -8,18 +8,20 @@ LL | #![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: item has unused generic parameters
-  --> $DIR/coroutine.rs:35:5
+  --> $DIR/coroutine.rs:36:5
    |
 LL | pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
    |                    - generic parameter `T` is unused
+LL |     #[coroutine]
 LL |     || {
    |     ^^
 
 error: item has unused generic parameters
-  --> $DIR/coroutine.rs:60:5
+  --> $DIR/coroutine.rs:64:5
    |
 LL | pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
    |                     ------------ generic parameter `T` is unused
+LL |     #[coroutine]
 LL |     || {
    |     ^^
 
diff --git a/tests/ui/print_type_sizes/coroutine.rs b/tests/ui/print_type_sizes/coroutine.rs
index 61488c51f05..15335788789 100644
--- a/tests/ui/print_type_sizes/coroutine.rs
+++ b/tests/ui/print_type_sizes/coroutine.rs
@@ -7,6 +7,7 @@
 use std::ops::Coroutine;
 
 fn coroutine<const C: usize>(array: [u8; C]) -> impl Coroutine<Yield = (), Return = ()> {
+    #[coroutine]
     move |()| {
         yield ();
         let _ = array;
diff --git a/tests/ui/print_type_sizes/coroutine.stdout b/tests/ui/print_type_sizes/coroutine.stdout
index 5d51339558c..339bbddfc2a 100644
--- a/tests/ui/print_type_sizes/coroutine.stdout
+++ b/tests/ui/print_type_sizes/coroutine.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `{coroutine@$DIR/coroutine.rs:10:5: 10:14}`: 8193 bytes, alignment: 1 bytes
+print-type-size type: `{coroutine@$DIR/coroutine.rs:11:5: 11:14}`: 8193 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 8192 bytes
 print-type-size         upvar `.array`: 8192 bytes
diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.rs b/tests/ui/print_type_sizes/coroutine_discr_placement.rs
index 4b9f67a7999..d97b0b28ed0 100644
--- a/tests/ui/print_type_sizes/coroutine_discr_placement.rs
+++ b/tests/ui/print_type_sizes/coroutine_discr_placement.rs
@@ -5,11 +5,12 @@
 // Tests a coroutine that has its discriminant as the *final* field.
 
 // Avoid emitting panic handlers, like the rest of these tests...
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![allow(dropping_copy_types)]
 
 pub fn foo() {
-    let a = || {
+    let a = #[coroutine]
+    || {
         {
             let w: i32 = 4;
             yield;
diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout
index 71a7f3c6381..4ce1ce46f6e 100644
--- a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout
+++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:12:13: 12:15}`: 8 bytes, alignment: 4 bytes
+print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:13:5: 13:7}`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Suspend0`: 7 bytes
diff --git a/tests/ui/regions/regions-addr-of-upvar-self.stderr b/tests/ui/regions/regions-addr-of-upvar-self.stderr
index c16a6f8585b..3a028cc9e21 100644
--- a/tests/ui/regions/regions-addr-of-upvar-self.stderr
+++ b/tests/ui/regions/regions-addr-of-upvar-self.stderr
@@ -20,6 +20,8 @@ LL |             let p: &'static mut usize = &mut self.food;
 error[E0597]: `self` does not live long enough
   --> $DIR/regions-addr-of-upvar-self.rs:8:46
    |
+LL |     pub fn chase_cat(&mut self) {
+   |                      --------- binding `self` declared here
 LL |         let _f = || {
    |                  -- value captured here
 LL |             let p: &'static mut usize = &mut self.food;
diff --git a/tests/ui/regions/regions-nested-fns-2.stderr b/tests/ui/regions/regions-nested-fns-2.stderr
index 254497639a1..02359fe1213 100644
--- a/tests/ui/regions/regions-nested-fns-2.stderr
+++ b/tests/ui/regions/regions-nested-fns-2.stderr
@@ -1,6 +1,9 @@
 error[E0597]: `y` does not live long enough
   --> $DIR/regions-nested-fns-2.rs:7:25
    |
+LL |     let y = 3;
+   |         - binding `y` declared here
+LL |     ignore(
 LL |         |z| {
    |         --- value captured here
 LL |             if false { &y } else { z }
diff --git a/tests/ui/regions/regions-nested-fns.stderr b/tests/ui/regions/regions-nested-fns.stderr
index ee43f9fa572..23b3f78dd4e 100644
--- a/tests/ui/regions/regions-nested-fns.stderr
+++ b/tests/ui/regions/regions-nested-fns.stderr
@@ -27,6 +27,9 @@ LL | }
 error[E0597]: `y` does not live long enough
   --> $DIR/regions-nested-fns.rs:10:15
    |
+LL |     let y = 3;
+   |         - binding `y` declared here
+...
 LL |     ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
    |                                                          --- value captured here
 LL |         ay = x;
diff --git a/tests/ui/regions/regions-steal-closure.stderr b/tests/ui/regions/regions-steal-closure.stderr
index 9324eb892a6..50068b32fa3 100644
--- a/tests/ui/regions/regions-steal-closure.stderr
+++ b/tests/ui/regions/regions-steal-closure.stderr
@@ -4,6 +4,7 @@ error[E0597]: `i` does not live long enough
 LL |     let mut cl_box = {
    |         ---------- borrow later stored here
 LL |         let mut i = 3;
+   |             ----- binding `i` declared here
 LL |         box_it(Box::new(|| i += 1))
    |                         -- ^ borrowed value does not live long enough
    |                         |
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
index d5c8a529e1e..9fdceefbf9b 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
@@ -113,7 +113,7 @@ fn dyn_coroutine(
 }
 
 fn test_coroutine() {
-    let coroutine = #[track_caller] |arg: String| {
+    let coroutine = #[track_caller] #[coroutine] |arg: String| {
         yield ("first", arg.clone(), Location::caller());
         yield ("second", arg.clone(), Location::caller());
     };
@@ -136,7 +136,7 @@ fn test_coroutine() {
     assert_eq!(mono_loc.line(), mono_line);
     assert_eq!(mono_loc.column(), 42);
 
-    let non_tracked_coroutine = || { yield Location::caller(); };
+    let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); };
     let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
     let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
         CoroutineState::Yielded(val) => val,
@@ -144,7 +144,7 @@ fn test_coroutine() {
     };
     assert_eq!(non_tracked_loc.file(), file!());
     assert_eq!(non_tracked_loc.line(), non_tracked_line);
-    assert_eq!(non_tracked_loc.column(), 44);
+    assert_eq!(non_tracked_loc.column(), 57);
 
 }
 
diff --git a/tests/ui/sanitizer/cfi-coroutine.rs b/tests/ui/sanitizer/cfi-coroutine.rs
index 5c6a489a7e8..ad994fcf737 100644
--- a/tests/ui/sanitizer/cfi-coroutine.rs
+++ b/tests/ui/sanitizer/cfi-coroutine.rs
@@ -14,7 +14,7 @@
 //@ compile-flags: --test -Z unstable-options
 //@ run-pass
 
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 #![feature(coroutine_trait)]
 #![feature(noop_waker)]
 #![feature(gen_blocks)]
@@ -27,7 +27,7 @@ use std::async_iter::AsyncIterator;
 
 #[test]
 fn general_coroutine() {
-    let mut coro = |x: i32| {
+    let mut coro = #[coroutine] |x: i32| {
         yield x;
         "done"
     };
diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs
index 06a747273ab..fda04434451 100644
--- a/tests/ui/simd/const-err-trumps-simd-err.rs
+++ b/tests/ui/simd/const-err-trumps-simd-err.rs
@@ -5,7 +5,7 @@
 #![feature(generic_arg_infer)]
 #![feature(core_intrinsics)]
 #![feature(repr_simd)]
-#![feature(inline_const)]
+
 use std::intrinsics::simd::*;
 
 #[repr(simd)]
diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs
index 73003087819..a81d8ebdf50 100644
--- a/tests/ui/simd/intrinsic/generic-elements-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs
@@ -2,7 +2,6 @@
 //@ ignore-emscripten FIXME(#45351) hits an LLVM assert
 
 #![feature(repr_simd, intrinsics)]
-#![feature(inline_const)]
 
 #[repr(simd)]
 #[derive(Copy, Clone, Debug, PartialEq)]
diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr
index bae0befcaca..c15547e8412 100644
--- a/tests/ui/span/send-is-not-static-ensures-scoping.stderr
+++ b/tests/ui/span/send-is-not-static-ensures-scoping.stderr
@@ -16,6 +16,9 @@ error[E0597]: `y` does not live long enough
    |
 LL |     let bad = {
    |         --- borrow later stored here
+LL |         let x = 1;
+LL |         let y = &x;
+   |             - binding `y` declared here
 ...
 LL |         scoped(|| {
    |                -- value captured here
diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs
index 6a35d779c1c..edc0637636b 100644
--- a/tests/ui/suggestions/issue-84973-blacklist.rs
+++ b/tests/ui/suggestions/issue-84973-blacklist.rs
@@ -14,7 +14,7 @@ struct S;
 fn main() {
     f_copy("".to_string()); //~ ERROR: the trait bound `String: Copy` is not satisfied [E0277]
     f_clone(S); //~ ERROR: the trait bound `S: Clone` is not satisfied [E0277]
-    f_unpin(static || { yield; });
+    f_unpin(#[coroutine] static || { yield; });
     //~^ ERROR: cannot be unpinned [E0277]
 
     let cl = || ();
diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr
index 33338228328..4fd063e4692 100644
--- a/tests/ui/suggestions/issue-84973-blacklist.stderr
+++ b/tests/ui/suggestions/issue-84973-blacklist.stderr
@@ -36,11 +36,11 @@ LL + #[derive(Clone)]
 LL | struct S;
    |
 
-error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` cannot be unpinned
-  --> $DIR/issue-84973-blacklist.rs:17:13
+error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}` cannot be unpinned
+  --> $DIR/issue-84973-blacklist.rs:17:26
    |
-LL |     f_unpin(static || { yield; });
-   |     ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}`
+LL |     f_unpin(#[coroutine] static || { yield; });
+   |     -------              ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/suggestions/option-content-move2.rs b/tests/ui/suggestions/option-content-move2.rs
index 88e8a5b7aee..b0104d9bafb 100644
--- a/tests/ui/suggestions/option-content-move2.rs
+++ b/tests/ui/suggestions/option-content-move2.rs
@@ -1,8 +1,10 @@
 struct NotCopyable;
+#[derive(Clone)]
+struct NotCopyableButCloneable;
 
 fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
 
-fn parse() {
+fn foo() {
     let mut var = None;
     func(|| {
         // Shouldn't suggest `move ||.as_ref()` here
@@ -12,5 +14,15 @@ fn parse() {
         }
     });
 }
+fn bar() {
+    let mut var = None;
+    func(|| {
+        // Shouldn't suggest `move ||.as_ref()` nor to `clone()` here
+        move || {
+        //~^ ERROR: cannot move out of `var`
+            var = Some(NotCopyableButCloneable);
+        }
+    });
+}
 
 fn main() {}
diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr
index 0297c031ecc..be97cba17b9 100644
--- a/tests/ui/suggestions/option-content-move2.stderr
+++ b/tests/ui/suggestions/option-content-move2.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
-  --> $DIR/option-content-move2.rs:9:9
+  --> $DIR/option-content-move2.rs:11:9
    |
 LL |     let mut var = None;
    |         ------- captured outer variable
@@ -15,6 +15,23 @@ LL |             var = Some(NotCopyable);
    |             variable moved due to use in closure
    |             move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
 
-error: aborting due to 1 previous error
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move2.rs:21:9
+   |
+LL |     let mut var = None;
+   |         ------- captured outer variable
+LL |     func(|| {
+   |          -- captured by this `FnMut` closure
+LL |         // Shouldn't suggest `move ||.as_ref()` nor to `clone()` here
+LL |         move || {
+   |         ^^^^^^^ `var` is moved here
+LL |
+LL |             var = Some(NotCopyableButCloneable);
+   |             ---
+   |             |
+   |             variable moved due to use in closure
+   |             move occurs because `var` has type `Option<NotCopyableButCloneable>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/option-content-move3.rs b/tests/ui/suggestions/option-content-move3.rs
new file mode 100644
index 00000000000..a245309d97f
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move3.rs
@@ -0,0 +1,30 @@
+#[derive(Debug)]
+struct NotCopyable;
+#[derive(Debug, Clone)]
+struct NotCopyableButCloneable;
+
+fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
+
+fn foo() {
+    let var = NotCopyable;
+    func(|| {
+        // Shouldn't suggest `move ||.as_ref()` here
+        move || { //~ ERROR cannot move out of `var`
+            let x = var; //~ ERROR cannot move out of `var`
+            println!("{x:?}");
+        }
+    });
+}
+
+fn bar() {
+    let var = NotCopyableButCloneable;
+    func(|| {
+        // Shouldn't suggest `move ||.as_ref()` here
+        move || { //~ ERROR cannot move out of `var`
+            let x = var; //~ ERROR cannot move out of `var`
+            println!("{x:?}");
+        }
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr
new file mode 100644
index 00000000000..a20dcce1ee3
--- /dev/null
+++ b/tests/ui/suggestions/option-content-move3.stderr
@@ -0,0 +1,95 @@
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move3.rs:13:21
+   |
+LL |     let var = NotCopyable;
+   |         --- captured outer variable
+...
+LL |         move || {
+   |         ------- captured by this `FnMut` closure
+LL |             let x = var;
+   |                     ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait
+   |
+note: if `NotCopyable` implemented `Clone`, you could clone the value
+  --> $DIR/option-content-move3.rs:2:1
+   |
+LL | struct NotCopyable;
+   | ^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |             let x = var;
+   |                     --- you could clone this value
+help: consider borrowing here
+   |
+LL |             let x = &var;
+   |                     +
+
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move3.rs:12:9
+   |
+LL |     let var = NotCopyable;
+   |         --- captured outer variable
+LL |     func(|| {
+   |          -- captured by this `FnMut` closure
+LL |         // Shouldn't suggest `move ||.as_ref()` here
+LL |         move || {
+   |         ^^^^^^^ `var` is moved here
+LL |             let x = var;
+   |                     ---
+   |                     |
+   |                     variable moved due to use in closure
+   |                     move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait
+   |
+note: if `NotCopyable` implemented `Clone`, you could clone the value
+  --> $DIR/option-content-move3.rs:2:1
+   |
+LL | struct NotCopyable;
+   | ^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |             let x = var;
+   |                     --- you could clone this value
+
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move3.rs:24:21
+   |
+LL |     let var = NotCopyableButCloneable;
+   |         --- captured outer variable
+...
+LL |         move || {
+   |         ------- captured by this `FnMut` closure
+LL |             let x = var;
+   |                     ^^^ move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |             let x = &var;
+   |                     +
+
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move3.rs:23:9
+   |
+LL |     let var = NotCopyableButCloneable;
+   |         --- captured outer variable
+LL |     func(|| {
+   |          -- captured by this `FnMut` closure
+LL |         // Shouldn't suggest `move ||.as_ref()` here
+LL |         move || {
+   |         ^^^^^^^ `var` is moved here
+LL |             let x = var;
+   |                     ---
+   |                     |
+   |                     variable moved due to use in closure
+   |                     move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait
+   |
+help: clone the value before moving it into the closure
+   |
+LL ~         {
+LL +         let value = var.clone();
+LL ~         move || {
+LL ~             let x = value;
+LL |             println!("{x:?}");
+LL ~         }
+LL +         }
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs
index a4e32d7c806..dd2c3536eb9 100644
--- a/tests/ui/suggestions/unnamable-types.rs
+++ b/tests/ui/suggestions/unnamable-types.rs
@@ -1,7 +1,7 @@
 // Test that we do not suggest to add type annotations for unnamable types.
 
 #![crate_type="lib"]
-#![feature(coroutines)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 const A = 5;
 //~^ ERROR: missing type for `const` item
@@ -34,6 +34,6 @@ const F = S { t: foo };
 //~| HELP: provide a type for the constant
 
 
-const G = || -> i32 { yield 0; return 1; };
+const G = #[coroutine] || -> i32 { yield 0; return 1; };
 //~^ ERROR: missing type for `const` item
 //~| NOTE: however, the inferred type
diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr
index d003b91691c..6623678fd0c 100644
--- a/tests/ui/suggestions/unnamable-types.stderr
+++ b/tests/ui/suggestions/unnamable-types.stderr
@@ -52,14 +52,14 @@ LL | const F = S { t: foo };
 error: missing type for `const` item
   --> $DIR/unnamable-types.rs:37:8
    |
-LL | const G = || -> i32 { yield 0; return 1; };
+LL | const G = #[coroutine] || -> i32 { yield 0; return 1; };
    |        ^
    |
-note: however, the inferred type `{coroutine@$DIR/unnamable-types.rs:37:11: 37:20}` cannot be named
-  --> $DIR/unnamable-types.rs:37:11
+note: however, the inferred type `{coroutine@$DIR/unnamable-types.rs:37:24: 37:33}` cannot be named
+  --> $DIR/unnamable-types.rs:37:24
    |
-LL | const G = || -> i32 { yield 0; return 1; };
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const G = #[coroutine] || -> i32 { yield 0; return 1; };
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr
index 14e67727d0b..e880d05a4dd 100644
--- a/tests/ui/traits/next-solver/coroutine.fail.stderr
+++ b/tests/ui/traits/next-solver/coroutine.fail.stderr
@@ -1,16 +1,16 @@
-error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:18:21: 18:23}: Coroutine<A>` is not satisfied
-  --> $DIR/coroutine.rs:18:21
+error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:20:9: 20:11}: Coroutine<A>` is not satisfied
+  --> $DIR/coroutine.rs:20:9
    |
-LL |       needs_coroutine(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
+LL |       needs_coroutine(
+   |       --------------- required by a bound introduced by this call
+LL |           #[coroutine]
+LL | /         || {
 LL | |
 LL | |
 LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ the trait `Coroutine<A>` is not implemented for `{coroutine@$DIR/coroutine.rs:18:21: 18:23}`
+LL | |             yield ();
+LL | |         },
+   | |_________^ the trait `Coroutine<A>` is not implemented for `{coroutine@$DIR/coroutine.rs:20:9: 20:11}`
    |
 note: required by a bound in `needs_coroutine`
   --> $DIR/coroutine.rs:14:28
@@ -18,19 +18,19 @@ note: required by a bound in `needs_coroutine`
 LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine`
 
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine<A>>::Yield == B`
-  --> $DIR/coroutine.rs:18:21
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine<A>>::Yield == B`
+  --> $DIR/coroutine.rs:20:9
    |
-LL |       needs_coroutine(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
+LL |       needs_coroutine(
+   |       --------------- required by a bound introduced by this call
+LL |           #[coroutine]
+LL | /         || {
 LL | |
 LL | |
 LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ types differ
+LL | |             yield ();
+LL | |         },
+   | |_________^ types differ
    |
 note: required by a bound in `needs_coroutine`
   --> $DIR/coroutine.rs:14:41
@@ -38,19 +38,19 @@ note: required by a bound in `needs_coroutine`
 LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
    |                                         ^^^^^^^^^ required by this bound in `needs_coroutine`
 
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine<A>>::Return == C`
-  --> $DIR/coroutine.rs:18:21
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine<A>>::Return == C`
+  --> $DIR/coroutine.rs:20:9
    |
-LL |       needs_coroutine(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
+LL |       needs_coroutine(
+   |       --------------- required by a bound introduced by this call
+LL |           #[coroutine]
+LL | /         || {
 LL | |
 LL | |
 LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ types differ
+LL | |             yield ();
+LL | |         },
+   | |_________^ types differ
    |
 note: required by a bound in `needs_coroutine`
   --> $DIR/coroutine.rs:14:52
diff --git a/tests/ui/traits/next-solver/coroutine.rs b/tests/ui/traits/next-solver/coroutine.rs
index 2b5bf01cefd..1882a62cf29 100644
--- a/tests/ui/traits/next-solver/coroutine.rs
+++ b/tests/ui/traits/next-solver/coroutine.rs
@@ -15,18 +15,24 @@ fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
 
 #[cfg(fail)]
 fn main() {
-    needs_coroutine(|| {
-        //[fail]~^ ERROR Coroutine<A>` is not satisfied
-        //[fail]~| ERROR as Coroutine<A>>::Yield == B`
-        //[fail]~| ERROR as Coroutine<A>>::Return == C`
-        yield ();
-    });
+    needs_coroutine(
+        #[coroutine]
+        || {
+            //[fail]~^ ERROR Coroutine<A>` is not satisfied
+            //[fail]~| ERROR as Coroutine<A>>::Yield == B`
+            //[fail]~| ERROR as Coroutine<A>>::Return == C`
+            yield ();
+        },
+    );
 }
 
 #[cfg(pass)]
 fn main() {
-    needs_coroutine(|_: A| {
-        let _: A = yield B;
-        C
-    })
+    needs_coroutine(
+        #[coroutine]
+        |_: A| {
+            let _: A = yield B;
+            C
+        },
+    )
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
index cd14bc1fd09..0d9126d3993 100644
--- a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
@@ -9,6 +9,7 @@ mod gen {
     pub type CoroOnce<Y, R> = impl Coroutine<Yield = Y, Return = R>;
 
     pub const fn const_coroutine<Y, R>(yielding: Y, returning: R) -> CoroOnce<Y, R> {
+        #[coroutine]
         move || {
             yield yielding;
 
diff --git a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
index 78a1d5116be..899e81ed562 100644
--- a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
@@ -8,6 +8,7 @@ use std::pin::Pin;
 
 type RandCoroutine<'a> = impl Coroutine<Return = (), Yield = u64> + 'a;
 fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> {
+    #[coroutine]
     move || {
         let _rng = rng;
         loop {
@@ -19,6 +20,7 @@ fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> {
 pub type RandCoroutineWithIndirection<'c> = impl Coroutine<Return = (), Yield = u64> + 'c;
 pub fn rand_coroutine_with_indirection<'a>(rng: &'a ()) -> RandCoroutineWithIndirection<'a> {
     fn helper<'b>(rng: &'b ()) -> impl 'b + Coroutine<Return = (), Yield = u64> {
+        #[coroutine]
         move || {
             let _rng = rng;
             loop {
diff --git a/tests/ui/type-alias-impl-trait/issue-94429.rs b/tests/ui/type-alias-impl-trait/issue-94429.rs
index 306e73003fa..11beed06a20 100644
--- a/tests/ui/type-alias-impl-trait/issue-94429.rs
+++ b/tests/ui/type-alias-impl-trait/issue-94429.rs
@@ -14,6 +14,7 @@ impl Runnable for Implementor {
 
     fn run(&mut self) -> Self::Coro {
         //~^ ERROR: type mismatch resolving
+        #[coroutine]
         move || {
             yield 1;
         }
diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr
index 5d081e6b1ef..4c2020becbe 100644
--- a/tests/ui/type-alias-impl-trait/issue-94429.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:17:9: 17:16} as Coroutine>::Yield == ()`
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:18:9: 18:16} as Coroutine>::Yield == ()`
   --> $DIR/issue-94429.rs:15:26
    |
 LL |     fn run(&mut self) -> Self::Coro {
diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
index 23aa18d7156..fc6f610ddd4 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
@@ -1,6 +1,9 @@
 error[E0597]: `factorial` does not live long enough
   --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17
    |
+LL |     let mut factorial: Option<Box<dyn Fn(u32) -> u32>> = None;
+   |         ------------- binding `factorial` declared here
+LL |
 LL |     let f = |x: u32| -> u32 {
    |             --------------- value captured here
 LL |         let g = factorial.as_ref().unwrap();
@@ -30,7 +33,9 @@ error[E0597]: `factorial` does not live long enough
   --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17
    |
 LL |     let mut factorial: Option<Box<dyn Fn(u32) -> u32 + 'static>> = None;
-   |                        ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+   |         -------------  ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+   |         |
+   |         binding `factorial` declared here
 LL |
 LL |     let f = |x: u32| -> u32 {
    |             --------------- value captured here
diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr
index 782fa63280e..f8e9609cb1c 100644
--- a/tests/ui/union/union-borrow-move-parent-sibling.stderr
+++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr
@@ -54,7 +54,10 @@ note: if `MockVec<u8>` implemented `Clone`, you could clone the value
   --> $DIR/union-borrow-move-parent-sibling.rs:25:1
    |
 LL | struct MockVec<T> {
-   | ^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     let a = (u.x.0).0;
+   |             --------- you could clone this value
 help: consider borrowing here
    |
 LL |     let a = &(u.x.0).0;
diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr
index 5ebb2716e5a..d520fb00ea9 100644
--- a/tests/ui/union/union-move.stderr
+++ b/tests/ui/union/union-move.stderr
@@ -20,7 +20,10 @@ note: if `U1` implemented `Clone`, you could clone the value
   --> $DIR/union-move.rs:9:1
    |
 LL | union U1 {
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- you could clone this value
 
 error[E0382]: use of moved value: `x`
   --> $DIR/union-move.rs:42:18
@@ -44,7 +47,10 @@ note: if `U1` implemented `Clone`, you could clone the value
   --> $DIR/union-move.rs:9:1
    |
 LL | union U1 {
-   | ^^^^^^^^
+   | ^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- you could clone this value
 
 error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
   --> $DIR/union-move.rs:49:18
diff --git a/tests/ui/unop-move-semantics.stderr b/tests/ui/unop-move-semantics.stderr
index 187dd66b2fe..bc9b3ea9903 100644
--- a/tests/ui/unop-move-semantics.stderr
+++ b/tests/ui/unop-move-semantics.stderr
@@ -33,6 +33,14 @@ LL |     !x;
 ...
 LL |     use_mut(n); use_imm(m);
    |                         - borrow later used here
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/unop-move-semantics.rs:11:18
+   |
+LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
+   |                  ^ consider constraining this type parameter with `Clone`
+LL |     let m = &x;
+   |             -- you could clone this value
 
 error[E0505]: cannot move out of `y` because it is borrowed
   --> $DIR/unop-move-semantics.rs:17:6
@@ -47,6 +55,15 @@ LL |     !y;
    |      ^ move out of `y` occurs here
 LL |     use_mut(n); use_imm(m);
    |             - borrow later used here
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/unop-move-semantics.rs:11:18
+   |
+LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
+   |                  ^ consider constraining this type parameter with `Clone`
+LL |     let m = &x;
+LL |     let n = &mut y;
+   |             ------ you could clone this value
 
 error[E0507]: cannot move out of `*m` which is behind a mutable reference
   --> $DIR/unop-move-semantics.rs:24:6
@@ -59,6 +76,14 @@ LL |     !*m;
    |
 note: calling this operator moves the value
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/unop-move-semantics.rs:20:24
+   |
+LL | fn illegal_dereference<T: Not<Output=T>>(mut x: T, y: T) {
+   |                        ^ consider constraining this type parameter with `Clone`
+...
+LL |     !*m;
+   |      -- you could clone this value
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/unop-move-semantics.rs:26:6
@@ -68,6 +93,15 @@ LL |     !*n;
    |     ||
    |     |move occurs because `*n` has type `T`, which does not implement the `Copy` trait
    |     `*n` moved due to usage in operator
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/unop-move-semantics.rs:20:24
+   |
+LL | fn illegal_dereference<T: Not<Output=T>>(mut x: T, y: T) {
+   |                        ^ consider constraining this type parameter with `Clone`
+...
+LL |     !*n;
+   |      -- you could clone this value
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr
index 4515d313ec0..03cada07a9e 100644
--- a/tests/ui/variance/variance-issue-20533.stderr
+++ b/tests/ui/variance/variance-issue-20533.stderr
@@ -14,7 +14,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value
   --> $DIR/variance-issue-20533.rs:26:1
    |
 LL | struct AffineU32(u32);
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let x = foo(&a);
+   |                     -- you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:41:14
@@ -32,7 +35,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value
   --> $DIR/variance-issue-20533.rs:26:1
    |
 LL | struct AffineU32(u32);
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let x = bar(&a);
+   |                     -- you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:47:14
@@ -50,7 +56,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value
   --> $DIR/variance-issue-20533.rs:26:1
    |
 LL | struct AffineU32(u32);
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |         let x = baz(&a);
+   |                     -- you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:53:14
diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs
index 0009ed0e34c..08b5517aae2 100644
--- a/tests/ui/weird-exprs.rs
+++ b/tests/ui/weird-exprs.rs
@@ -152,6 +152,7 @@ fn r#match() {
 }
 
 fn i_yield() {
+    #[coroutine]
     static || {
         yield yield yield yield yield yield yield yield yield;
     };