about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock65
-rw-r--r--README.md14
-rw-r--r--compiler/rustc_abi/src/lib.rs2
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl10
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs62
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs2
-rw-r--r--compiler/rustc_borrowck/messages.ftl42
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs72
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs70
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs20
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs24
-rw-r--r--compiler/rustc_borrowck/src/path_utils.rs4
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs40
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs40
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs46
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs6
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_gcc/example/std_example.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs117
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs101
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs22
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs90
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs74
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs40
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs24
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs30
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs4
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/flock.rs13
-rw-r--r--compiler/rustc_data_structures/src/lib.rs33
-rw-r--r--compiler/rustc_data_structures/src/marker.rs31
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs13
-rw-r--r--compiler/rustc_data_structures/src/sync.rs7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0626.md22
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0627.md16
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0628.md16
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0698.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0727.md8
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0790.md16
-rw-r--r--compiler/rustc_feature/src/removed.rs6
-rw-r--r--compiler/rustc_feature/src/unstable.rs12
-rw-r--r--compiler/rustc_hir/src/def.rs14
-rw-r--r--compiler/rustc_hir/src/hir.rs64
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs4
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs36
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs8
-rw-r--r--compiler/rustc_infer/messages.ftl10
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs25
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs4
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs10
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs6
-rw-r--r--compiler/rustc_lint/messages.ftl14
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/foreign_modules.rs6
-rw-r--r--compiler/rustc_lint/src/lints.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs4
-rw-r--r--compiler/rustc_lint/src/unused.rs18
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs34
-rw-r--r--compiler/rustc_metadata/src/lib.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs44
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs2
-rw-r--r--compiler/rustc_middle/messages.ftl8
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs4
-rw-r--r--compiler/rustc_middle/src/hir/nested_filter.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs5
-rw-r--r--compiler/rustc_middle/src/middle/region.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs48
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs16
-rw-r--r--compiler/rustc_middle/src/mir/query.rs28
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs52
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs6
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs30
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs4
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs10
-rw-r--r--compiler/rustc_middle/src/query/erase.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs24
-rw-r--r--compiler/rustc_middle/src/thir.rs4
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs5
-rw-r--r--compiler/rustc_middle/src/traits/select.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs14
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs10
-rw-r--r--compiler/rustc_middle/src/ty/error.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs20
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs6
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs14
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs14
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs10
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs8
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs38
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs12
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs148
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs8
-rw-r--r--compiler/rustc_middle/src/ty/util.rs66
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs2
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs34
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs86
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_build/src/errors.rs4
-rw-r--r--compiler/rustc_mir_build/src/lints.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs25
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs282
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs258
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs4
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs10
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs8
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs (renamed from compiler/rustc_mir_transform/src/generator.rs)344
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs26
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs195
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs42
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs67
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs2
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs6
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs10
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs4
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs18
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs4
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs31
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs14
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_passes/src/lang_items.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs17
-rw-r--r--compiler/rustc_session/src/code_stats.rs14
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs61
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs14
-rw-r--r--compiler/rustc_smir/src/rustc_smir/builder.rs55
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs62
-rw-r--r--compiler/rustc_span/Cargo.toml1
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs8
-rw-r--r--compiler/rustc_span/src/lib.rs21
-rw-r--r--compiler/rustc_span/src/symbol.rs6
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs12
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs28
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs34
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals/mod.rs38
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs229
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs50
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs40
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs50
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs8
-rw-r--r--compiler/rustc_ty_utils/messages.ftl2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs18
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs20
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs74
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs8
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs6
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs258
-rw-r--r--compiler/rustc_type_ir/src/debug.rs117
-rw-r--r--compiler/rustc_type_ir/src/flags.rs119
-rw-r--r--compiler/rustc_type_ir/src/fold.rs103
-rw-r--r--compiler/rustc_type_ir/src/interner.rs155
-rw-r--r--compiler/rustc_type_ir/src/lib.rs586
-rw-r--r--compiler/rustc_type_ir/src/macros.rs17
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs412
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs390
-rw-r--r--compiler/rustc_type_ir/src/ty_info.rs15
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs (renamed from compiler/rustc_type_ir/src/sty.rs)884
-rw-r--r--compiler/rustc_type_ir/src/visit.rs82
-rw-r--r--compiler/stable_mir/src/error.rs7
-rw-r--r--compiler/stable_mir/src/fold.rs2
-rw-r--r--compiler/stable_mir/src/lib.rs4
-rw-r--r--compiler/stable_mir/src/mir/body.rs49
-rw-r--r--compiler/stable_mir/src/mir/mono.rs11
-rw-r--r--compiler/stable_mir/src/ty.rs5
-rw-r--r--compiler/stable_mir/src/visitor.rs2
-rw-r--r--library/alloc/src/boxed.rs14
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/tests/autotraits.rs4
-rw-r--r--library/core/src/future/mod.rs2
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/iter/sources.rs8
-rw-r--r--library/core/src/iter/sources/from_coroutine.rs59
-rw-r--r--library/core/src/iter/sources/from_generator.rs58
-rw-r--r--library/core/src/iter/sources/once_with.rs2
-rw-r--r--library/core/src/mem/maybe_uninit.rs2
-rw-r--r--library/core/src/ops/coroutine.rs139
-rw-r--r--library/core/src/ops/generator.rs135
-rw-r--r--library/core/src/ops/mod.rs6
-rw-r--r--library/core/src/pin.rs28
-rw-r--r--library/core/src/sync/atomic.rs2
-rw-r--r--library/core/src/sync/exclusive.rs10
-rw-r--r--library/std/build.rs10
-rw-r--r--library/std/src/collections/hash/map.rs2
-rw-r--r--library/std/src/os/freebsd/fs.rs10
-rw-r--r--src/doc/unstable-book/src/language-features/closure-track-caller.md4
-rw-r--r--src/doc/unstable-book/src/language-features/coroutines.md246
-rw-r--r--src/doc/unstable-book/src/language-features/generators.md246
-rw-r--r--src/doc/unstable-book/src/the-unstable-book.md18
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/formats/item_type.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs6
-rw-r--r--src/tools/clippy/CHANGELOG.md2
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md19
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md12
-rw-r--r--src/tools/clippy/clippy_lints/src/async_yields_async.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs126
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs (renamed from src/tools/clippy/clippy_lints/src/enum_variants.rs)211
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/large_futures.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs75
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_bits.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_first.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_identity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs104
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs315
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_async_block.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_locals.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/uninit_vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs115
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs23
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml1
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs114
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs90
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/str_utils.rs53
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs6
-rw-r--r--src/tools/clippy/tests/compile-test.rs88
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/ignore.rs37
-rw-r--r--src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/ignore.rs46
-rw-r--r--src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs16
-rw-r--r--src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/impl_trait_in_params/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs16
-rw-r--r--src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr15
-rw-r--r--src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/clippy.toml (renamed from src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml)1
-rw-r--r--src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs (renamed from src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs)2
-rw-r--r--src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/clippy.toml (renamed from src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml)1
-rw-r--r--src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.rs32
-rw-r--r--src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.stderr34
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr14
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr2
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_closure.rs5
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_closure.stdout39
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_loop.rs8
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_loop.stdout48
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5238.rs2
-rw-r--r--src/tools/clippy/tests/ui/get_first.fixed13
-rw-r--r--src/tools/clippy/tests/ui/get_first.rs13
-rw-r--r--src/tools/clippy/tests/ui/get_first.stderr18
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.rs35
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.stderr30
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.rs34
-rw-r--r--src/tools/clippy/tests/ui/large_futures.fixed2
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.stderr76
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.stderr78
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.fixed4
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.rs4
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.stderr22
-rw-r--r--src/tools/clippy/tests/ui/map_identity.fixed3
-rw-r--r--src/tools/clippy/tests/ui/map_identity.rs3
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.rs1
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.stderr58
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.fixed1
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.rs1
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.stderr36
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed3
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr42
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs32
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs8
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.stderr4
-rw-r--r--src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.rs1
-rw-r--r--src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr6
-rw-r--r--src/tools/clippy/tests/ui/struct_fields.rs331
-rw-r--r--src/tools/clippy/tests/ui/struct_fields.stderr265
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed3
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs3
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr94
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs5
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr10
-rw-r--r--src/tools/clippy/triagebot.toml2
-rw-r--r--src/tools/miri/.github/workflows/ci.yml4
-rw-r--r--src/tools/miri/Cargo.lock76
-rw-r--r--src/tools/miri/Cargo.toml1
-rw-r--r--src/tools/miri/cargo-miri/Cargo.lock4
-rw-r--r--src/tools/miri/miri-script/Cargo.lock4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs6
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs5
-rw-r--r--src/tools/miri/src/helpers.rs6
-rw-r--r--src/tools/miri/src/intptrcast.rs226
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs15
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs14
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs12
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs5
-rw-r--r--src/tools/miri/src/shims/windows/sync.rs4
-rw-r--r--src/tools/miri/src/shims/x86/aesni.rs168
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs13
-rw-r--r--src/tools/miri/src/shims/x86/sse3.rs7
-rw-r--r--src/tools/miri/src/shims/x86/sse41.rs319
-rw-r--r--src/tools/miri/tests/fail/coroutine-pinned-moved.rs46
-rw-r--r--src/tools/miri/tests/fail/coroutine-pinned-moved.stderr (renamed from src/tools/miri/tests/fail/generator-pinned-moved.stderr)22
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs2
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs7
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr40
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr (renamed from src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr)0
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs55
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr19
-rw-r--r--src/tools/miri/tests/fail/generator-pinned-moved.rs46
-rw-r--r--src/tools/miri/tests/pass/calls.rs16
-rw-r--r--src/tools/miri/tests/pass/coroutine.rs (renamed from src/tools/miri/tests/pass/generator.rs)24
-rw-r--r--src/tools/miri/tests/pass/float_nan.rs7
-rw-r--r--src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs291
-rw-r--r--src/tools/miri/tests/pass/intrinsics-x86-sse41.rs315
-rw-r--r--src/tools/miri/tests/pass/move-data-across-await-point.rs2
-rw-r--r--src/tools/miri/tests/pass/panic/catch_panic.rs11
-rw-r--r--src/tools/miri/tests/pass/ptr_raw.rs2
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs (renamed from src/tools/miri/tests/pass/stacked-borrows/generators-self-referential.rs)12
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs2
-rw-r--r--src/tools/miri/tests/pass/track-caller-attribute.rs40
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs2
-rw-r--r--src/tools/miri/triagebot.toml5
-rw-r--r--src/tools/rustfmt/tests/source/immovable_coroutines.rs (renamed from src/tools/rustfmt/tests/source/immovable_generators.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/immovable_coroutines.rs (renamed from src/tools/rustfmt/tests/target/immovable_generators.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/issue_4110.rs2
-rw-r--r--tests/codegen/async-fn-debug-awaitee-field.rs2
-rw-r--r--tests/codegen/async-fn-debug-msvc.rs2
-rw-r--r--tests/codegen/coroutine-debug-msvc.rs (renamed from tests/codegen/generator-debug-msvc.rs)12
-rw-r--r--tests/codegen/coroutine-debug.rs (renamed from tests/codegen/generator-debug.rs)14
-rw-r--r--tests/coverage-map/fn_sig_into_try.cov-map53
-rw-r--r--tests/coverage-map/fn_sig_into_try.rs41
-rw-r--r--tests/coverage-map/status-quo/coroutine.cov-map (renamed from tests/coverage-map/status-quo/generator.cov-map)6
-rw-r--r--tests/coverage-map/status-quo/coroutine.rs (renamed from tests/coverage-map/status-quo/generator.rs)16
-rw-r--r--tests/coverage-map/status-quo/inline-dead.cov-map14
-rw-r--r--tests/coverage-map/status-quo/issue-84561.cov-map6
-rw-r--r--tests/coverage-map/status-quo/yield.rs24
-rw-r--r--tests/debuginfo/coroutine-locals.rs (renamed from tests/debuginfo/generator-locals.rs)4
-rw-r--r--tests/debuginfo/coroutine-objects.rs (renamed from tests/debuginfo/generator-objects.rs)30
-rw-r--r--tests/debuginfo/function-names.rs20
-rw-r--r--tests/debuginfo/issue-57822.rs10
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir (renamed from tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir)4
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir (renamed from tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir)16
-rw-r--r--tests/mir-opt/building/async_await.rs6
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir (renamed from tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir)10
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir (renamed from tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir)10
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.rs (renamed from tests/mir-opt/generator_drop_cleanup.rs)6
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir (renamed from tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir)4
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir (renamed from tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir)4
-rw-r--r--tests/mir-opt/coroutine_storage_dead_unwind.rs (renamed from tests/mir-opt/generator_storage_dead_unwind.rs)6
-rw-r--r--tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir (renamed from tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir)22
-rw-r--r--tests/mir-opt/coroutine_tiny.rs (renamed from tests/mir-opt/generator_tiny.rs)6
-rw-r--r--tests/mir-opt/inline/inline_async.rs2
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff (renamed from tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff)30
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff (renamed from tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff)30
-rw-r--r--tests/mir-opt/inline/inline_coroutine.rs (renamed from tests/mir-opt/inline/inline_generator.rs)8
-rw-r--r--tests/run-coverage/coroutine.coverage (renamed from tests/run-coverage/generator.coverage)16
-rw-r--r--tests/run-coverage/coroutine.rs (renamed from tests/run-coverage/generator.rs)16
-rw-r--r--tests/run-coverage/fn_sig_into_try.coverage45
-rw-r--r--tests/run-coverage/fn_sig_into_try.rs41
-rw-r--r--tests/run-coverage/issue-84561.coverage2
-rw-r--r--tests/run-coverage/yield.coverage24
-rw-r--r--tests/run-coverage/yield.rs24
-rw-r--r--tests/rustdoc-ui/error-in-impl-trait/closure.rs2
-rw-r--r--tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs4
-rw-r--r--tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr4
-rw-r--r--tests/ui-fulldeps/stable-mir/check_instance.rs (renamed from tests/ui-fulldeps/stable-mir/instance.rs)26
-rw-r--r--tests/ui/async-await/coroutine-desc.rs (renamed from tests/ui/async-await/generator-desc.rs)0
-rw-r--r--tests/ui/async-await/coroutine-desc.stderr (renamed from tests/ui/async-await/generator-desc.stderr)20
-rw-r--r--tests/ui/async-await/coroutine-not-future.rs (renamed from tests/ui/async-await/generator-not-future.rs)24
-rw-r--r--tests/ui/async-await/coroutine-not-future.stderr81
-rw-r--r--tests/ui/async-await/future-sizes/async-awaiting-fut.stdout6
-rw-r--r--tests/ui/async-await/generator-not-future.stderr81
-rw-r--r--tests/ui/async-await/issue-60709.rs2
-rw-r--r--tests/ui/async-await/issue-61793.rs2
-rw-r--r--tests/ui/async-await/issue-62658.rs2
-rw-r--r--tests/ui/async-await/issue-73137.rs2
-rw-r--r--tests/ui/async-await/issues/issue-51719.rs4
-rw-r--r--tests/ui/async-await/issues/issue-59972.rs2
-rw-r--r--tests/ui/async-await/issues/issue-60655-latebound-regions.rs2
-rw-r--r--tests/ui/async-await/issues/issue-64477-2.rs2
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs4
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs4
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs (renamed from tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs)10
-rw-r--r--tests/ui/async-await/non-trivial-drop.rs2
-rw-r--r--tests/ui/async-await/send-bound-async-closure.rs2
-rw-r--r--tests/ui/async-await/task-context-arg.rs2
-rw-r--r--tests/ui/async-await/unnecessary-await.rs5
-rw-r--r--tests/ui/async-await/unnecessary-await.stderr15
-rw-r--r--tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs4
-rw-r--r--tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr6
-rw-r--r--tests/ui/closures/issue-25439.rs2
-rw-r--r--tests/ui/closures/issue-25439.stderr2
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.rs (renamed from tests/ui/coherence/coherence-with-generator.rs)10
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.stock.stderr (renamed from tests/ui/coherence/coherence-with-generator.stock.stderr)8
-rw-r--r--tests/ui/coroutine/addassign-yield.rs (renamed from tests/ui/generator/addassign-yield.rs)2
-rw-r--r--tests/ui/coroutine/async-coroutine-issue-67158.rs6
-rw-r--r--tests/ui/coroutine/async-coroutine-issue-67158.stderr (renamed from tests/ui/generator/async-generator-issue-67158.stderr)4
-rw-r--r--tests/ui/coroutine/auto-trait-regions.rs (renamed from tests/ui/generator/auto-trait-regions.rs)6
-rw-r--r--tests/ui/coroutine/auto-trait-regions.stderr (renamed from tests/ui/generator/auto-trait-regions.stderr)0
-rw-r--r--tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs11
-rw-r--r--tests/ui/coroutine/auxiliary/xcrate-reachable.rs14
-rw-r--r--tests/ui/coroutine/auxiliary/xcrate.rs18
-rw-r--r--tests/ui/coroutine/borrow-in-tail-expr.rs (renamed from tests/ui/generator/borrow-in-tail-expr.rs)2
-rw-r--r--tests/ui/coroutine/borrowing.rs (renamed from tests/ui/generator/borrowing.rs)4
-rw-r--r--tests/ui/coroutine/borrowing.stderr (renamed from tests/ui/generator/borrowing.stderr)6
-rw-r--r--tests/ui/coroutine/clone-impl-async.rs (renamed from tests/ui/generator/clone-impl-async.rs)6
-rw-r--r--tests/ui/coroutine/clone-impl-async.stderr (renamed from tests/ui/generator/clone-impl-async.stderr)0
-rw-r--r--tests/ui/coroutine/clone-impl-static.rs (renamed from tests/ui/generator/clone-impl-static.rs)6
-rw-r--r--tests/ui/coroutine/clone-impl-static.stderr (renamed from tests/ui/generator/clone-impl-static.stderr)8
-rw-r--r--tests/ui/coroutine/clone-impl.rs (renamed from tests/ui/generator/clone-impl.rs)6
-rw-r--r--tests/ui/coroutine/clone-impl.stderr (renamed from tests/ui/generator/clone-impl.stderr)40
-rw-r--r--tests/ui/coroutine/conditional-drop.rs (renamed from tests/ui/generator/conditional-drop.rs)4
-rw-r--r--tests/ui/coroutine/control-flow.rs (renamed from tests/ui/generator/control-flow.rs)10
-rw-r--r--tests/ui/coroutine/coroutine-region-requirements.migrate.stderr (renamed from tests/ui/generator/generator-region-requirements.migrate.stderr)0
-rw-r--r--tests/ui/coroutine/coroutine-region-requirements.rs (renamed from tests/ui/generator/generator-region-requirements.rs)8
-rw-r--r--tests/ui/coroutine/coroutine-region-requirements.stderr (renamed from tests/ui/generator/generator-region-requirements.stderr)4
-rw-r--r--tests/ui/coroutine/coroutine-resume-after-panic.rs (renamed from tests/ui/generator/generator-resume-after-panic.rs)8
-rw-r--r--tests/ui/coroutine/coroutine-with-nll.rs (renamed from tests/ui/generator/generator-with-nll.rs)4
-rw-r--r--tests/ui/coroutine/coroutine-with-nll.stderr (renamed from tests/ui/generator/generator-with-nll.stderr)4
-rw-r--r--tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs35
-rw-r--r--tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr (renamed from tests/ui/generator/generator-yielding-or-returning-itself.stderr)32
-rw-r--r--tests/ui/coroutine/derived-drop-parent-expr.rs (renamed from tests/ui/generator/derived-drop-parent-expr.rs)2
-rw-r--r--tests/ui/coroutine/discriminant.rs (renamed from tests/ui/generator/discriminant.rs)14
-rw-r--r--tests/ui/coroutine/drop-and-replace.rs (renamed from tests/ui/generator/drop-and-replace.rs)10
-rw-r--r--tests/ui/coroutine/drop-control-flow.rs (renamed from tests/ui/generator/drop-control-flow.rs)6
-rw-r--r--tests/ui/coroutine/drop-env.rs (renamed from tests/ui/generator/drop-env.rs)4
-rw-r--r--tests/ui/coroutine/drop-track-addassign-yield.rs (renamed from tests/ui/generator/drop-track-addassign-yield.rs)2
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.rs (renamed from tests/ui/generator/drop-tracking-parent-expression.rs)2
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.stderr (renamed from tests/ui/generator/drop-tracking-parent-expression.stderr)24
-rw-r--r--tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs (renamed from tests/ui/generator/drop-tracking-yielding-in-match-guards.rs)2
-rw-r--r--tests/ui/coroutine/drop-yield-twice.rs (renamed from tests/ui/generator/drop-yield-twice.rs)4
-rw-r--r--tests/ui/coroutine/drop-yield-twice.stderr (renamed from tests/ui/generator/drop-yield-twice.stderr)8
-rw-r--r--tests/ui/coroutine/dropck-resume.rs (renamed from tests/ui/generator/dropck-resume.rs)8
-rw-r--r--tests/ui/coroutine/dropck-resume.stderr (renamed from tests/ui/generator/dropck-resume.stderr)2
-rw-r--r--tests/ui/coroutine/dropck.rs (renamed from tests/ui/generator/dropck.rs)6
-rw-r--r--tests/ui/coroutine/dropck.stderr (renamed from tests/ui/generator/dropck.stderr)8
-rw-r--r--tests/ui/coroutine/issue-102645.rs (renamed from tests/ui/generator/issue-102645.rs)4
-rw-r--r--tests/ui/coroutine/issue-102645.stderr (renamed from tests/ui/generator/issue-102645.stderr)2
-rw-r--r--tests/ui/coroutine/issue-105084.rs (renamed from tests/ui/generator/issue-105084.rs)12
-rw-r--r--tests/ui/coroutine/issue-105084.stderr (renamed from tests/ui/generator/issue-105084.stderr)10
-rw-r--r--tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs (renamed from tests/ui/generator/issue-110929-generator-conflict-error-ice.rs)2
-rw-r--r--tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.stderr (renamed from tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr)6
-rw-r--r--tests/ui/coroutine/issue-113279.rs (renamed from tests/ui/generator/issue-113279.rs)6
-rw-r--r--tests/ui/coroutine/issue-113279.stderr (renamed from tests/ui/generator/issue-113279.stderr)0
-rw-r--r--tests/ui/coroutine/issue-44197.rs (renamed from tests/ui/generator/issue-44197.rs)12
-rw-r--r--tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr (renamed from tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr)2
-rw-r--r--tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs (renamed from tests/ui/generator/issue-45729-unsafe-in-generator.rs)2
-rw-r--r--tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr (renamed from tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr)2
-rw-r--r--tests/ui/coroutine/issue-48048.rs (renamed from tests/ui/generator/issue-48048.rs)4
-rw-r--r--tests/ui/coroutine/issue-48048.stderr (renamed from tests/ui/generator/issue-48048.stderr)2
-rw-r--r--tests/ui/coroutine/issue-52304.rs11
-rw-r--r--tests/ui/coroutine/issue-52398.rs (renamed from tests/ui/generator/issue-52398.rs)6
-rw-r--r--tests/ui/coroutine/issue-52398.stderr (renamed from tests/ui/generator/issue-52398.stderr)8
-rw-r--r--tests/ui/coroutine/issue-53548-1.rs (renamed from tests/ui/generator/issue-53548-1.rs)2
-rw-r--r--tests/ui/coroutine/issue-53548.rs (renamed from tests/ui/generator/issue-53548.rs)4
-rw-r--r--tests/ui/coroutine/issue-57017.rs (renamed from tests/ui/generator/issue-57017.rs)2
-rw-r--r--tests/ui/coroutine/issue-57084.rs (renamed from tests/ui/generator/issue-57084.rs)8
-rw-r--r--tests/ui/coroutine/issue-57084.stderr (renamed from tests/ui/generator/issue-57084.stderr)4
-rw-r--r--tests/ui/coroutine/issue-57478.rs (renamed from tests/ui/generator/issue-57478.rs)2
-rw-r--r--tests/ui/coroutine/issue-58888.rs (renamed from tests/ui/generator/issue-58888.rs)6
-rw-r--r--tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs (renamed from tests/ui/generator/issue-61442-stmt-expr-with-drop.rs)4
-rw-r--r--tests/ui/coroutine/issue-62506-two_awaits.rs (renamed from tests/ui/generator/issue-62506-two_awaits.rs)2
-rw-r--r--tests/ui/coroutine/issue-64620-yield-array-element.rs9
-rw-r--r--tests/ui/coroutine/issue-64620-yield-array-element.stderr (renamed from tests/ui/generator/issue-64620-yield-array-element.stderr)2
-rw-r--r--tests/ui/coroutine/issue-68112.rs (renamed from tests/ui/generator/issue-68112.rs)26
-rw-r--r--tests/ui/coroutine/issue-68112.stderr (renamed from tests/ui/generator/issue-68112.stderr)24
-rw-r--r--tests/ui/coroutine/issue-69017.rs (renamed from tests/ui/generator/issue-69017.rs)8
-rw-r--r--tests/ui/coroutine/issue-69039.rs (renamed from tests/ui/generator/issue-69039.rs)12
-rw-r--r--tests/ui/coroutine/issue-87142.rs32
-rw-r--r--tests/ui/coroutine/issue-88653.rs (renamed from tests/ui/generator/issue-88653.rs)12
-rw-r--r--tests/ui/coroutine/issue-88653.stderr (renamed from tests/ui/generator/issue-88653.stderr)8
-rw-r--r--tests/ui/coroutine/issue-91477.rs (renamed from tests/ui/generator/issue-91477.rs)2
-rw-r--r--tests/ui/coroutine/issue-91477.stderr (renamed from tests/ui/generator/issue-91477.stderr)2
-rw-r--r--tests/ui/coroutine/issue-93161.rs (renamed from tests/ui/generator/issue-93161.rs)0
-rw-r--r--tests/ui/coroutine/iterator-count.rs (renamed from tests/ui/generator/iterator-count.rs)14
-rw-r--r--tests/ui/coroutine/layout-error.rs (renamed from tests/ui/generator/layout-error.rs)2
-rw-r--r--tests/ui/coroutine/layout-error.stderr (renamed from tests/ui/generator/layout-error.stderr)0
-rw-r--r--tests/ui/coroutine/live-upvar-across-yield.rs (renamed from tests/ui/generator/live-upvar-across-yield.rs)4
-rw-r--r--tests/ui/coroutine/match-bindings.rs (renamed from tests/ui/generator/match-bindings.rs)4
-rw-r--r--tests/ui/coroutine/match-bindings.stderr (renamed from tests/ui/generator/match-bindings.stderr)4
-rw-r--r--tests/ui/coroutine/metadata-sufficient-for-layout.rs (renamed from tests/ui/generator/metadata-sufficient-for-layout.rs)10
-rw-r--r--tests/ui/coroutine/metadata-sufficient-for-layout.stderr (renamed from tests/ui/generator/metadata-sufficient-for-layout.stderr)0
-rw-r--r--tests/ui/coroutine/nested_coroutine.rs21
-rw-r--r--tests/ui/coroutine/niche-in-coroutine.rs (renamed from tests/ui/generator/niche-in-generator.rs)4
-rw-r--r--tests/ui/coroutine/non-static-is-unpin.rs (renamed from tests/ui/generator/non-static-is-unpin.rs)4
-rw-r--r--tests/ui/coroutine/not-send-sync.rs (renamed from tests/ui/generator/not-send-sync.rs)6
-rw-r--r--tests/ui/coroutine/not-send-sync.stderr (renamed from tests/ui/generator/not-send-sync.stderr)16
-rw-r--r--tests/ui/coroutine/overlap-locals.rs (renamed from tests/ui/generator/overlap-locals.rs)2
-rw-r--r--tests/ui/coroutine/panic-drops-resume.rs (renamed from tests/ui/generator/panic-drops-resume.rs)6
-rw-r--r--tests/ui/coroutine/panic-drops.rs (renamed from tests/ui/generator/panic-drops.rs)4
-rw-r--r--tests/ui/coroutine/panic-safe.rs (renamed from tests/ui/generator/panic-safe.rs)4
-rw-r--r--tests/ui/coroutine/parent-expression.rs (renamed from tests/ui/generator/parent-expression.rs)2
-rw-r--r--tests/ui/coroutine/parent-expression.stderr (renamed from tests/ui/generator/parent-expression.stderr)24
-rw-r--r--tests/ui/coroutine/partial-drop.rs (renamed from tests/ui/generator/partial-drop.rs)2
-rw-r--r--tests/ui/coroutine/partial-initialization-across-yield.rs (renamed from tests/ui/generator/partial-initialization-across-yield.rs)4
-rw-r--r--tests/ui/coroutine/partial-initialization-across-yield.stderr (renamed from tests/ui/generator/partial-initialization-across-yield.stderr)0
-rw-r--r--tests/ui/coroutine/pattern-borrow.rs (renamed from tests/ui/generator/pattern-borrow.rs)4
-rw-r--r--tests/ui/coroutine/pattern-borrow.stderr (renamed from tests/ui/generator/pattern-borrow.stderr)2
-rw-r--r--tests/ui/coroutine/pin-box-coroutine.rs13
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-1.rs (renamed from tests/ui/generator/print/generator-print-verbose-1.rs)24
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-1.stderr (renamed from tests/ui/generator/print/generator-print-verbose-1.stderr)42
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.rs (renamed from tests/ui/generator/print/generator-print-verbose-2.rs)8
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.stderr (renamed from tests/ui/generator/print/generator-print-verbose-2.stderr)24
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-3.rs (renamed from tests/ui/generator/print/generator-print-verbose-3.rs)4
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-3.stderr (renamed from tests/ui/generator/print/generator-print-verbose-3.stderr)8
-rw-r--r--tests/ui/coroutine/reborrow-mut-upvar.rs (renamed from tests/ui/generator/reborrow-mut-upvar.rs)4
-rw-r--r--tests/ui/coroutine/reborrow-mut-upvar.stderr (renamed from tests/ui/generator/reborrow-mut-upvar.stderr)4
-rw-r--r--tests/ui/coroutine/ref-escapes-but-not-over-yield.rs (renamed from tests/ui/generator/ref-escapes-but-not-over-yield.rs)6
-rw-r--r--tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr (renamed from tests/ui/generator/ref-escapes-but-not-over-yield.stderr)8
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.rs (renamed from tests/ui/generator/ref-upvar-not-send.rs)12
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.stderr (renamed from tests/ui/generator/ref-upvar-not-send.stderr)10
-rw-r--r--tests/ui/coroutine/reinit-in-match-guard.rs (renamed from tests/ui/generator/reinit-in-match-guard.rs)2
-rw-r--r--tests/ui/coroutine/resume-after-return.rs (renamed from tests/ui/generator/resume-after-return.rs)8
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.rs (renamed from tests/ui/generator/resume-arg-late-bound.rs)8
-rw-r--r--tests/ui/coroutine/resume-arg-late-bound.stderr (renamed from tests/ui/generator/resume-arg-late-bound.stderr)6
-rw-r--r--tests/ui/coroutine/resume-arg-size.rs (renamed from tests/ui/generator/resume-arg-size.rs)8
-rw-r--r--tests/ui/coroutine/resume-live-across-yield.rs (renamed from tests/ui/generator/resume-live-across-yield.rs)8
-rw-r--r--tests/ui/coroutine/retain-resume-ref.rs (renamed from tests/ui/generator/retain-resume-ref.rs)6
-rw-r--r--tests/ui/coroutine/retain-resume-ref.stderr (renamed from tests/ui/generator/retain-resume-ref.stderr)2
-rw-r--r--tests/ui/coroutine/size-moved-locals.rs (renamed from tests/ui/generator/size-moved-locals.rs)14
-rw-r--r--tests/ui/coroutine/sized-yield.rs14
-rw-r--r--tests/ui/coroutine/sized-yield.stderr26
-rw-r--r--tests/ui/coroutine/smoke-resume-args.rs (renamed from tests/ui/generator/smoke-resume-args.rs)10
-rw-r--r--tests/ui/coroutine/smoke.rs (renamed from tests/ui/generator/smoke.rs)32
-rw-r--r--tests/ui/coroutine/static-coroutine.rs20
-rw-r--r--tests/ui/coroutine/static-mut-reference-across-yield.rs (renamed from tests/ui/generator/static-mut-reference-across-yield.rs)2
-rw-r--r--tests/ui/coroutine/static-not-unpin.current.stderr (renamed from tests/ui/generator/static-not-unpin.current.stderr)6
-rw-r--r--tests/ui/coroutine/static-not-unpin.next.stderr (renamed from tests/ui/generator/static-not-unpin.next.stderr)6
-rw-r--r--tests/ui/coroutine/static-not-unpin.rs (renamed from tests/ui/generator/static-not-unpin.rs)6
-rw-r--r--tests/ui/coroutine/static-reference-across-yield.rs (renamed from tests/ui/generator/static-reference-across-yield.rs)2
-rw-r--r--tests/ui/coroutine/too-live-local-in-immovable-gen.rs (renamed from tests/ui/generator/too-live-local-in-immovable-gen.rs)8
-rw-r--r--tests/ui/coroutine/too-live-local-in-immovable-gen.stderr (renamed from tests/ui/generator/too-live-local-in-immovable-gen.stderr)6
-rw-r--r--tests/ui/coroutine/too-many-parameters.rs8
-rw-r--r--tests/ui/coroutine/too-many-parameters.stderr (renamed from tests/ui/generator/too-many-parameters.stderr)2
-rw-r--r--tests/ui/coroutine/type-mismatch-error.rs (renamed from tests/ui/generator/type-mismatch-error.rs)6
-rw-r--r--tests/ui/coroutine/type-mismatch-error.stderr (renamed from tests/ui/generator/type-mismatch-error.stderr)0
-rw-r--r--tests/ui/coroutine/type-mismatch-signature-deduction.rs (renamed from tests/ui/generator/type-mismatch-signature-deduction.rs)6
-rw-r--r--tests/ui/coroutine/type-mismatch-signature-deduction.stderr (renamed from tests/ui/generator/type-mismatch-signature-deduction.stderr)4
-rw-r--r--tests/ui/coroutine/unresolved-ct-var.rs (renamed from tests/ui/generator/unresolved-ct-var.rs)0
-rw-r--r--tests/ui/coroutine/unresolved-ct-var.stderr (renamed from tests/ui/generator/unresolved-ct-var.stderr)0
-rw-r--r--tests/ui/coroutine/unsized-capture-across-yield.rs (renamed from tests/ui/generator/unsized-capture-across-yield.rs)8
-rw-r--r--tests/ui/coroutine/unsized-capture-across-yield.stderr (renamed from tests/ui/generator/unsized-capture-across-yield.stderr)0
-rw-r--r--tests/ui/coroutine/unsized-local-across-yield.rs (renamed from tests/ui/generator/unsized-local-across-yield.rs)8
-rw-r--r--tests/ui/coroutine/unsized-local-across-yield.stderr (renamed from tests/ui/generator/unsized-local-across-yield.stderr)0
-rw-r--r--tests/ui/coroutine/xcrate-reachable.rs (renamed from tests/ui/generator/xcrate-reachable.rs)4
-rw-r--r--tests/ui/coroutine/xcrate.rs (renamed from tests/ui/generator/xcrate.rs)10
-rw-r--r--tests/ui/coroutine/yield-in-args-rev.rs (renamed from tests/ui/generator/yield-in-args-rev.rs)4
-rw-r--r--tests/ui/coroutine/yield-in-args-rev.stderr (renamed from tests/ui/generator/yield-in-args-rev.stderr)4
-rw-r--r--tests/ui/coroutine/yield-in-args.rs (renamed from tests/ui/generator/yield-in-args.rs)2
-rw-r--r--tests/ui/coroutine/yield-in-args.stderr (renamed from tests/ui/generator/yield-in-args.stderr)2
-rw-r--r--tests/ui/coroutine/yield-in-const.rs (renamed from tests/ui/generator/yield-in-const.rs)2
-rw-r--r--tests/ui/coroutine/yield-in-const.stderr (renamed from tests/ui/generator/yield-in-const.stderr)2
-rw-r--r--tests/ui/coroutine/yield-in-function.rs (renamed from tests/ui/generator/yield-in-function.rs)2
-rw-r--r--tests/ui/coroutine/yield-in-function.stderr (renamed from tests/ui/generator/yield-in-function.stderr)2
-rw-r--r--tests/ui/coroutine/yield-in-initializer.rs (renamed from tests/ui/generator/yield-in-initializer.rs)4
-rw-r--r--tests/ui/coroutine/yield-in-initializer.stderr (renamed from tests/ui/generator/yield-in-initializer.stderr)4
-rw-r--r--tests/ui/coroutine/yield-in-static.rs (renamed from tests/ui/generator/yield-in-static.rs)2
-rw-r--r--tests/ui/coroutine/yield-in-static.stderr (renamed from tests/ui/generator/yield-in-static.stderr)2
-rw-r--r--tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs (renamed from tests/ui/generator/yield-outside-generator-issue-78653.rs)4
-rw-r--r--tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr (renamed from tests/ui/generator/yield-outside-generator-issue-78653.stderr)6
-rw-r--r--tests/ui/coroutine/yield-subtype.rs (renamed from tests/ui/generator/yield-subtype.rs)4
-rw-r--r--tests/ui/coroutine/yield-subtype.stderr (renamed from tests/ui/generator/yield-subtype.stderr)4
-rw-r--r--tests/ui/coroutine/yield-while-iterating.rs (renamed from tests/ui/generator/yield-while-iterating.rs)6
-rw-r--r--tests/ui/coroutine/yield-while-iterating.stderr (renamed from tests/ui/generator/yield-while-iterating.stderr)4
-rw-r--r--tests/ui/coroutine/yield-while-local-borrowed.rs (renamed from tests/ui/generator/yield-while-local-borrowed.rs)16
-rw-r--r--tests/ui/coroutine/yield-while-local-borrowed.stderr (renamed from tests/ui/generator/yield-while-local-borrowed.stderr)12
-rw-r--r--tests/ui/coroutine/yield-while-ref-reborrowed.rs (renamed from tests/ui/generator/yield-while-ref-reborrowed.rs)8
-rw-r--r--tests/ui/coroutine/yield-while-ref-reborrowed.stderr (renamed from tests/ui/generator/yield-while-ref-reborrowed.stderr)4
-rw-r--r--tests/ui/coroutine/yielding-in-match-guards.rs (renamed from tests/ui/generator/yielding-in-match-guards.rs)2
-rw-r--r--tests/ui/drop/dynamic-drop.rs14
-rw-r--r--tests/ui/error-codes/E0283.rs8
-rw-r--r--tests/ui/error-codes/E0283.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-closure_track_caller.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-closure_track_caller.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.rs (renamed from tests/ui/feature-gates/feature-gate-generators.rs)2
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.stderr (renamed from tests/ui/feature-gates/feature-gate-generators.stderr)16
-rw-r--r--tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs18
-rw-r--r--tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr101
-rw-r--r--tests/ui/generator/async-generator-issue-67158.rs6
-rw-r--r--tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs11
-rw-r--r--tests/ui/generator/auxiliary/xcrate-reachable.rs14
-rw-r--r--tests/ui/generator/auxiliary/xcrate.rs18
-rw-r--r--tests/ui/generator/generator-yielding-or-returning-itself.rs35
-rw-r--r--tests/ui/generator/issue-52304.rs11
-rw-r--r--tests/ui/generator/issue-64620-yield-array-element.rs9
-rw-r--r--tests/ui/generator/issue-87142.rs32
-rw-r--r--tests/ui/generator/nested_generators.rs21
-rw-r--r--tests/ui/generator/pin-box-generator.rs13
-rw-r--r--tests/ui/generator/sized-yield.rs14
-rw-r--r--tests/ui/generator/sized-yield.stderr26
-rw-r--r--tests/ui/generator/static-generators.rs20
-rw-r--r--tests/ui/generator/too-many-parameters.rs8
-rw-r--r--tests/ui/generic-associated-types/bugs/issue-100013.rs8
-rw-r--r--tests/ui/generic-associated-types/bugs/issue-100013.stderr8
-rw-r--r--tests/ui/impl-trait/bounds_regression.rs10
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.rs8
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.stderr2
-rw-r--r--tests/ui/impl-trait/lifetimes.rs4
-rw-r--r--tests/ui/impl-trait/recursive-coroutine.rs (renamed from tests/ui/impl-trait/recursive-generator.rs)10
-rw-r--r--tests/ui/impl-trait/recursive-coroutine.stderr (renamed from tests/ui/impl-trait/recursive-generator.stderr)6
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs14
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr16
-rw-r--r--tests/ui/invalid-compile-flags/invalid-llvm-passes.rs (renamed from tests/ui/invalid/invalid-llvm-passes.rs)0
-rw-r--r--tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr (renamed from tests/ui/invalid/invalid-llvm-passes.stderr)0
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs22
-rw-r--r--tests/ui/lifetimes/borrowck-let-suggestion.stderr4
-rw-r--r--tests/ui/lifetimes/issue-77175.rs2
-rw-r--r--tests/ui/lint/must_not_suspend/tuple-mismatch.rs4
-rw-r--r--tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs6
-rw-r--r--tests/ui/lint/unused/unused-closure.rs4
-rw-r--r--tests/ui/liveness/liveness-upvars.rs8
-rw-r--r--tests/ui/macros/stringify.rs2
-rw-r--r--tests/ui/mir/issue-71793-inline-args-storage.rs2
-rw-r--r--tests/ui/mir/remove-zsts-query-cycle.rs2
-rw-r--r--tests/ui/nll/coroutine-distinct-lifetime.rs (renamed from tests/ui/nll/generator-distinct-lifetime.rs)4
-rw-r--r--tests/ui/nll/coroutine-upvar-mutability.rs (renamed from tests/ui/nll/generator-upvar-mutability.rs)4
-rw-r--r--tests/ui/nll/coroutine-upvar-mutability.stderr (renamed from tests/ui/nll/generator-upvar-mutability.stderr)2
-rw-r--r--tests/ui/nll/extra-unused-mut.rs4
-rw-r--r--tests/ui/nll/issue-48623-coroutine.rs (renamed from tests/ui/nll/issue-48623-generator.rs)6
-rw-r--r--tests/ui/nll/issue-48623-coroutine.stderr (renamed from tests/ui/nll/issue-48623-generator.stderr)6
-rw-r--r--tests/ui/nll/issue-55850.rs10
-rw-r--r--tests/ui/nll/issue-55850.stderr2
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed10
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs10
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr20
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_sized_used.stderr4
-rw-r--r--tests/ui/packed/packed-struct-drop-aligned.rs8
-rw-r--r--tests/ui/polymorphization/coroutine.rs (renamed from tests/ui/polymorphization/generators.rs)24
-rw-r--r--tests/ui/polymorphization/coroutine.stderr (renamed from tests/ui/polymorphization/generators.stderr)12
-rw-r--r--tests/ui/print_type_sizes/coroutine.rs (renamed from tests/ui/print_type_sizes/generator.rs)8
-rw-r--r--tests/ui/print_type_sizes/coroutine.stdout (renamed from tests/ui/print_type_sizes/generator.stdout)2
-rw-r--r--tests/ui/print_type_sizes/coroutine_discr_placement.rs (renamed from tests/ui/print_type_sizes/generator_discr_placement.rs)4
-rw-r--r--tests/ui/print_type_sizes/coroutine_discr_placement.stdout (renamed from tests/ui/print_type_sizes/generator_discr_placement.stdout)2
-rw-r--r--tests/ui/regions/closure-in-projection-issue-97405.rs2
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs78
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr125
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs8
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs40
-rw-r--r--tests/ui/sanitize/issue-111184-coroutine-witness.rs (renamed from tests/ui/sanitize/issue-111184-generator-witness.rs)2
-rw-r--r--tests/ui/suggestions/issue-81839.stderr15
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.rs2
-rw-r--r--tests/ui/suggestions/issue-84973-blacklist.stderr4
-rw-r--r--tests/ui/suggestions/silenced-binding-typo.fixed5
-rw-r--r--tests/ui/suggestions/silenced-binding-typo.rs5
-rw-r--r--tests/ui/suggestions/silenced-binding-typo.stderr14
-rw-r--r--tests/ui/suggestions/unnamable-types.rs2
-rw-r--r--tests/ui/suggestions/unnamable-types.stderr2
-rw-r--r--tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs2
-rw-r--r--tests/ui/traits/new-solver/coroutine.fail.stderr64
-rw-r--r--tests/ui/traits/new-solver/coroutine.rs32
-rw-r--r--tests/ui/traits/new-solver/generator.fail.stderr64
-rw-r--r--tests/ui/traits/new-solver/generator.rs32
-rw-r--r--tests/ui/type-alias-impl-trait/closure_parent_substs.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs22
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs22
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs39
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs39
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-simplified.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-94429.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/issue-94429.stderr6
-rw-r--r--tests/ui/typeck/issue-36708.stderr7
-rw-r--r--tests/ui/typeck/issue-91334.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr2
-rw-r--r--tests/ui/weird-exprs.rs2
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr4
-rw-r--r--triagebot.toml18
825 files changed, 10826 insertions, 7351 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a1a02c65d94..6c96f415f44 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -25,6 +25,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "aes"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
 name = "ahash"
 version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -471,6 +482,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
 name = "clap"
 version = "4.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -543,7 +564,7 @@ dependencies = [
  "tester",
  "tokio",
  "toml 0.7.5",
- "ui_test 0.20.0",
+ "ui_test",
  "walkdir",
 ]
 
@@ -593,6 +614,7 @@ dependencies = [
  "if_chain",
  "itertools",
  "rustc-semver",
+ "serde",
 ]
 
 [[package]]
@@ -1985,6 +2007,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
 
 [[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
 name = "installer"
 version = "0.0.0"
 dependencies = [
@@ -2465,6 +2496,7 @@ dependencies = [
 name = "miri"
 version = "0.1.0"
 dependencies = [
+ "aes",
  "colored",
  "ctrlc",
  "env_logger 0.10.0",
@@ -2480,7 +2512,7 @@ dependencies = [
  "rustc_version",
  "serde",
  "smallvec",
- "ui_test 0.21.2",
+ "ui_test",
 ]
 
 [[package]]
@@ -3665,7 +3697,6 @@ version = "0.0.0"
 dependencies = [
  "arrayvec",
  "bitflags 1.3.2",
- "cfg-if",
  "elsa",
  "ena",
  "indexmap 2.0.0",
@@ -4497,7 +4528,6 @@ dependencies = [
 name = "rustc_span"
 version = "0.0.0"
 dependencies = [
- "cfg-if",
  "indexmap 2.0.0",
  "md-5",
  "rustc_arena",
@@ -5711,33 +5741,6 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
 
 [[package]]
 name = "ui_test"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd8fb9b15c8332cf51bfc2dc4830063b2446a9c9d732421b56f2478024a3971"
-dependencies = [
- "annotate-snippets",
- "anyhow",
- "bstr",
- "cargo-platform",
- "cargo_metadata 0.15.4",
- "color-eyre",
- "colored",
- "comma",
- "crossbeam-channel",
- "indicatif",
- "lazy_static",
- "levenshtein",
- "prettydiff",
- "regex",
- "rustc_version",
- "rustfix",
- "serde",
- "serde_json",
- "tempfile",
-]
-
-[[package]]
-name = "ui_test"
 version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
diff --git a/README.md b/README.md
index f0c45f341d8..a88ee4b8bf0 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,20 @@ standard library, and documentation.
 If you wish to _contribute_ to the compiler, you should read
 [CONTRIBUTING.md](CONTRIBUTING.md) instead.
 
+<details>
+<summary>Table of content</summary>
+
+- [Quick Start](#quick-start)
+- [Installing from Source](#installing-from-source)
+- [Building Documentation](#building-documentation)
+- [Notes](#notes)
+- [Getting Help](#getting-help)
+- [Contributing](#contributing)
+- [License](#license)
+- [Trademark](#trademark)
+
+</details>
+
 ## Quick Start
 
 Read ["Installation"] from [The Book].
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 3722a0774ba..8e7aa59ee34 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1502,7 +1502,7 @@ pub struct LayoutS<FieldIdx: Idx, VariantIdx: Idx> {
     /// Encodes information about multi-variant layouts.
     /// Even with `Multiple` variants, a layout still has its own fields! Those are then
     /// shared between all variants. One of them will be the discriminant,
-    /// but e.g. generators can have more.
+    /// but e.g. coroutines can have more.
     ///
     /// To access all fields of this layout, both `fields` and the fields of the active variant
     /// must be taken into account.
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index b9fe99ac72f..91591a71611 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -11,8 +11,8 @@ ast_lowering_argument = argument
 ast_lowering_assoc_ty_parentheses =
     parenthesized generic arguments cannot be used in associated type constraints
 
-ast_lowering_async_generators_not_supported =
-    `async` generators are not yet supported
+ast_lowering_async_coroutines_not_supported =
+    `async` coroutines are not yet supported
 
 ast_lowering_async_non_move_closure_not_supported =
     `async` non-`move` closures with parameters are not currently supported
@@ -42,6 +42,9 @@ ast_lowering_clobber_abi_not_supported =
 
 ast_lowering_closure_cannot_be_static = closures cannot be static
 
+ast_lowering_coroutine_too_many_parameters =
+    too many parameters for a coroutine (expected 0 or 1 parameters)
+
 ast_lowering_does_not_support_modifiers =
     the `{$class_name}` register class does not support template modifiers
 
@@ -53,9 +56,6 @@ ast_lowering_functional_record_update_destructuring_assignment =
     functional record updates are not allowed in destructuring assignments
     .suggestion = consider removing the trailing pattern
 
-ast_lowering_generator_too_many_parameters =
-    too many parameters for a generator (expected 0 or 1 parameters)
-
 ast_lowering_generic_type_with_parentheses =
     parenthesized type parameters may only be used with a `Fn` trait
     .label = only `Fn` traits may use parentheses
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index fe0c7d101c1..6e1a9eff500 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -131,8 +131,8 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_generator_too_many_parameters, code = "E0628")]
-pub struct GeneratorTooManyParameters {
+#[diag(ast_lowering_coroutine_too_many_parameters, code = "E0628")]
+pub struct CoroutineTooManyParameters {
     #[primary_span]
     pub fn_decl_span: Span,
 }
@@ -161,8 +161,8 @@ pub struct FunctionalRecordUpdateDestructuringAssignment {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_async_generators_not_supported, code = "E0727")]
-pub struct AsyncGeneratorsNotSupported {
+#[diag(ast_lowering_async_coroutines_not_supported, code = "E0727")]
+pub struct AsyncCoroutinesNotSupported {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index dda23028222..4f1b13870fd 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,8 +1,8 @@
 use super::errors::{
-    AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
-    BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignment,
-    GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
-    UnderscoreExprLhsAssign,
+    AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
+    BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
+    FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd,
+    NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
 };
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
@@ -188,7 +188,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     e.id,
                     None,
                     e.span,
-                    hir::AsyncGeneratorKind::Block,
+                    hir::AsyncCoroutineKind::Block,
                     |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
                 ),
                 ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
@@ -583,7 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    /// Lower an `async` construct to a generator that implements `Future`.
+    /// Lower an `async` construct to a coroutine that implements `Future`.
     ///
     /// This results in:
     ///
@@ -598,7 +598,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         closure_node_id: NodeId,
         ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
-        async_gen_kind: hir::AsyncGeneratorKind,
+        async_gen_kind: hir::AsyncCoroutineKind,
         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
     ) -> hir::ExprKind<'hir> {
         let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
@@ -613,7 +613,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             span: unstable_span,
         };
 
-        // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
+        // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
         let fn_decl = self.arena.alloc(hir::FnDecl {
             inputs: arena_vec![self; input_ty],
             output,
@@ -637,7 +637,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let params = arena_vec![self; param];
 
         let body = self.lower_body(move |this| {
-            this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
+            this.coroutine_kind = Some(hir::CoroutineKind::Async(async_gen_kind));
 
             let old_ctx = this.task_context;
             this.task_context = Some(task_context_hid);
@@ -710,9 +710,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// ```
     fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
         let full_span = expr.span.to(await_kw_span);
-        match self.generator_kind {
-            Some(hir::GeneratorKind::Async(_)) => {}
-            Some(hir::GeneratorKind::Gen) | None => {
+        match self.coroutine_kind {
+            Some(hir::CoroutineKind::Async(_)) => {}
+            Some(hir::CoroutineKind::Coroutine) | None => {
                 self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
                     await_kw_span,
                     item_span: self.current_item,
@@ -887,19 +887,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::ExprKind<'hir> {
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
-        let (body_id, generator_option) = self.with_new_scopes(move |this| {
+        let (body_id, coroutine_option) = self.with_new_scopes(move |this| {
             let prev = this.current_item;
             this.current_item = Some(fn_decl_span);
-            let mut generator_kind = None;
+            let mut coroutine_kind = None;
             let body_id = this.lower_fn_body(decl, |this| {
                 let e = this.lower_expr_mut(body);
-                generator_kind = this.generator_kind;
+                coroutine_kind = this.coroutine_kind;
                 e
             });
-            let generator_option =
-                this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
+            let coroutine_option =
+                this.coroutine_movability_for_fn(&decl, fn_decl_span, coroutine_kind, movability);
             this.current_item = prev;
-            (body_id, generator_option)
+            (body_id, coroutine_option)
         });
 
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
@@ -915,28 +915,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
             body: body_id,
             fn_decl_span: self.lower_span(fn_decl_span),
             fn_arg_span: Some(self.lower_span(fn_arg_span)),
-            movability: generator_option,
+            movability: coroutine_option,
             constness: self.lower_constness(constness),
         });
 
         hir::ExprKind::Closure(c)
     }
 
-    fn generator_movability_for_fn(
+    fn coroutine_movability_for_fn(
         &mut self,
         decl: &FnDecl,
         fn_decl_span: Span,
-        generator_kind: Option<hir::GeneratorKind>,
+        coroutine_kind: Option<hir::CoroutineKind>,
         movability: Movability,
     ) -> Option<hir::Movability> {
-        match generator_kind {
-            Some(hir::GeneratorKind::Gen) => {
+        match coroutine_kind {
+            Some(hir::CoroutineKind::Coroutine) => {
                 if decl.inputs.len() > 1 {
-                    self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span });
+                    self.tcx.sess.emit_err(CoroutineTooManyParameters { fn_decl_span });
                 }
                 Some(movability)
             }
-            Some(hir::GeneratorKind::Async(_)) => {
+            Some(hir::CoroutineKind::Async(_)) => {
                 panic!("non-`async` closure body turned `async` during lowering");
             }
             None => {
@@ -1005,7 +1005,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     inner_closure_id,
                     async_ret_ty,
                     body.span,
-                    hir::AsyncGeneratorKind::Closure,
+                    hir::AsyncCoroutineKind::Closure,
                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
                 );
                 let hir_id = this.lower_node_id(inner_closure_id);
@@ -1444,12 +1444,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
-        match self.generator_kind {
-            Some(hir::GeneratorKind::Gen) => {}
-            Some(hir::GeneratorKind::Async(_)) => {
-                self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span });
+        match self.coroutine_kind {
+            Some(hir::CoroutineKind::Coroutine) => {}
+            Some(hir::CoroutineKind::Async(_)) => {
+                self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span });
             }
-            None => self.generator_kind = Some(hir::GeneratorKind::Gen),
+            None => self.coroutine_kind = Some(hir::CoroutineKind::Coroutine),
         }
 
         let expr =
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index b73f21433e1..3c165f87dbf 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -82,7 +82,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             is_in_loop_condition: false,
             is_in_trait_impl: false,
             is_in_dyn_type: false,
-            generator_kind: None,
+            coroutine_kind: None,
             task_context: None,
             current_item: None,
             impl_trait_defs: Vec::new(),
@@ -974,7 +974,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         value: hir::Expr<'hir>,
     ) -> hir::BodyId {
         let body = hir::Body {
-            generator_kind: self.generator_kind,
+            coroutine_kind: self.coroutine_kind,
             params,
             value: self.arena.alloc(value),
         };
@@ -988,12 +988,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
     ) -> hir::BodyId {
-        let prev_gen_kind = self.generator_kind.take();
+        let prev_gen_kind = self.coroutine_kind.take();
         let task_context = self.task_context.take();
         let (parameters, result) = f(self);
         let body_id = self.record_body(parameters, result);
         self.task_context = task_context;
-        self.generator_kind = prev_gen_kind;
+        self.coroutine_kind = prev_gen_kind;
         body_id
     }
 
@@ -1206,7 +1206,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 closure_id,
                 None,
                 body.span,
-                hir::AsyncGeneratorKind::Fn,
+                hir::AsyncCoroutineKind::Fn,
                 |this| {
                     // Create a block from the user's function body:
                     let user_body = this.lower_block_expr(body);
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 68567f97eab..1e51449e70c 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -111,10 +111,10 @@ struct LoweringContext<'a, 'hir> {
     /// Collect items that were created by lowering the current owner.
     children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>,
 
-    generator_kind: Option<hir::GeneratorKind>,
+    coroutine_kind: Option<hir::CoroutineKind>,
 
     /// When inside an `async` context, this is the `HirId` of the
-    /// `task_context` local bound to the resume argument of the generator.
+    /// `task_context` local bound to the resume argument of the coroutine.
     task_context: Option<hir::HirId>,
 
     /// Used to get the current `fn`'s def span to point to when using `await`
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 9328b83e8f3..34532967d9e 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -554,7 +554,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         "consider removing `for<...>`"
     );
     gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
-    gate_all!(generators, "yield syntax is experimental");
+    gate_all!(coroutines, "yield syntax is experimental");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
     gate_all!(const_trait_impl, "const trait impls are experimental");
     gate_all!(
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index 2c7b97afa80..8c5a1d89709 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -1,20 +1,20 @@
 borrowck_assign_due_to_use_closure =
     assignment occurs due to use in closure
 
-borrowck_assign_due_to_use_generator =
-    assign occurs due to use in generator
+borrowck_assign_due_to_use_coroutine =
+    assign occurs due to use in coroutine
 
 borrowck_assign_part_due_to_use_closure =
     assignment to part occurs due to use in closure
 
-borrowck_assign_part_due_to_use_generator =
-    assign to part occurs due to use in generator
+borrowck_assign_part_due_to_use_coroutine =
+    assign to part occurs due to use in coroutine
 
 borrowck_borrow_due_to_use_closure =
     borrow occurs due to use in closure
 
-borrowck_borrow_due_to_use_generator =
-    borrow occurs due to use in generator
+borrowck_borrow_due_to_use_coroutine =
+    borrow occurs due to use in coroutine
 
 borrowck_calling_operator_moves_lhs =
     calling this operator moves the left-hand side
@@ -142,11 +142,11 @@ borrowck_partial_var_move_by_use_in_closure =
         *[false] moved
     } due to use in closure
 
-borrowck_partial_var_move_by_use_in_generator =
+borrowck_partial_var_move_by_use_in_coroutine =
     variable {$is_partial ->
         [true] partially moved
         *[false] moved
-    } due to use in generator
+    } due to use in coroutine
 
 borrowck_returned_async_block_escaped =
     returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
@@ -180,15 +180,15 @@ borrowck_ty_no_impl_copy =
 borrowck_use_due_to_use_closure =
     use occurs due to use in closure
 
-borrowck_use_due_to_use_generator =
-    use occurs due to use in generator
+borrowck_use_due_to_use_coroutine =
+    use occurs due to use in coroutine
 
 borrowck_used_impl_require_static =
     the used `impl` has a `'static` requirement
 
 borrowck_value_capture_here =
     value captured {$is_within ->
-        [true] here by generator
+        [true] here by coroutine
         *[false] here
     }
 
@@ -207,8 +207,8 @@ borrowck_value_moved_here =
 borrowck_var_borrow_by_use_in_closure =
     borrow occurs due to use in closure
 
-borrowck_var_borrow_by_use_in_generator =
-    borrow occurs due to use in generator
+borrowck_var_borrow_by_use_in_coroutine =
+    borrow occurs due to use in coroutine
 
 borrowck_var_borrow_by_use_place_in_closure =
     {$is_single_var ->
@@ -216,11 +216,11 @@ borrowck_var_borrow_by_use_place_in_closure =
         [false] borrows occur
     } due to use of {$place} in closure
 
-borrowck_var_borrow_by_use_place_in_generator =
+borrowck_var_borrow_by_use_place_in_coroutine =
     {$is_single_var ->
         *[true] borrow occurs
         [false] borrows occur
-    } due to use of {$place} in generator
+    } due to use of {$place} in coroutine
 
 borrowck_var_cannot_escape_closure =
     captured variable cannot escape `FnMut` closure body
@@ -234,8 +234,8 @@ borrowck_var_does_not_need_mut =
 borrowck_var_first_borrow_by_use_place_in_closure =
     first borrow occurs due to use of {$place} in closure
 
-borrowck_var_first_borrow_by_use_place_in_generator =
-    first borrow occurs due to use of {$place} in generator
+borrowck_var_first_borrow_by_use_place_in_coroutine =
+    first borrow occurs due to use of {$place} in coroutine
 
 borrowck_var_here_captured = variable captured here
 
@@ -244,8 +244,8 @@ borrowck_var_here_defined = variable defined here
 borrowck_var_move_by_use_in_closure =
     move occurs due to use in closure
 
-borrowck_var_move_by_use_in_generator =
-    move occurs due to use in generator
+borrowck_var_move_by_use_in_coroutine =
+    move occurs due to use in coroutine
 
 borrowck_var_mutable_borrow_by_use_place_in_closure =
     mutable borrow occurs due to use of {$place} in closure
@@ -253,5 +253,5 @@ borrowck_var_mutable_borrow_by_use_place_in_closure =
 borrowck_var_second_borrow_by_use_place_in_closure =
     second borrow occurs due to use of {$place} in closure
 
-borrowck_var_second_borrow_by_use_place_in_generator =
-    second borrow occurs due to use of {$place} in generator
+borrowck_var_second_borrow_by_use_place_in_coroutine =
+    second borrow occurs due to use of {$place} in coroutine
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index a2c7e767b4c..2ceec1b5658 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -368,7 +368,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
-    pub(crate) fn cannot_borrow_across_generator_yield(
+    pub(crate) fn cannot_borrow_across_coroutine_yield(
         &self,
         span: Span,
         yield_span: Span,
@@ -377,7 +377,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
             self,
             span,
             E0626,
-            "borrow may still be in use when generator yields",
+            "borrow may still be in use when coroutine yields",
         );
         err.span_label(yield_span, "possible yield occurs here");
         err
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index b719a610e07..201f0df1238 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -44,7 +44,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::MutatingUse(MutatingUseContext::Projection) |
 
         // Borrows only consider their local used at the point of the borrow.
-        // This won't affect the results since we use this analysis for generators
+        // This won't affect the results since we use this analysis for coroutines
         // and we only care about the result at suspension points. Borrows cannot
         // cross suspension points so this behavior is unproblematic.
         PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 20a4402f6f6..ecf7930ff6b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -8,7 +8,7 @@ use rustc_errors::{
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
-use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
+use rustc_hir::{AsyncCoroutineKind, CoroutineKind, LangItem};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::tcx::PlaceTy;
@@ -848,7 +848,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             match kind {
-                Some(_) => MoveUseInGenerator { var_span },
+                Some(_) => MoveUseInCoroutine { var_span },
                 None => MoveUseInClosure { var_span },
             }
         });
@@ -894,7 +894,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let desc_place = self.describe_any_place(place.as_ref());
             match kind {
                 Some(_) => {
-                    BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
+                    BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true }
                 }
                 None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
             }
@@ -926,8 +926,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let borrow_spans = self.borrow_spans(span, location);
         let span = borrow_spans.args_or_use();
 
-        let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() {
-            "generator"
+        let container_name = if issued_spans.for_coroutine() || borrow_spans.for_coroutine() {
+            "coroutine"
         } else {
             "closure"
         };
@@ -1040,7 +1040,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         |kind, var_span| {
                             use crate::session_diagnostics::CaptureVarCause::*;
                             match kind {
-                                Some(_) => BorrowUsePlaceGenerator {
+                                Some(_) => BorrowUsePlaceCoroutine {
                                     place: desc_place,
                                     var_span,
                                     is_single_var: true,
@@ -1125,7 +1125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
                 use crate::session_diagnostics::CaptureVarCause::*;
                 match kind {
-                    Some(_) => BorrowUsePlaceGenerator {
+                    Some(_) => BorrowUsePlaceCoroutine {
                         place: desc_place,
                         var_span,
                         is_single_var: false,
@@ -1146,7 +1146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
                     match kind {
                         Some(_) => {
-                            FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
+                            FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span }
                         }
                         None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
                     }
@@ -1160,7 +1160,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 |kind, var_span| {
                     use crate::session_diagnostics::CaptureVarCause::*;
                     match kind {
-                        Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
+                        Some(_) => SecondBorrowUsePlaceCoroutine { place: desc_place, var_span },
                         None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
                     }
                 },
@@ -1575,7 +1575,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         // Get closure's arguments
         let ty::Closure(_, args) = typeck_results.expr_ty(closure_expr).kind() else {
-            /* hir::Closure can be a generator too */
+            /* hir::Closure can be a coroutine too */
             return;
         };
         let sig = args.as_closure().sig();
@@ -1949,7 +1949,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             (
                 Some(name),
                 BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
-            ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
+            ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self
                 .report_escaping_closure_capture(
                     borrow_spans,
                     borrow_span,
@@ -1974,7 +1974,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     span,
                     ..
                 },
-            ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
+            ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self
                 .report_escaping_closure_capture(
                     borrow_spans,
                     borrow_span,
@@ -2077,8 +2077,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         .unwrap_or_else(|| {
                             match &self.infcx.tcx.def_kind(self.mir_def_id()) {
                                 DefKind::Closure => "enclosing closure",
-                                DefKind::Generator => "enclosing generator",
-                                kind => bug!("expected closure or generator, found {:?}", kind),
+                                DefKind::Coroutine => "enclosing coroutine",
+                                kind => bug!("expected closure or coroutine, found {:?}", kind),
                             }
                             .to_string()
                         })
@@ -2112,7 +2112,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             borrow_spans.args_subdiag(&mut err, |args_span| {
                 crate::session_diagnostics::CaptureArgLabel::Capture {
-                    is_within: borrow_spans.for_generator(),
+                    is_within: borrow_spans.for_coroutine(),
                     args_span,
                 }
             });
@@ -2263,6 +2263,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     current: usize,
                     found: usize,
                     prop_expr: Option<&'tcx hir::Expr<'tcx>>,
+                    call: Option<&'tcx hir::Expr<'tcx>>,
                 }
 
                 impl<'tcx> Visitor<'tcx> for NestedStatementVisitor<'tcx> {
@@ -2272,6 +2273,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         self.current -= 1;
                     }
                     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+                        if let hir::ExprKind::MethodCall(_, rcvr, _, _) = expr.kind {
+                            if self.span == rcvr.span.source_callsite() {
+                                self.call = Some(expr);
+                            }
+                        }
                         if self.span == expr.span.source_callsite() {
                             self.found = self.current;
                             if self.prop_expr.is_none() {
@@ -2295,6 +2301,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             current: 0,
                             found: 0,
                             prop_expr: None,
+                            call: None,
                         };
                         visitor.visit_stmt(stmt);
 
@@ -2316,6 +2323,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             && let Some(p) = sm.span_to_margin(stmt.span)
                             && let Ok(s) = sm.span_to_snippet(proper_span)
                         {
+                            if let Some(call) = visitor.call
+                                && let hir::ExprKind::MethodCall(path, _, [], _) = call.kind
+                                && path.ident.name == sym::iter
+                                && let Some(ty) = expr_ty
+                            {
+                                err.span_suggestion_verbose(
+                                    path.ident.span,
+                                    format!(
+                                        "consider consuming the `{ty}` when turning it into an \
+                                         `Iterator`",
+                                    ),
+                                    "into_iter".to_string(),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
                             if !is_format_arguments_item {
                                 let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
                                 err.multipart_suggestion_verbose(
@@ -2353,7 +2375,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         borrow_spans.args_subdiag(&mut err, |args_span| {
             crate::session_diagnostics::CaptureArgLabel::Capture {
-                is_within: borrow_spans.for_generator(),
+                is_within: borrow_spans.for_coroutine(),
                 args_span,
             }
         });
@@ -2481,14 +2503,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             Err(_) => (args_span, "move |<args>| <body>"),
         };
-        let kind = match use_span.generator_kind() {
-            Some(generator_kind) => match generator_kind {
-                GeneratorKind::Async(async_kind) => match async_kind {
-                    AsyncGeneratorKind::Block => "async block",
-                    AsyncGeneratorKind::Closure => "async closure",
+        let kind = match use_span.coroutine_kind() {
+            Some(coroutine_kind) => match coroutine_kind {
+                CoroutineKind::Async(async_kind) => match async_kind {
+                    AsyncCoroutineKind::Block => "async block",
+                    AsyncCoroutineKind::Closure => "async closure",
                     _ => bug!("async block/closure expected, but async function found."),
                 },
-                GeneratorKind::Gen => "generator",
+                CoroutineKind::Coroutine => "coroutine",
             },
             None => "closure",
         };
@@ -2517,7 +2539,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             ConstraintCategory::CallArgument(_) => {
                 fr_name.highlight_region_name(&mut err);
-                if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
+                if matches!(use_span.coroutine_kind(), Some(CoroutineKind::Async(_))) {
                     err.note(
                         "async blocks are not executed immediately and must either take a \
                          reference or ownership of outside variables they use",
@@ -2785,7 +2807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
                     use crate::session_diagnostics::CaptureVarCause::*;
                     match kind {
-                        Some(_) => BorrowUseInGenerator { var_span },
+                        Some(_) => BorrowUseInCoroutine { var_span },
                         None => BorrowUseInClosure { var_span },
                     }
                 });
@@ -2801,7 +2823,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             match kind {
-                Some(_) => BorrowUseInGenerator { var_span },
+                Some(_) => BorrowUseInCoroutine { var_span },
                 None => BorrowUseInClosure { var_span },
             }
         });
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index c9514f5604c..8a930ca59a3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -182,7 +182,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     // Otherwise, just report the whole type (and use
                     // the intentionally fuzzy phrase "destructor")
                     ty::Closure(..) => ("destructor", "closure".to_owned()),
-                    ty::Generator(..) => ("destructor", "generator".to_owned()),
+                    ty::Coroutine(..) => ("destructor", "coroutine".to_owned()),
 
                     _ => ("destructor", format!("type `{}`", local_decl.ty)),
                 };
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 8f5d5e67a7a..47a387e25e3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -8,7 +8,7 @@ use itertools::Itertools;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
-use rustc_hir::GeneratorKind;
+use rustc_hir::CoroutineKind;
 use rustc_index::IndexSlice;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::tcx::PlaceTy;
@@ -369,7 +369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ty::Array(ty, _) | ty::Slice(ty) => {
                     self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
                 }
-                ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
+                ty::Closure(def_id, _) | ty::Coroutine(def_id, _, _) => {
                     // We won't be borrowck'ing here if the closure came from another crate,
                     // so it's safe to call `expect_local`.
                     //
@@ -501,8 +501,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 pub(super) enum UseSpans<'tcx> {
     /// The access is caused by capturing a variable for a closure.
     ClosureUse {
-        /// This is true if the captured variable was from a generator.
-        generator_kind: Option<GeneratorKind>,
+        /// This is true if the captured variable was from a coroutine.
+        coroutine_kind: Option<CoroutineKind>,
         /// The span of the args of the closure, including the `move` keyword if
         /// it's present.
         args_span: Span,
@@ -569,9 +569,9 @@ impl UseSpans<'_> {
         }
     }
 
-    pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
+    pub(super) fn coroutine_kind(self) -> Option<CoroutineKind> {
         match self {
-            UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
+            UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind,
             _ => None,
         }
     }
@@ -596,14 +596,14 @@ impl UseSpans<'_> {
     ) {
         use crate::InitializationRequiringAction::*;
         use CaptureVarPathUseCause::*;
-        if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
-            match generator_kind {
+        if let UseSpans::ClosureUse { coroutine_kind, path_span, .. } = self {
+            match coroutine_kind {
                 Some(_) => {
                     err.subdiagnostic(match action {
-                        Borrow => BorrowInGenerator { path_span },
-                        MatchOn | Use => UseInGenerator { path_span },
-                        Assignment => AssignInGenerator { path_span },
-                        PartialAssignment => AssignPartInGenerator { path_span },
+                        Borrow => BorrowInCoroutine { path_span },
+                        MatchOn | Use => UseInCoroutine { path_span },
+                        Assignment => AssignInCoroutine { path_span },
+                        PartialAssignment => AssignPartInCoroutine { path_span },
                     });
                 }
                 None => {
@@ -624,9 +624,9 @@ impl UseSpans<'_> {
         handler: Option<&rustc_errors::Handler>,
         err: &mut Diagnostic,
         kind: Option<rustc_middle::mir::BorrowKind>,
-        f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
+        f: impl FnOnce(Option<CoroutineKind>, Span) -> CaptureVarCause,
     ) {
-        if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
+        if let UseSpans::ClosureUse { coroutine_kind, capture_kind_span, path_span, .. } = self {
             if capture_kind_span != path_span {
                 err.subdiagnostic(match kind {
                     Some(kd) => match kd {
@@ -642,7 +642,7 @@ impl UseSpans<'_> {
                     None => CaptureVarKind::Move { kind_span: capture_kind_span },
                 });
             };
-            let diag = f(generator_kind, path_span);
+            let diag = f(coroutine_kind, path_span);
             match handler {
                 Some(hd) => err.eager_subdiagnostic(hd, diag),
                 None => err.subdiagnostic(diag),
@@ -653,15 +653,15 @@ impl UseSpans<'_> {
     /// Returns `false` if this place is not used in a closure.
     pub(super) fn for_closure(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
+            UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_none(),
             _ => false,
         }
     }
 
-    /// Returns `false` if this place is not used in a generator.
-    pub(super) fn for_generator(&self) -> bool {
+    /// Returns `false` if this place is not used in a coroutine.
+    pub(super) fn for_coroutine(&self) -> bool {
         match *self {
-            UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
+            UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_some(),
             _ => false,
         }
     }
@@ -780,15 +780,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
         if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
-            && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) =
+            && let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) =
                 **kind
         {
             debug!("move_spans: def_id={:?} places={:?}", def_id, places);
             let def_id = def_id.expect_local();
-            if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+            if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
                 self.closure_span(def_id, moved_place, places)
             {
-                return ClosureUse { generator_kind, args_span, capture_kind_span, path_span };
+                return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
             }
         }
 
@@ -800,11 +800,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 | FakeReadCause::ForLet(Some(closure_def_id)) => {
                     debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
                     let places = &[Operand::Move(place)];
-                    if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+                    if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
                         self.closure_span(closure_def_id, moved_place, IndexSlice::from_raw(places))
                     {
                         return ClosureUse {
-                            generator_kind,
+                            coroutine_kind,
                             args_span,
                             capture_kind_span,
                             path_span,
@@ -914,21 +914,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         for stmt in statements.chain(maybe_additional_statement) {
             if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
-                let (&def_id, is_generator) = match kind {
+                let (&def_id, is_coroutine) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
-                    box AggregateKind::Generator(def_id, _, _) => (def_id, true),
+                    box AggregateKind::Coroutine(def_id, _, _) => (def_id, true),
                     _ => continue,
                 };
                 let def_id = def_id.expect_local();
 
                 debug!(
-                    "borrow_spans: def_id={:?} is_generator={:?} places={:?}",
-                    def_id, is_generator, places
+                    "borrow_spans: def_id={:?} is_coroutine={:?} places={:?}",
+                    def_id, is_coroutine, places
                 );
-                if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+                if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
                     self.closure_span(def_id, Place::from(target).as_ref(), places)
                 {
-                    return ClosureUse { generator_kind, args_span, capture_kind_span, path_span };
+                    return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
                 } else {
                     return OtherUse(use_span);
                 }
@@ -942,7 +942,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         OtherUse(use_span)
     }
 
-    /// Finds the spans of a captured place within a closure or generator.
+    /// Finds the spans of a captured place within a closure or coroutine.
     /// The first span is the location of the use resulting in the capture kind of the capture
     /// The second span is the location the use resulting in the captured path of the capture
     fn closure_span(
@@ -950,7 +950,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         def_id: LocalDefId,
         target_place: PlaceRef<'tcx>,
         places: &IndexSlice<FieldIdx, Operand<'tcx>>,
-    ) -> Option<(Span, Option<GeneratorKind>, Span, Span)> {
+    ) -> Option<(Span, Option<CoroutineKind>, Span, Span)> {
         debug!(
             "closure_span: def_id={:?} target_place={:?} places={:?}",
             def_id, target_place, places
@@ -968,11 +968,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     {
                         debug!("closure_span: found captured local {:?}", place);
                         let body = self.infcx.tcx.hir().body(body);
-                        let generator_kind = body.generator_kind();
+                        let coroutine_kind = body.coroutine_kind();
 
                         return Some((
                             fn_decl_span,
-                            generator_kind,
+                            coroutine_kind,
                             captured_place.get_capture_kind_span(self.infcx.tcx),
                             captured_place.get_path_span(self.infcx.tcx),
                         ));
@@ -1188,7 +1188,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             // another message for the same span
             if !is_loop_message {
                 move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
-                    Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
+                    Some(_) => CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial },
                     None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
                 })
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index e5ffc8a1114..003254b8da1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 local,
                 projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
-                debug_assert!(is_closure_or_generator(
+                debug_assert!(is_closure_or_coroutine(
                     Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
                 ));
 
@@ -122,7 +122,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 {
                     item_msg = access_place_desc;
                     debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref());
-                    debug_assert!(is_closure_or_generator(
+                    debug_assert!(is_closure_or_coroutine(
                         the_place_err.ty(self.body, self.infcx.tcx).ty
                     ));
 
@@ -385,7 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 local,
                 projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
-                debug_assert!(is_closure_or_generator(
+                debug_assert!(is_closure_or_coroutine(
                     Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
                 ));
 
@@ -1377,8 +1377,8 @@ fn suggest_ampmut<'tcx>(
     }
 }
 
-fn is_closure_or_generator(ty: Ty<'_>) -> bool {
-    ty.is_closure() || ty.is_generator()
+fn is_closure_or_coroutine(ty: Ty<'_>) -> bool {
+    ty.is_closure() || ty.is_coroutine()
 }
 
 /// Given a field that needs to be mutable, returns a span where the " mut " could go.
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 27072a60f65..a0a809123c0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -580,7 +580,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let err = FnMutError {
             span: *span,
             ty_err: match output_ty.kind() {
-                ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
+                ty::Coroutine(def, ..) if self.infcx.tcx.coroutine_is_async(*def) => {
                     FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
                 }
                 _ if output_ty.contains_closure() => {
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 ..
             }) => {
                 let body = map.body(*body);
-                if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                if !matches!(body.coroutine_kind, Some(hir::CoroutineKind::Async(..))) {
                     closure_span = Some(expr.span.shrink_to_lo());
                 }
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index f8883c53d57..de9ece3faba 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -41,7 +41,7 @@ pub(crate) enum RegionNameSource {
     AnonRegionFromUpvar(Span, Symbol),
     /// The region corresponding to the return type of a closure.
     AnonRegionFromOutput(RegionNameHighlight, &'static str),
-    /// The region from a type yielded by a generator.
+    /// The region from a type yielded by a coroutine.
     AnonRegionFromYieldTy(Span, String),
     /// An anonymous region from an async fn.
     AnonRegionFromAsyncFn(Span),
@@ -322,7 +322,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     let DefiningTy::Closure(_, args) = def_ty else {
-                        // Can't have BrEnv in functions, constants or generators.
+                        // Can't have BrEnv in functions, constants or coroutines.
                         bug!("BrEnv outside of closure.");
                     };
                     let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
@@ -680,16 +680,16 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     }
                     hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
                 };
-                let mir_description = match hir.body(body).generator_kind {
-                    Some(hir::GeneratorKind::Async(gen)) => match gen {
-                        hir::AsyncGeneratorKind::Block => " of async block",
-                        hir::AsyncGeneratorKind::Closure => " of async closure",
-                        hir::AsyncGeneratorKind::Fn => {
+                let mir_description = match hir.body(body).coroutine_kind {
+                    Some(hir::CoroutineKind::Async(gen)) => match gen {
+                        hir::AsyncCoroutineKind::Block => " of async block",
+                        hir::AsyncCoroutineKind::Closure => " of async closure",
+                        hir::AsyncCoroutineKind::Fn => {
                             let parent_item =
                                 hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
                             let output = &parent_item
                                 .fn_decl()
-                                .expect("generator lowered from async fn should be in fn")
+                                .expect("coroutine lowered from async fn should be in fn")
                                 .output;
                             span = output.span();
                             if let hir::FnRetTy::Return(ret) = output {
@@ -698,7 +698,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                             " of async function"
                         }
                     },
-                    Some(hir::GeneratorKind::Gen) => " of generator",
+                    Some(hir::CoroutineKind::Coroutine) => " of coroutine",
                     None => " of closure",
                 };
                 (span, mir_description, hir_ty)
@@ -793,7 +793,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         &self,
         fr: RegionVid,
     ) -> Option<RegionName> {
-        // Note: generators from `async fn` yield `()`, so we don't have to
+        // Note: coroutines from `async fn` yield `()`, so we don't have to
         // worry about them here.
         let yield_ty = self.regioncx.universal_regions().yield_ty?;
         debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty);
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 84be50a6416..7b5b52e39b1 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -161,7 +161,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             TerminatorKind::UnwindResume
             | TerminatorKind::Return
-            | TerminatorKind::GeneratorDrop => {
+            | TerminatorKind::CoroutineDrop => {
                 // Invalidate all borrows of local places
                 let borrow_set = self.borrow_set;
                 let start = self.location_table.start_index(location);
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d274a3eea6c..ee34be847cc 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -302,11 +302,11 @@ fn do_mir_borrowck<'tcx>(
         .pass_name("borrowck")
         .iterate_to_fixpoint();
 
-    let movable_generator =
-        // The first argument is the generator type passed by value
+    let movable_coroutine =
+        // The first argument is the coroutine type passed by value
         if let Some(local) = body.local_decls.raw.get(1)
         // Get the interior types and args which typeck computed
-        && let ty::Generator(_, _, hir::Movability::Static) = local.ty.kind()
+        && let ty::Coroutine(_, _, hir::Movability::Static) = local.ty.kind()
     {
         false
     } else {
@@ -323,7 +323,7 @@ fn do_mir_borrowck<'tcx>(
                 body: promoted_body,
                 move_data: &move_data,
                 location_table, // no need to create a real one for the promoted, it is not used
-                movable_generator,
+                movable_coroutine,
                 fn_self_span_reported: Default::default(),
                 locals_are_invalidated_at_exit,
                 access_place_error_reported: Default::default(),
@@ -351,7 +351,7 @@ fn do_mir_borrowck<'tcx>(
         body,
         move_data: &mdpe.move_data,
         location_table,
-        movable_generator,
+        movable_coroutine,
         locals_are_invalidated_at_exit,
         fn_self_span_reported: Default::default(),
         access_place_error_reported: Default::default(),
@@ -536,7 +536,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
     /// when MIR borrowck begins.
     location_table: &'cx LocationTable,
 
-    movable_generator: bool,
+    movable_coroutine: bool,
     /// This keeps track of whether local variables are free-ed when the function
     /// exits even without a `StorageDead`, which appears to be the case for
     /// constants.
@@ -778,7 +778,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
             | TerminatorKind::Unreachable
             | TerminatorKind::UnwindResume
             | TerminatorKind::Return
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
                 // no data used, thus irrelevant to borrowck
@@ -797,7 +797,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
 
         match term.kind {
             TerminatorKind::Yield { value: _, resume: _, resume_arg: _, drop: _ } => {
-                if self.movable_generator {
+                if self.movable_coroutine {
                     // Look for any active borrows to locals
                     let borrow_set = self.borrow_set.clone();
                     for i in flow_state.borrows.iter() {
@@ -809,7 +809,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
 
             TerminatorKind::UnwindResume
             | TerminatorKind::Return
-            | TerminatorKind::GeneratorDrop => {
+            | TerminatorKind::CoroutineDrop => {
                 // Returning from the function implicitly kills storage for all locals and statics.
                 // Often, the storage will already have been killed by an explicit
                 // StorageDead, but we don't always emit those (notably on unwind paths),
@@ -1326,7 +1326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // moved into the closure and subsequently used by the closure,
                 // in order to populate our used_mut set.
                 match **aggregate_kind {
-                    AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
+                    AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) => {
                         let def_id = def_id.expect_local();
                         let BorrowCheckResult { used_mut_upvars, .. } =
                             self.infcx.tcx.mir_borrowck(def_id);
@@ -1549,12 +1549,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// Reports an error if this is a borrow of local data.
-    /// This is called for all Yield expressions on movable generators
+    /// This is called for all Yield expressions on movable coroutines
     fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) {
         debug!("check_for_local_borrow({:?})", borrow);
 
         if borrow_of_local_data(borrow.borrowed_place) {
-            let err = self.cannot_borrow_across_generator_yield(
+            let err = self.cannot_borrow_across_coroutine_yield(
                 self.retrieve_borrow_spans(borrow).var_or_use(),
                 yield_span,
             );
diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs
index ed93a560981..51e318f0854 100644
--- a/compiler/rustc_borrowck/src/path_utils.rs
+++ b/compiler/rustc_borrowck/src/path_utils.rs
@@ -137,7 +137,7 @@ pub(super) fn is_active<'tcx>(
 }
 
 /// Determines if a given borrow is borrowing local data
-/// This is called for all Yield expressions on movable generators
+/// This is called for all Yield expressions on movable coroutines
 pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool {
     // Reborrow of already borrowed data is ignored
     // Any errors will be caught on the initial borrow
@@ -165,7 +165,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>(
     match place_ref.last_projection() {
         Some((place_base, ProjectionElem::Field(field, _ty))) => {
             let base_ty = place_base.ty(body, tcx).ty;
-            if (base_ty.is_closure() || base_ty.is_generator())
+            if (base_ty.is_closure() || base_ty.is_coroutine())
                 && (!by_ref || upvars[field.index()].by_ref)
             {
                 Some(field)
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index ca3ccf439f2..e321b92603d 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -139,23 +139,23 @@ pub(crate) enum RequireStaticErr {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum CaptureVarPathUseCause {
-    #[label(borrowck_borrow_due_to_use_generator)]
-    BorrowInGenerator {
+    #[label(borrowck_borrow_due_to_use_coroutine)]
+    BorrowInCoroutine {
         #[primary_span]
         path_span: Span,
     },
-    #[label(borrowck_use_due_to_use_generator)]
-    UseInGenerator {
+    #[label(borrowck_use_due_to_use_coroutine)]
+    UseInCoroutine {
         #[primary_span]
         path_span: Span,
     },
-    #[label(borrowck_assign_due_to_use_generator)]
-    AssignInGenerator {
+    #[label(borrowck_assign_due_to_use_coroutine)]
+    AssignInCoroutine {
         #[primary_span]
         path_span: Span,
     },
-    #[label(borrowck_assign_part_due_to_use_generator)]
-    AssignPartInGenerator {
+    #[label(borrowck_assign_part_due_to_use_coroutine)]
+    AssignPartInCoroutine {
         #[primary_span]
         path_span: Span,
     },
@@ -202,8 +202,8 @@ pub(crate) enum CaptureVarKind {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum CaptureVarCause {
-    #[label(borrowck_var_borrow_by_use_place_in_generator)]
-    BorrowUsePlaceGenerator {
+    #[label(borrowck_var_borrow_by_use_place_in_coroutine)]
+    BorrowUsePlaceCoroutine {
         is_single_var: bool,
         place: String,
         #[primary_span]
@@ -216,8 +216,8 @@ pub(crate) enum CaptureVarCause {
         #[primary_span]
         var_span: Span,
     },
-    #[label(borrowck_var_borrow_by_use_in_generator)]
-    BorrowUseInGenerator {
+    #[label(borrowck_var_borrow_by_use_in_coroutine)]
+    BorrowUseInCoroutine {
         #[primary_span]
         var_span: Span,
     },
@@ -226,8 +226,8 @@ pub(crate) enum CaptureVarCause {
         #[primary_span]
         var_span: Span,
     },
-    #[label(borrowck_var_move_by_use_in_generator)]
-    MoveUseInGenerator {
+    #[label(borrowck_var_move_by_use_in_coroutine)]
+    MoveUseInCoroutine {
         #[primary_span]
         var_span: Span,
     },
@@ -236,8 +236,8 @@ pub(crate) enum CaptureVarCause {
         #[primary_span]
         var_span: Span,
     },
-    #[label(borrowck_var_first_borrow_by_use_place_in_generator)]
-    FirstBorrowUsePlaceGenerator {
+    #[label(borrowck_var_first_borrow_by_use_place_in_coroutine)]
+    FirstBorrowUsePlaceCoroutine {
         place: String,
         #[primary_span]
         var_span: Span,
@@ -248,8 +248,8 @@ pub(crate) enum CaptureVarCause {
         #[primary_span]
         var_span: Span,
     },
-    #[label(borrowck_var_second_borrow_by_use_place_in_generator)]
-    SecondBorrowUsePlaceGenerator {
+    #[label(borrowck_var_second_borrow_by_use_place_in_coroutine)]
+    SecondBorrowUsePlaceCoroutine {
         place: String,
         #[primary_span]
         var_span: Span,
@@ -266,8 +266,8 @@ pub(crate) enum CaptureVarCause {
         #[primary_span]
         var_span: Span,
     },
-    #[label(borrowck_partial_var_move_by_use_in_generator)]
-    PartialMoveUseInGenerator {
+    #[label(borrowck_partial_var_move_by_use_in_coroutine)]
+    PartialMoveUseInCoroutine {
         #[primary_span]
         var_span: Span,
         is_partial: bool,
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index eec886b7be4..d053d0a4b3b 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         // We will not have a universal_regions.yield_ty if we yield (by accident)
-        // outside of a generator and return an `impl Trait`, so emit a delay_span_bug
+        // outside of a coroutine and return an `impl Trait`, so emit a delay_span_bug
         // because we don't want to panic in an assert here if we've already got errors.
         if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
             self.tcx().sess.delay_span_bug(
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 21da05c32dd..80e6c6c1dfb 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -101,7 +101,7 @@ pub(super) fn trace<'mir, 'tcx>(
     results.dropck_boring_locals(boring_locals);
 }
 
-/// Contextual state for the type-liveness generator.
+/// Contextual state for the type-liveness coroutine.
 struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
     /// Current type-checker, giving us our inference context etc.
     typeck: &'me mut TypeChecker<'typeck, 'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 1ec0e62d16a..9eb02be2f15 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -671,8 +671,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                         PlaceTy { ty: base_ty, variant_index: Some(index) }
                     }
                 }
-                // We do not need to handle generators here, because this runs
-                // before the generator transform stage.
+                // We do not need to handle coroutines here, because this runs
+                // before the coroutine transform stage.
                 _ => {
                     let ty = if let Some(name) = maybe_name {
                         span_mirbug_and_err!(
@@ -774,13 +774,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         let (variant, args) = match base_ty {
             PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
                 ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args),
-                ty::Generator(def_id, args, _) => {
-                    let mut variants = args.as_generator().state_tys(def_id, tcx);
+                ty::Coroutine(def_id, args, _) => {
+                    let mut variants = args.as_coroutine().state_tys(def_id, tcx);
                     let Some(mut variant) = variants.nth(variant_index.into()) else {
                         bug!(
-                            "variant_index of generator out of range: {:?}/{:?}",
+                            "variant_index of coroutine out of range: {:?}/{:?}",
                             variant_index,
-                            args.as_generator().state_tys(def_id, tcx).count()
+                            args.as_coroutine().state_tys(def_id, tcx).count()
                         );
                     };
                     return match variant.nth(field.index()) {
@@ -788,7 +788,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                         None => Err(FieldAccessError::OutOfRange { field_count: variant.count() }),
                     };
                 }
-                _ => bug!("can't have downcast of non-adt non-generator type"),
+                _ => bug!("can't have downcast of non-adt non-coroutine type"),
             },
             PlaceTy { ty, variant_index: None } => match *ty.kind() {
                 ty::Adt(adt_def, args) if !adt_def.is_enum() => {
@@ -802,13 +802,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                         }),
                     };
                 }
-                ty::Generator(_, args, _) => {
+                ty::Coroutine(_, args, _) => {
                     // Only prefix fields (upvars and current state) are
                     // accessible without a variant index.
-                    return match args.as_generator().prefix_tys().get(field.index()) {
+                    return match args.as_coroutine().prefix_tys().get(field.index()) {
                         Some(ty) => Ok(*ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: args.as_generator().prefix_tys().len(),
+                            field_count: args.as_coroutine().prefix_tys().len(),
                         }),
                     };
                 }
@@ -1351,7 +1351,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
@@ -1468,7 +1468,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                 let value_ty = value.ty(body, tcx);
                 match body.yield_ty() {
-                    None => span_mirbug!(self, term, "yield in non-generator"),
+                    None => span_mirbug!(self, term, "yield in non-coroutine"),
                     Some(ty) => {
                         if let Err(terr) = self.sub_types(
                             value_ty,
@@ -1648,9 +1648,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, block_data, "return on cleanup block")
                 }
             }
-            TerminatorKind::GeneratorDrop { .. } => {
+            TerminatorKind::CoroutineDrop { .. } => {
                 if is_cleanup {
-                    span_mirbug!(self, block_data, "generator_drop in cleanup block")
+                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
                 }
             }
             TerminatorKind::Yield { resume, drop, .. } => {
@@ -1797,14 +1797,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }),
                 }
             }
-            AggregateKind::Generator(_, args, _) => {
+            AggregateKind::Coroutine(_, args, _) => {
                 // It doesn't make sense to look at a field beyond the prefix;
                 // these require a variant index, and are not initialized in
                 // aggregate rvalues.
-                match args.as_generator().prefix_tys().get(field_index.as_usize()) {
+                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
                     Some(ty) => Ok(*ty),
                     None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_generator().prefix_tys().len(),
+                        field_count: args.as_coroutine().prefix_tys().len(),
                     }),
                 }
             }
@@ -2397,7 +2397,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 AggregateKind::Array(_) => None,
                 AggregateKind::Tuple => None,
                 AggregateKind::Closure(_, _) => None,
-                AggregateKind::Generator(_, _, _) => None,
+                AggregateKind::Coroutine(_, _, _) => None,
             },
         }
     }
@@ -2625,7 +2625,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // desugaring. A closure gets desugared to a struct, and
             // these extra requirements are basically like where
             // clauses on the struct.
-            AggregateKind::Closure(def_id, args) | AggregateKind::Generator(def_id, args, _) => {
+            AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args, _) => {
                 (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location))
             }
 
@@ -2673,7 +2673,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let parent_args = match tcx.def_kind(def_id) {
             DefKind::Closure => args.as_closure().parent_args(),
-            DefKind::Generator => args.as_generator().parent_args(),
+            DefKind::Coroutine => args.as_coroutine().parent_args(),
             DefKind::InlineConst => args.as_inline_const().parent_args(),
             other => bug!("unexpected item {:?}", other),
         };
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index c73192f4404..7897a5a63ba 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -58,7 +58,7 @@ pub struct UniversalRegions<'tcx> {
     num_universals: usize,
 
     /// The "defining" type for this function, with all universal
-    /// regions instantiated. For a closure or generator, this is the
+    /// regions instantiated. For a closure or coroutine, this is the
     /// closure type, but for a top-level function it's the `FnDef`.
     pub defining_ty: DefiningTy<'tcx>,
 
@@ -91,10 +91,10 @@ pub enum DefiningTy<'tcx> {
     /// `ClosureArgs::closure_sig_ty`.
     Closure(DefId, GenericArgsRef<'tcx>),
 
-    /// The MIR is a generator. The signature is that generators take
+    /// The MIR is a coroutine. The signature is that coroutines take
     /// no parameters and return the result of
-    /// `ClosureArgs::generator_return_ty`.
-    Generator(DefId, GenericArgsRef<'tcx>, hir::Movability),
+    /// `ClosureArgs::coroutine_return_ty`.
+    Coroutine(DefId, GenericArgsRef<'tcx>, hir::Movability),
 
     /// The MIR is a fn item with the given `DefId` and args. The signature
     /// of the function can be bound then with the `fn_sig` query.
@@ -112,13 +112,13 @@ pub enum DefiningTy<'tcx> {
 
 impl<'tcx> DefiningTy<'tcx> {
     /// Returns a list of all the upvar types for this MIR. If this is
-    /// not a closure or generator, there are no upvars, and hence it
+    /// not a closure or coroutine, there are no upvars, and hence it
     /// will be an empty list. The order of types in this list will
     /// match up with the upvar order in the HIR, typesystem, and MIR.
     pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
         match self {
             DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
-            DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(),
+            DefiningTy::Coroutine(_, args, _) => args.as_coroutine().upvar_tys(),
             DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
                 ty::List::empty()
             }
@@ -130,7 +130,7 @@ impl<'tcx> DefiningTy<'tcx> {
     /// user's code.
     pub fn implicit_inputs(self) -> usize {
         match self {
-            DefiningTy::Closure(..) | DefiningTy::Generator(..) => 1,
+            DefiningTy::Closure(..) | DefiningTy::Coroutine(..) => 1,
             DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
         }
     }
@@ -146,7 +146,7 @@ impl<'tcx> DefiningTy<'tcx> {
     pub fn def_id(&self) -> DefId {
         match *self {
             DefiningTy::Closure(def_id, ..)
-            | DefiningTy::Generator(def_id, ..)
+            | DefiningTy::Coroutine(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
             | DefiningTy::Const(def_id, ..)
             | DefiningTy::InlineConst(def_id, ..) => def_id,
@@ -178,7 +178,7 @@ pub enum RegionClassification {
     Global,
 
     /// An **external** region is only relevant for
-    /// closures, generators, and inline consts. In that
+    /// closures, coroutines, and inline consts. In that
     /// case, it refers to regions that are free in the type
     /// -- basically, something bound in the surrounding context.
     ///
@@ -196,7 +196,7 @@ pub enum RegionClassification {
     /// Here, the lifetimes `'a` and `'b` would be **external** to the
     /// closure.
     ///
-    /// If we are not analyzing a closure/generator/inline-const,
+    /// If we are not analyzing a closure/coroutine/inline-const,
     /// there are no external lifetimes.
     External,
 
@@ -354,7 +354,7 @@ impl<'tcx> UniversalRegions<'tcx> {
                     err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
                 });
             }
-            DefiningTy::Generator(def_id, args, _) => {
+            DefiningTy::Coroutine(def_id, args, _) => {
                 let v = with_no_trimmed_paths!(
                     args[tcx.generics_of(def_id).parent_count..]
                         .iter()
@@ -362,7 +362,7 @@ impl<'tcx> UniversalRegions<'tcx> {
                         .collect::<Vec<_>>()
                 );
                 err.note(format!(
-                    "defining type: {} with generator args [\n    {},\n]",
+                    "defining type: {} with coroutine args [\n    {},\n]",
                     tcx.def_path_str_with_args(def_id, args),
                     v.join(",\n    "),
                 ));
@@ -426,13 +426,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
         let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
 
-        // If this is a 'root' body (not a closure/generator/inline const), then
+        // If this is a 'root' body (not a closure/coroutine/inline const), then
         // there are no extern regions, so the local regions start at the same
         // position as the (empty) sub-list of extern regions
         let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
             first_extern_index
         } else {
-            // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
+            // If this is a closure, coroutine, or inline-const, then the late-bound regions from the enclosing
             // function/closures are actually external regions to us. For example, here, 'a is not local
             // to the closure c (although it is local to the fn foo):
             // fn foo<'a>() {
@@ -528,7 +528,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         debug!("build: local regions  = {}..{}", first_local_index, num_universals);
 
         let yield_ty = match defining_ty {
-            DefiningTy::Generator(_, args, _) => Some(args.as_generator().yield_ty()),
+            DefiningTy::Coroutine(_, args, _) => Some(args.as_coroutine().yield_ty()),
             _ => None,
         };
 
@@ -563,8 +563,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
                 match *defining_ty.kind() {
                     ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
-                    ty::Generator(def_id, args, movability) => {
-                        DefiningTy::Generator(def_id, args, movability)
+                    ty::Coroutine(def_id, args, movability) => {
+                        DefiningTy::Coroutine(def_id, args, movability)
                     }
                     ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
                     _ => span_bug!(
@@ -621,7 +621,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
         let fr_args = match defining_ty {
             DefiningTy::Closure(_, args)
-            | DefiningTy::Generator(_, args, _)
+            | DefiningTy::Coroutine(_, args, _)
             | DefiningTy::InlineConst(_, args) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureArgs are
@@ -686,13 +686,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 )
             }
 
-            DefiningTy::Generator(def_id, args, movability) => {
+            DefiningTy::Coroutine(def_id, args, movability) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
-                let resume_ty = args.as_generator().resume_ty();
-                let output = args.as_generator().return_ty();
-                let generator_ty = Ty::new_generator(tcx, def_id, args, movability);
+                let resume_ty = args.as_coroutine().resume_ty();
+                let output = args.as_coroutine().return_ty();
+                let coroutine_ty = Ty::new_coroutine(tcx, def_id, args, movability);
                 let inputs_and_output =
-                    self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]);
+                    self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
                 ty::Binder::dummy(inputs_and_output)
             }
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 9c57f68f0b8..c7999a226c7 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -179,7 +179,7 @@ fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
 }
 
 /// A folder used to remove any entry points (like fn main) because the harness
-/// generator will provide its own
+/// coroutine will provide its own
 struct EntryPointCleaner<'a> {
     // Current depth in the ast
     sess: &'a Session,
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 490cc2404f6..9bd2ab5c638 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -1,7 +1,7 @@
 #![feature(
     core_intrinsics,
-    generators,
-    generator_trait,
+    coroutines,
+    coroutine_trait,
     is_sorted,
     repr_simd,
     tuple_trait,
@@ -12,7 +12,7 @@
 use std::arch::x86_64::*;
 use std::hint::black_box;
 use std::io::Write;
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 fn main() {
     println!("{:?}", std::env::args().collect::<Vec<_>>());
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 3b2a12ec028..c83efa51e9e 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -157,7 +157,7 @@ rm -r tests/run-make/compressed-debuginfo
 
 rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
 
-rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug with Generator's
+rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug with Coroutine's
 
 # bugs in the test suite
 # ======================
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index ac7389792c8..80e7c5bd9ed 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -478,7 +478,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
             TerminatorKind::Yield { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::GeneratorDrop => {
+            | TerminatorKind::CoroutineDrop => {
                 bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
             }
             TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 1cb6fa07723..b0853d30e03 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -510,7 +510,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                     | TerminatorKind::Drop { .. }
                     | TerminatorKind::Assert { .. } => {}
                     TerminatorKind::Yield { .. }
-                    | TerminatorKind::GeneratorDrop
+                    | TerminatorKind::CoroutineDrop
                     | TerminatorKind::FalseEdge { .. }
                     | TerminatorKind::FalseUnwind { .. } => unreachable!(),
                     TerminatorKind::InlineAsm { .. } => return None,
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index 18f2ddcde12..dc0aad04a78 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -1,9 +1,9 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
 
 #[cfg(feature="master")]
 use std::arch::x86_64::*;
 use std::io::Write;
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 extern {
     pub fn printf(format: *const i8, ...) -> i32;
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index c2eab295acd..357ce622659 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
         // FIXME(eddyb) producing readable type names for trait objects can result
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
-        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str
+        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
@@ -98,10 +98,10 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
+            if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap();
+                write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
             }
             Some(name)
         }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 411620c9e49..2f825b801ac 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -4,14 +4,16 @@ use crate::coverageinfo::ffi::CounterMappingRegion;
 use crate::coverageinfo::map_data::FunctionCoverage;
 use crate::llvm;
 
-use rustc_codegen_ssa::traits::ConstMethods;
+use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
 use rustc_middle::bug;
+use rustc_middle::mir;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::DefIdSet;
 use rustc_span::Symbol;
 
 /// Generates and exports the Coverage Map.
@@ -94,8 +96,14 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
     // Generate the LLVM IR representation of the coverage map and store it in a well-known global
     let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
 
+    let mut unused_function_names = Vec::new();
+
     let covfun_section_name = coverageinfo::covfun_section_name(cx);
     for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
+        if !is_used {
+            unused_function_names.push(mangled_function_name);
+        }
+
         save_function_record(
             cx,
             &covfun_section_name,
@@ -107,6 +115,25 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
         );
     }
 
+    // For unused functions, we need to take their mangled names and store them
+    // in a specially-named global array. LLVM's `InstrProfiling` pass will
+    // detect this global and include those names in its `__llvm_prf_names`
+    // section. (See `llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp`.)
+    if !unused_function_names.is_empty() {
+        assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
+
+        let name_globals = unused_function_names
+            .into_iter()
+            .map(|mangled_function_name| cx.const_str(mangled_function_name).0)
+            .collect::<Vec<_>>();
+        let initializer = cx.const_array(cx.type_ptr(), &name_globals);
+
+        let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), "__llvm_coverage_names");
+        llvm::set_global_constant(array, true);
+        llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
+        llvm::set_initializer(array, initializer);
+    }
+
     // Save the coverage data value to LLVM IR
     coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
 }
@@ -287,13 +314,12 @@ fn save_function_record(
 /// `-Clink-dead-code` will not generate code for unused generic functions.)
 ///
 /// We can find the unused functions (including generic functions) by the set difference of all MIR
-/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query
-/// `codegened_and_inlined_items`).
+/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`codegenned_and_inlined_items`).
 ///
-/// These unused functions are then codegen'd in one of the CGUs which is marked as the
-/// "code coverage dead code cgu" during the partitioning process. This prevents us from generating
-/// code regions for the same function more than once which can lead to linker errors regarding
-/// duplicate symbols.
+/// These unused functions don't need to be codegenned, but we do need to add them to the function
+/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
+/// We also end up adding their symbol names to a special global array that LLVM will include in
+/// its embedded coverage data.
 fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
     assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
 
@@ -313,7 +339,7 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
             // generic functions from consideration as well.
             if !matches!(
                 kind,
-                DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator
+                DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Coroutine
             ) {
                 return None;
             }
@@ -324,19 +350,80 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
         })
         .collect();
 
-    let codegenned_def_ids = tcx.codegened_and_inlined_items(());
+    let codegenned_def_ids = codegenned_and_inlined_items(tcx);
 
-    for non_codegenned_def_id in
-        eligible_def_ids.into_iter().filter(|id| !codegenned_def_ids.contains(id))
-    {
+    // For each `DefId` that should have coverage instrumentation but wasn't
+    // codegenned, add it to the function coverage map as an unused function.
+    for def_id in eligible_def_ids.into_iter().filter(|id| !codegenned_def_ids.contains(id)) {
         // Skip any function that didn't have coverage data added to it by the
         // coverage instrumentor.
-        let body = tcx.instance_mir(ty::InstanceDef::Item(non_codegenned_def_id));
+        let body = tcx.instance_mir(ty::InstanceDef::Item(def_id));
         let Some(function_coverage_info) = body.function_coverage_info.as_deref() else {
             continue;
         };
 
-        debug!("generating unused fn: {:?}", non_codegenned_def_id);
-        cx.define_unused_fn(non_codegenned_def_id, function_coverage_info);
+        debug!("generating unused fn: {def_id:?}");
+        let instance = declare_unused_fn(tcx, def_id);
+        add_unused_function_coverage(cx, instance, function_coverage_info);
+    }
+}
+
+/// All items participating in code generation together with (instrumented)
+/// items inlined into them.
+fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet {
+    let (items, cgus) = tcx.collect_and_partition_mono_items(());
+    let mut visited = DefIdSet::default();
+    let mut result = items.clone();
+
+    for cgu in cgus {
+        for item in cgu.items().keys() {
+            if let mir::mono::MonoItem::Fn(ref instance) = item {
+                let did = instance.def_id();
+                if !visited.insert(did) {
+                    continue;
+                }
+                let body = tcx.instance_mir(instance.def);
+                for block in body.basic_blocks.iter() {
+                    for statement in &block.statements {
+                        let mir::StatementKind::Coverage(_) = statement.kind else { continue };
+                        let scope = statement.source_info.scope;
+                        if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
+                            result.insert(inlined.def_id());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    result
+}
+
+fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tcx> {
+    ty::Instance::new(
+        def_id,
+        ty::GenericArgs::for_item(tcx, def_id, |param, _| {
+            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                tcx.lifetimes.re_erased.into()
+            } else {
+                tcx.mk_param_from_def(param)
+            }
+        }),
+    )
+}
+
+fn add_unused_function_coverage<'tcx>(
+    cx: &CodegenCx<'_, 'tcx>,
+    instance: ty::Instance<'tcx>,
+    function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
+) {
+    // An unused function's mappings will automatically be rewritten to map to
+    // zero, because none of its counters/expressions are marked as seen.
+    let function_coverage = FunctionCoverage::unused(instance, function_coverage_info);
+
+    if let Some(coverage_context) = cx.coverage_context() {
+        coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage);
+    } else {
+        bug!("Could not get the `coverage_context`");
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 204a73b788a..cf7c7e6be60 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -1,6 +1,5 @@
 use crate::llvm;
 
-use crate::abi::Abi;
 use crate::builder::Builder;
 use crate::common::CodegenCx;
 use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
@@ -12,17 +11,12 @@ use rustc_codegen_ssa::traits::{
     StaticMethods,
 };
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_llvm::RustString;
 use rustc_middle::bug;
-use rustc_middle::mir::coverage::{CounterId, CoverageKind, FunctionCoverageInfo};
+use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::Coverage;
-use rustc_middle::ty;
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use rustc_middle::ty::GenericArgs;
+use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::Instance;
-use rustc_middle::ty::Ty;
 
 use std::cell::RefCell;
 
@@ -30,8 +24,6 @@ pub(crate) mod ffi;
 pub(crate) mod map_data;
 pub mod mapgen;
 
-const UNUSED_FUNCTION_COUNTER_ID: CounterId = CounterId::START;
-
 const VAR_ALIGN_BYTES: usize = 8;
 
 /// A context object for maintaining all state needed by the coverageinfo module.
@@ -76,25 +68,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             bug!("Could not get the `coverage_context`");
         }
     }
-
-    /// Functions with MIR-based coverage are normally codegenned _only_ if
-    /// called. LLVM coverage tools typically expect every function to be
-    /// defined (even if unused), with at least one call to LLVM intrinsic
-    /// `instrprof.increment`.
-    ///
-    /// Codegen a small function that will never be called, with one counter
-    /// that will never be incremented.
-    ///
-    /// For used/called functions, the coverageinfo was already added to the
-    /// `function_coverage_map` (keyed by function `Instance`) during codegen.
-    /// But in this case, since the unused function was _not_ previously
-    /// codegenned, collect the function coverage info from MIR and add an
-    /// "unused" entry to the function coverage map.
-    fn define_unused_fn(&self, def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo) {
-        let instance = declare_unused_fn(self, def_id);
-        codegen_unused_fn_and_counter(self, instance);
-        add_unused_function_coverage(self, instance, function_coverage_info);
-    }
 }
 
 impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
@@ -159,76 +132,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
     }
 }
 
-fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<'tcx> {
-    let tcx = cx.tcx;
-
-    let instance = Instance::new(
-        def_id,
-        GenericArgs::for_item(tcx, def_id, |param, _| {
-            if let ty::GenericParamDefKind::Lifetime = param.kind {
-                tcx.lifetimes.re_erased.into()
-            } else {
-                tcx.mk_param_from_def(param)
-            }
-        }),
-    );
-
-    let llfn = cx.declare_fn(
-        tcx.symbol_name(instance).name,
-        cx.fn_abi_of_fn_ptr(
-            ty::Binder::dummy(tcx.mk_fn_sig(
-                [Ty::new_unit(tcx)],
-                Ty::new_unit(tcx),
-                false,
-                hir::Unsafety::Unsafe,
-                Abi::Rust,
-            )),
-            ty::List::empty(),
-        ),
-        None,
-    );
-
-    llvm::set_linkage(llfn, llvm::Linkage::PrivateLinkage);
-    llvm::set_visibility(llfn, llvm::Visibility::Default);
-
-    assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none());
-
-    instance
-}
-
-fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) {
-    let llfn = cx.get_fn(instance);
-    let llbb = Builder::append_block(cx, llfn, "unused_function");
-    let mut bx = Builder::build(cx, llbb);
-    let fn_name = bx.get_pgo_func_name_var(instance);
-    let hash = bx.const_u64(0);
-    let num_counters = bx.const_u32(1);
-    let index = bx.const_u32(u32::from(UNUSED_FUNCTION_COUNTER_ID));
-    debug!(
-        "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?},
-            index={:?}) for unused function: {:?}",
-        fn_name, hash, num_counters, index, instance
-    );
-    bx.instrprof_increment(fn_name, hash, num_counters, index);
-    bx.ret_void();
-}
-
-fn add_unused_function_coverage<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
-    instance: Instance<'tcx>,
-    function_coverage_info: &'tcx FunctionCoverageInfo,
-) {
-    // An unused function's mappings will automatically be rewritten to map to
-    // zero, because none of its counters/expressions are marked as seen.
-    let function_coverage = FunctionCoverage::unused(instance, function_coverage_info);
-
-    if let Some(coverage_context) = cx.coverage_context() {
-        coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage);
-    } else {
-        bug!("Could not get the `coverage_context`");
-    }
-}
-
 /// Calls llvm::createPGOFuncNameVar() with the given function instance's
 /// mangled function name. The LLVM API returns an llvm::GlobalVariable
 /// containing the function name, with the specific variable name and linkage
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 4f8ae2ddb8f..865bf01c8c1 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -460,7 +460,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
         }
         ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
         ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
-        ty::Generator(..) => enums::build_generator_di_node(cx, unique_type_id),
+        ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id),
         ty::Adt(def, ..) => match def.adt_kind() {
             AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id),
             AdtKind::Union => build_union_type_di_node(cx, unique_type_id),
@@ -1026,20 +1026,20 @@ fn build_struct_type_di_node<'ll, 'tcx>(
 // Tuples
 //=-----------------------------------------------------------------------------
 
-/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
-/// For a generator, this will handle upvars shared by all states.
+/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or coroutine.
+/// For a coroutine, this will handle upvars shared by all states.
 fn build_upvar_field_di_nodes<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
-    closure_or_generator_ty: Ty<'tcx>,
-    closure_or_generator_di_node: &'ll DIType,
+    closure_or_coroutine_ty: Ty<'tcx>,
+    closure_or_coroutine_di_node: &'ll DIType,
 ) -> SmallVec<&'ll DIType> {
-    let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() {
-        ty::Generator(def_id, args, _) => (def_id, args.as_generator().prefix_tys()),
+    let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() {
+        ty::Coroutine(def_id, args, _) => (def_id, args.as_coroutine().prefix_tys()),
         ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
         _ => {
             bug!(
-                "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}",
-                closure_or_generator_ty
+                "build_upvar_field_di_nodes() called with non-closure-or-coroutine-type: {:?}",
+                closure_or_coroutine_ty
             )
         }
     };
@@ -1049,7 +1049,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
     );
 
     let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
-    let layout = cx.layout_of(closure_or_generator_ty);
+    let layout = cx.layout_of(closure_or_coroutine_ty);
 
     up_var_tys
         .into_iter()
@@ -1058,7 +1058,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
         .map(|(index, (up_var_ty, capture_name))| {
             build_field_di_node(
                 cx,
-                closure_or_generator_di_node,
+                closure_or_coroutine_di_node,
                 capture_name.as_str(),
                 cx.size_and_align_of(up_var_ty),
                 layout.fields.offset(index),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 88040557a9b..ca7bfbeac25 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -12,7 +12,7 @@ use rustc_middle::{
     ty::{
         self,
         layout::{LayoutOf, TyAndLayout},
-        AdtDef, GeneratorArgs, Ty,
+        AdtDef, CoroutineArgs, Ty,
     },
 };
 use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
@@ -268,18 +268,18 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     )
 }
 
-/// A generator debuginfo node looks the same as a that of an enum type.
+/// A coroutine debuginfo node looks the same as a that of an enum type.
 ///
 /// See [build_enum_type_di_node] for more information.
-pub(super) fn build_generator_di_node<'ll, 'tcx>(
+pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
-    let generator_type = unique_type_id.expect_ty();
-    let generator_type_and_layout = cx.layout_of(generator_type);
-    let generator_type_name = compute_debuginfo_type_name(cx.tcx, generator_type, false);
+    let coroutine_type = unique_type_id.expect_ty();
+    let coroutine_type_and_layout = cx.layout_of(coroutine_type);
+    let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
 
-    debug_assert!(!wants_c_like_enum_debuginfo(generator_type_and_layout));
+    debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
 
     type_map::build_type_with_children(
         cx,
@@ -287,24 +287,24 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
             cx,
             type_map::Stub::Union,
             unique_type_id,
-            &generator_type_name,
-            size_and_align_of(generator_type_and_layout),
+            &coroutine_type_name,
+            size_and_align_of(coroutine_type_and_layout),
             NO_SCOPE_METADATA,
             DIFlags::FlagZero,
         ),
-        |cx, generator_type_di_node| match generator_type_and_layout.variants {
+        |cx, coroutine_type_di_node| match coroutine_type_and_layout.variants {
             Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => {
-                build_union_fields_for_direct_tag_generator(
+                build_union_fields_for_direct_tag_coroutine(
                     cx,
-                    generator_type_and_layout,
-                    generator_type_di_node,
+                    coroutine_type_and_layout,
+                    coroutine_type_di_node,
                 )
             }
             Variants::Single { .. }
             | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
                 bug!(
-                    "Encountered generator with non-direct-tag layout: {:?}",
-                    generator_type_and_layout
+                    "Encountered coroutine with non-direct-tag layout: {:?}",
+                    coroutine_type_and_layout
                 )
             }
         },
@@ -428,7 +428,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
         })
         .collect();
 
-    build_union_fields_for_direct_tag_enum_or_generator(
+    build_union_fields_for_direct_tag_enum_or_coroutine(
         cx,
         enum_type_and_layout,
         enum_type_di_node,
@@ -469,8 +469,8 @@ fn build_variant_names_type_di_node<'ll, 'tcx>(
 
 fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
-    enum_or_generator_type_and_layout: TyAndLayout<'tcx>,
-    enum_or_generator_type_di_node: &'ll DIType,
+    enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
+    enum_or_coroutine_type_di_node: &'ll DIType,
     variant_index: VariantIdx,
     untagged_variant_index: Option<VariantIdx>,
     variant_struct_type_di_node: &'ll DIType,
@@ -486,13 +486,13 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             UniqueTypeId::for_enum_variant_struct_type_wrapper(
                 cx.tcx,
-                enum_or_generator_type_and_layout.ty,
+                enum_or_coroutine_type_and_layout.ty,
                 variant_index,
             ),
             &variant_struct_wrapper_type_name(variant_index),
             // NOTE: We use size and align of enum_type, not from variant_layout:
-            size_and_align_of(enum_or_generator_type_and_layout),
-            Some(enum_or_generator_type_di_node),
+            size_and_align_of(enum_or_coroutine_type_and_layout),
+            Some(enum_or_coroutine_type_di_node),
             DIFlags::FlagZero,
         ),
         |cx, wrapper_struct_type_di_node| {
@@ -535,7 +535,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
                 cx,
                 wrapper_struct_type_di_node,
                 "value",
-                size_and_align_of(enum_or_generator_type_and_layout),
+                size_and_align_of(enum_or_coroutine_type_and_layout),
                 Size::ZERO,
                 DIFlags::FlagZero,
                 variant_struct_type_di_node,
@@ -662,40 +662,40 @@ fn split_128(value: u128) -> Split128 {
     Split128 { hi: (value >> 64) as u64, lo: value as u64 }
 }
 
-fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
+fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
-    generator_type_and_layout: TyAndLayout<'tcx>,
-    generator_type_di_node: &'ll DIType,
+    coroutine_type_and_layout: TyAndLayout<'tcx>,
+    coroutine_type_di_node: &'ll DIType,
 ) -> SmallVec<&'ll DIType> {
     let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
-        generator_type_and_layout.variants
+        coroutine_type_and_layout.variants
     else {
         bug!("This function only supports layouts with directly encoded tags.")
     };
 
-    let (generator_def_id, generator_args) = match generator_type_and_layout.ty.kind() {
-        &ty::Generator(def_id, args, _) => (def_id, args.as_generator()),
+    let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() {
+        &ty::Coroutine(def_id, args, _) => (def_id, args.as_coroutine()),
         _ => unreachable!(),
     };
 
-    let generator_layout = cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
+    let coroutine_layout = cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
 
-    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
-    let variant_range = generator_args.variant_range(generator_def_id, cx.tcx);
+    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
+    let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
     let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
 
-    let tag_base_type = tag_base_type(cx, generator_type_and_layout);
+    let tag_base_type = tag_base_type(cx, coroutine_type_and_layout);
 
     let variant_names_type_di_node = build_variant_names_type_di_node(
         cx,
-        generator_type_di_node,
+        coroutine_type_di_node,
         variant_range
             .clone()
-            .map(|variant_index| (variant_index, GeneratorArgs::variant_name(variant_index))),
+            .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
     );
 
     let discriminants: IndexVec<VariantIdx, DiscrResult> = {
-        let discriminants_iter = generator_args.discriminants(generator_def_id, cx.tcx);
+        let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
         let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
             IndexVec::with_capacity(variant_count);
         for (variant_index, discr) in discriminants_iter {
@@ -709,16 +709,16 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
     // Build the type node for each field.
     let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
         .map(|variant_index| {
-            let variant_struct_type_di_node = super::build_generator_variant_struct_type_di_node(
+            let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
                 cx,
                 variant_index,
-                generator_type_and_layout,
-                generator_type_di_node,
-                generator_layout,
+                coroutine_type_and_layout,
+                coroutine_type_di_node,
+                coroutine_layout,
                 &common_upvar_names,
             );
 
-            let span = generator_layout.variant_source_info[variant_index].span;
+            let span = coroutine_layout.variant_source_info[variant_index].span;
             let source_info = if !span.is_dummy() {
                 let loc = cx.lookup_debug_loc(span.lo());
                 Some((file_metadata(cx, &loc.file), loc.line as c_uint))
@@ -735,10 +735,10 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
         })
         .collect();
 
-    build_union_fields_for_direct_tag_enum_or_generator(
+    build_union_fields_for_direct_tag_enum_or_coroutine(
         cx,
-        generator_type_and_layout,
-        generator_type_di_node,
+        coroutine_type_and_layout,
+        coroutine_type_di_node,
         &variant_field_infos[..],
         variant_names_type_di_node,
         tag_base_type,
@@ -747,9 +747,9 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
     )
 }
 
-/// This is a helper function shared between enums and generators that makes sure fields have the
+/// This is a helper function shared between enums and coroutines that makes sure fields have the
 /// expect names.
-fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
+fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     enum_type_and_layout: TyAndLayout<'tcx>,
     enum_type_di_node: &'ll DIType,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index d3239d5c358..df1df6d197e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -6,11 +6,11 @@ use rustc_hir::def::CtorKind;
 use rustc_index::IndexSlice;
 use rustc_middle::{
     bug,
-    mir::GeneratorLayout,
+    mir::CoroutineLayout,
     ty::{
         self,
         layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
-        AdtDef, GeneratorArgs, Ty, VariantDef,
+        AdtDef, CoroutineArgs, Ty, VariantDef,
     },
 };
 use rustc_span::Symbol;
@@ -66,14 +66,14 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     }
 }
 
-pub(super) fn build_generator_di_node<'ll, 'tcx>(
+pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     if cpp_like_debuginfo(cx.tcx) {
-        cpp_like::build_generator_di_node(cx, unique_type_id)
+        cpp_like::build_coroutine_di_node(cx, unique_type_id)
     } else {
-        native::build_generator_di_node(cx, unique_type_id)
+        native::build_coroutine_di_node(cx, unique_type_id)
     }
 }
 
@@ -101,13 +101,13 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
     }
 }
 
-/// Extract the type with which we want to describe the tag of the given enum or generator.
+/// Extract the type with which we want to describe the tag of the given enum or coroutine.
 fn tag_base_type<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     enum_type_and_layout: TyAndLayout<'tcx>,
 ) -> Ty<'tcx> {
     debug_assert!(match enum_type_and_layout.ty.kind() {
-        ty::Generator(..) => true,
+        ty::Coroutine(..) => true,
         ty::Adt(adt_def, _) => adt_def.is_enum(),
         _ => false,
     });
@@ -300,8 +300,8 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
     .di_node
 }
 
-/// Build the struct type for describing a single generator state.
-/// See [build_generator_variant_struct_type_di_node].
+/// Build the struct type for describing a single coroutine state.
+/// See [build_coroutine_variant_struct_type_di_node].
 ///
 /// ```txt
 ///
@@ -317,25 +317,25 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
 ///  --->   DW_TAG_structure_type            (type of variant 3)
 ///
 /// ```
-pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
+pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     variant_index: VariantIdx,
-    generator_type_and_layout: TyAndLayout<'tcx>,
-    generator_type_di_node: &'ll DIType,
-    generator_layout: &GeneratorLayout<'tcx>,
+    coroutine_type_and_layout: TyAndLayout<'tcx>,
+    coroutine_type_di_node: &'ll DIType,
+    coroutine_layout: &CoroutineLayout<'tcx>,
     common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
 ) -> &'ll DIType {
-    let variant_name = GeneratorArgs::variant_name(variant_index);
+    let variant_name = CoroutineArgs::variant_name(variant_index);
     let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
         cx.tcx,
-        generator_type_and_layout.ty,
+        coroutine_type_and_layout.ty,
         variant_index,
     );
 
-    let variant_layout = generator_type_and_layout.for_variant(cx, variant_index);
+    let variant_layout = coroutine_type_and_layout.for_variant(cx, variant_index);
 
-    let generator_args = match generator_type_and_layout.ty.kind() {
-        ty::Generator(_, args, _) => args.as_generator(),
+    let coroutine_args = match coroutine_type_and_layout.ty.kind() {
+        ty::Coroutine(_, args, _) => args.as_coroutine(),
         _ => unreachable!(),
     };
 
@@ -346,17 +346,17 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &variant_name,
-            size_and_align_of(generator_type_and_layout),
-            Some(generator_type_di_node),
+            size_and_align_of(coroutine_type_and_layout),
+            Some(coroutine_type_di_node),
             DIFlags::FlagZero,
         ),
         |cx, variant_struct_type_di_node| {
             // Fields that just belong to this variant/state
             let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count())
                 .map(|field_index| {
-                    let generator_saved_local = generator_layout.variant_fields[variant_index]
+                    let coroutine_saved_local = coroutine_layout.variant_fields[variant_index]
                         [FieldIdx::from_usize(field_index)];
-                    let field_name_maybe = generator_layout.field_names[generator_saved_local];
+                    let field_name_maybe = coroutine_layout.field_names[coroutine_saved_local];
                     let field_name = field_name_maybe
                         .as_ref()
                         .map(|s| Cow::from(s.as_str()))
@@ -377,7 +377,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
                 .collect();
 
             // Fields that are common to all states
-            let common_fields: SmallVec<_> = generator_args
+            let common_fields: SmallVec<_> = coroutine_args
                 .prefix_tys()
                 .iter()
                 .zip(common_upvar_names)
@@ -388,7 +388,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
                         variant_struct_type_di_node,
                         upvar_name.as_str(),
                         cx.size_and_align_of(upvar_ty),
-                        generator_type_and_layout.fields.offset(index),
+                        coroutine_type_and_layout.fields.offset(index),
                         DIFlags::FlagZero,
                         type_di_node(cx, upvar_ty),
                     )
@@ -397,7 +397,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
 
             state_specific_fields.into_iter().chain(common_fields.into_iter()).collect()
         },
-        |cx| build_generic_type_param_di_nodes(cx, generator_type_and_layout.ty),
+        |cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
     )
     .di_node
 }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index feac40d8c30..7eff52b857f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -110,12 +110,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     )
 }
 
-/// Build the debuginfo node for a generator environment. It looks the same as the debuginfo for
+/// Build the debuginfo node for a coroutine environment. It looks the same as the debuginfo for
 /// an enum. See [build_enum_type_di_node] for more information.
 ///
 /// ```txt
 ///
-///  ---> DW_TAG_structure_type              (top-level type for the generator)
+///  ---> DW_TAG_structure_type              (top-level type for the coroutine)
 ///         DW_TAG_variant_part              (variant part)
 ///           DW_AT_discr                    (reference to discriminant DW_TAG_member)
 ///           DW_TAG_member                  (discriminant member)
@@ -127,21 +127,21 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
 ///         DW_TAG_structure_type            (type of variant 3)
 ///
 /// ```
-pub(super) fn build_generator_di_node<'ll, 'tcx>(
+pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
-    let generator_type = unique_type_id.expect_ty();
-    let &ty::Generator(generator_def_id, _, _) = generator_type.kind() else {
-        bug!("build_generator_di_node() called with non-generator type: `{:?}`", generator_type)
+    let coroutine_type = unique_type_id.expect_ty();
+    let &ty::Coroutine(coroutine_def_id, _, _) = coroutine_type.kind() else {
+        bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
     };
 
-    let containing_scope = get_namespace_for_item(cx, generator_def_id);
-    let generator_type_and_layout = cx.layout_of(generator_type);
+    let containing_scope = get_namespace_for_item(cx, coroutine_def_id);
+    let coroutine_type_and_layout = cx.layout_of(coroutine_type);
 
-    debug_assert!(!wants_c_like_enum_debuginfo(generator_type_and_layout));
+    debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
 
-    let generator_type_name = compute_debuginfo_type_name(cx.tcx, generator_type, false);
+    let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
 
     type_map::build_type_with_children(
         cx,
@@ -149,37 +149,37 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
             cx,
             Stub::Struct,
             unique_type_id,
-            &generator_type_name,
-            size_and_align_of(generator_type_and_layout),
+            &coroutine_type_name,
+            size_and_align_of(coroutine_type_and_layout),
             Some(containing_scope),
             DIFlags::FlagZero,
         ),
-        |cx, generator_type_di_node| {
-            let generator_layout =
-                cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
+        |cx, coroutine_type_di_node| {
+            let coroutine_layout =
+                cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
 
             let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
-                generator_type_and_layout.variants
+                coroutine_type_and_layout.variants
             else {
                 bug!(
-                    "Encountered generator with non-direct-tag layout: {:?}",
-                    generator_type_and_layout
+                    "Encountered coroutine with non-direct-tag layout: {:?}",
+                    coroutine_type_and_layout
                 )
             };
 
             let common_upvar_names =
-                cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
+                cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
 
             // Build variant struct types
             let variant_struct_type_di_nodes: SmallVec<_> = variants
                 .indices()
                 .map(|variant_index| {
                     // FIXME: This is problematic because just a number is not a valid identifier.
-                    //        GeneratorArgs::variant_name(variant_index), would be consistent
+                    //        CoroutineArgs::variant_name(variant_index), would be consistent
                     //        with enums?
                     let variant_name = format!("{}", variant_index.as_usize()).into();
 
-                    let span = generator_layout.variant_source_info[variant_index].span;
+                    let span = coroutine_layout.variant_source_info[variant_index].span;
                     let source_info = if !span.is_dummy() {
                         let loc = cx.lookup_debug_loc(span.lo());
                         Some((file_metadata(cx, &loc.file), loc.line))
@@ -191,12 +191,12 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
                         variant_index,
                         variant_name,
                         variant_struct_type_di_node:
-                            super::build_generator_variant_struct_type_di_node(
+                            super::build_coroutine_variant_struct_type_di_node(
                                 cx,
                                 variant_index,
-                                generator_type_and_layout,
-                                generator_type_di_node,
-                                generator_layout,
+                                coroutine_type_and_layout,
+                                coroutine_type_di_node,
+                                coroutine_layout,
                                 &common_upvar_names,
                             ),
                         source_info,
@@ -206,18 +206,18 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
 
             smallvec![build_enum_variant_part_di_node(
                 cx,
-                generator_type_and_layout,
-                generator_type_di_node,
+                coroutine_type_and_layout,
+                coroutine_type_di_node,
                 &variant_struct_type_di_nodes[..],
             )]
         },
-        // We don't seem to be emitting generic args on the generator type, it seems. Rather
+        // We don't seem to be emitting generic args on the coroutine type, it seems. Rather
         // they get attached to the struct type of each variant.
         NO_GENERICS,
     )
 }
 
-/// Builds the DW_TAG_variant_part of an enum or generator debuginfo node:
+/// Builds the DW_TAG_variant_part of an enum or coroutine debuginfo node:
 ///
 /// ```txt
 ///       DW_TAG_structure_type              (top-level type for enum)
@@ -306,11 +306,11 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
 /// ```
 fn build_discr_member_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
-    enum_or_generator_type_and_layout: TyAndLayout<'tcx>,
-    enum_or_generator_type_di_node: &'ll DIType,
+    enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
+    enum_or_coroutine_type_di_node: &'ll DIType,
 ) -> Option<&'ll DIType> {
-    let tag_name = match enum_or_generator_type_and_layout.ty.kind() {
-        ty::Generator(..) => "__state",
+    let tag_name = match enum_or_coroutine_type_and_layout.ty.kind() {
+        ty::Coroutine(..) => "__state",
         _ => "",
     };
 
@@ -320,14 +320,14 @@ fn build_discr_member_di_node<'ll, 'tcx>(
     //       In LLVM IR the wrong scope will be listed but when DWARF is
     //       generated from it, the DW_TAG_member will be a child the
     //       DW_TAG_variant_part.
-    let containing_scope = enum_or_generator_type_di_node;
+    let containing_scope = enum_or_coroutine_type_di_node;
 
-    match enum_or_generator_type_and_layout.layout.variants() {
+    match enum_or_coroutine_type_and_layout.layout.variants() {
         // A single-variant enum has no discriminant.
         &Variants::Single { .. } => None,
 
         &Variants::Multiple { tag_field, .. } => {
-            let tag_base_type = tag_base_type(cx, enum_or_generator_type_and_layout);
+            let tag_base_type = tag_base_type(cx, enum_or_coroutine_type_and_layout);
             let (size, align) = cx.size_and_align_of(tag_base_type);
 
             unsafe {
@@ -340,7 +340,7 @@ fn build_discr_member_di_node<'ll, 'tcx>(
                     UNKNOWN_LINE_NUMBER,
                     size.bits(),
                     align.bits() as u32,
-                    enum_or_generator_type_and_layout.fields.offset(tag_field).bits(),
+                    enum_or_coroutine_type_and_layout.fields.offset(tag_field).bits(),
                     DIFlags::FlagArtificial,
                     type_di_node(cx, tag_base_type),
                 ))
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index e30622cbdce..1aec65cf949 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -43,7 +43,7 @@ pub(super) enum UniqueTypeId<'tcx> {
     /// The ID of a regular type as it shows up at the language level.
     Ty(Ty<'tcx>, private::HiddenZst),
     /// The ID for the single DW_TAG_variant_part nested inside the top-level
-    /// DW_TAG_structure_type that describes enums and generators.
+    /// DW_TAG_structure_type that describes enums and coroutines.
     VariantPart(Ty<'tcx>, private::HiddenZst),
     /// The ID for the artificial struct type describing a single enum variant.
     VariantStructType(Ty<'tcx>, VariantIdx, private::HiddenZst),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index d874b3ab99d..c8bf7286edf 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -342,7 +342,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         // We look up the generics of the enclosing function and truncate the args
         // to their length in order to cut off extra stuff that might be in there for
-        // closures or generators.
+        // closures or coroutines.
         let generics = tcx.generics_of(enclosing_fn_def_id);
         let args = instance.args.truncate_to(tcx, generics);
 
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index fd4c9572af2..712b6ed5333 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -42,7 +42,7 @@ fn uncached_llvm_type<'a, 'tcx>(
         // FIXME(eddyb) producing readable type names for trait objects can result
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
-        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str
+        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
             // For performance reasons we use names only when emitting LLVM IR.
             if !cx.sess().fewer_names() =>
         {
@@ -54,10 +54,10 @@ fn uncached_llvm_type<'a, 'tcx>(
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
+            if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap();
+                write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
             }
             Some(name)
         }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 989df448a31..e401f6bbcbf 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
-use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
+use rustc_hir::{AsyncCoroutineKind, CoroutineKind, Mutability};
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
 use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
@@ -398,23 +398,23 @@ fn push_debuginfo_type_name<'tcx>(
             // processing
             visited.remove(&t);
         }
-        ty::Closure(def_id, args) | ty::Generator(def_id, args, ..) => {
-            // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
+        ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
+            // Name will be "{closure_env#0}<T1, T2, ...>", "{coroutine_env#0}<T1, T2, ...>", or
             // "{async_fn_env#0}<T1, T2, ...>", etc.
             // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
             // an artificial `enum2$<>` type, as defined in msvc_enum_fallback().
-            if cpp_like_debuginfo && t.is_generator() {
+            if cpp_like_debuginfo && t.is_coroutine() {
                 let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap();
                 msvc_enum_fallback(
                     ty_and_layout,
                     &|output, visited| {
-                        push_closure_or_generator_name(tcx, def_id, args, true, output, visited);
+                        push_closure_or_coroutine_name(tcx, def_id, args, true, output, visited);
                     },
                     output,
                     visited,
                 );
             } else {
-                push_closure_or_generator_name(tcx, def_id, args, qualified, output, visited);
+                push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited);
             }
         }
         // Type parameters from polymorphized functions.
@@ -426,7 +426,7 @@ fn push_debuginfo_type_name<'tcx>(
         | ty::Placeholder(..)
         | ty::Alias(..)
         | ty::Bound(..)
-        | ty::GeneratorWitness(..) => {
+        | ty::CoroutineWitness(..) => {
             bug!(
                 "debuginfo: Trying to create type name for \
                   unexpected type: {:?}",
@@ -558,12 +558,12 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &
     push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output);
 }
 
-fn generator_kind_label(generator_kind: Option<GeneratorKind>) -> &'static str {
-    match generator_kind {
-        Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) => "async_block",
-        Some(GeneratorKind::Async(AsyncGeneratorKind::Closure)) => "async_closure",
-        Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) => "async_fn",
-        Some(GeneratorKind::Gen) => "generator",
+fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str {
+    match coroutine_kind {
+        Some(CoroutineKind::Async(AsyncCoroutineKind::Block)) => "async_block",
+        Some(CoroutineKind::Async(AsyncCoroutineKind::Closure)) => "async_closure",
+        Some(CoroutineKind::Async(AsyncCoroutineKind::Fn)) => "async_fn",
+        Some(CoroutineKind::Coroutine) => "coroutine",
         None => "closure",
     }
 }
@@ -592,7 +592,7 @@ fn push_unqualified_item_name(
             output.push_str(tcx.crate_name(def_id.krate).as_str());
         }
         DefPathData::ClosureExpr => {
-            let label = generator_kind_label(tcx.generator_kind(def_id));
+            let label = coroutine_kind_label(tcx.coroutine_kind(def_id));
 
             push_disambiguated_special_name(
                 label,
@@ -707,7 +707,7 @@ pub fn push_generic_params<'tcx>(
     push_generic_params_internal(tcx, args, def_id, output, &mut visited);
 }
 
-fn push_closure_or_generator_name<'tcx>(
+fn push_closure_or_coroutine_name<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     args: GenericArgsRef<'tcx>,
@@ -715,10 +715,10 @@ fn push_closure_or_generator_name<'tcx>(
     output: &mut String,
     visited: &mut FxHashSet<Ty<'tcx>>,
 ) {
-    // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
+    // Name will be "{closure_env#0}<T1, T2, ...>", "{coroutine_env#0}<T1, T2, ...>", or
     // "{async_fn_env#0}<T1, T2, ...>", etc.
     let def_key = tcx.def_key(def_id);
-    let generator_kind = tcx.generator_kind(def_id);
+    let coroutine_kind = tcx.coroutine_kind(def_id);
 
     if qualified {
         let parent_def_id = DefId { index: def_key.parent.unwrap(), ..def_id };
@@ -727,7 +727,7 @@ fn push_closure_or_generator_name<'tcx>(
     }
 
     let mut label = String::with_capacity(20);
-    write!(&mut label, "{}_env", generator_kind_label(generator_kind)).unwrap();
+    write!(&mut label, "{}_env", coroutine_kind_label(coroutine_kind)).unwrap();
 
     push_disambiguated_special_name(
         &label,
@@ -736,7 +736,7 @@ fn push_closure_or_generator_name<'tcx>(
         output,
     );
 
-    // We also need to add the generic arguments of the async fn/generator or
+    // We also need to add the generic arguments of the async fn/coroutine or
     // the enclosing function (for closures or async blocks), so that we end
     // up with a unique name for every instantiation.
 
@@ -745,7 +745,7 @@ fn push_closure_or_generator_name<'tcx>(
     let generics = tcx.generics_of(enclosing_fn_def_id);
 
     // Truncate the args to the length of the above generics. This will cut off
-    // anything closure- or generator-specific.
+    // anything closure- or coroutine-specific.
     let args = args.truncate_to(tcx, generics);
     push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited);
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 62e997e5cfa..53cc063e55a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -272,7 +272,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
                 | TerminatorKind::UnwindResume
                 | TerminatorKind::UnwindTerminate(_)
                 | TerminatorKind::Return
-                | TerminatorKind::GeneratorDrop
+                | TerminatorKind::CoroutineDrop
                 | TerminatorKind::Unreachable
                 | TerminatorKind::SwitchInt { .. }
                 | TerminatorKind::Yield { .. }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 68f22aaf990..caade768795 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1265,8 +1265,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 fn_span,
                 mergeable_succ(),
             ),
-            mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {
-                bug!("generator ops in codegen")
+            mir::TerminatorKind::CoroutineDrop | mir::TerminatorKind::Yield { .. } => {
+                bug!("coroutine ops in codegen")
             }
             mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseUnwind { .. } => {
                 bug!("borrowck false edges in codegen")
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 166d3d45e79..0d0ebe6f390 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -534,8 +534,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             OverflowNeg(op) => OverflowNeg(eval_to_int(op)?),
             DivisionByZero(op) => DivisionByZero(eval_to_int(op)?),
             RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
-            ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind),
-            ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind),
+            ResumedAfterReturn(coroutine_kind) => ResumedAfterReturn(*coroutine_kind),
+            ResumedAfterPanic(coroutine_kind) => ResumedAfterPanic(*coroutine_kind),
             MisalignedPointerDereference { ref required, ref found } => {
                 MisalignedPointerDereference {
                     required: eval_to_int(required)?,
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 7436ea6ae57..d6dc1a62f4d 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -151,8 +151,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         | ty::Infer(_)
         // FIXME(oli-obk): we can probably encode closures just like structs
         | ty::Closure(..)
-        | ty::Generator(..)
-        | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType),
+        | ty::Coroutine(..)
+        | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType),
     }
 }
 
@@ -278,8 +278,8 @@ pub fn valtree_to_const_value<'tcx>(
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Closure(..)
-        | ty::Generator(..)
-        | ty::GeneratorWitness(..)
+        | ty::Coroutine(..)
+        | ty::CoroutineWitness(..)
         | ty::FnPtr(_)
         | ty::RawPtr(_)
         | ty::Str
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index b9557eaf6ab..8fc0205d6c7 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
 use rustc_target::abi::Integer;
-use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::TyKind::*;
 
 use super::{
     util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
@@ -185,7 +185,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         src: &ImmTy<'tcx, M::Provenance>,
         cast_to: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
-        use rustc_type_ir::sty::TyKind::*;
+        use rustc_type_ir::TyKind::*;
 
         let val = match src.layout.ty.kind() {
             // Floating point
@@ -310,7 +310,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     where
         F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>,
     {
-        use rustc_type_ir::sty::TyKind::*;
+        use rustc_type_ir::TyKind::*;
 
         fn adjust_nan<
             'mir,
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 49e01728ff4..8dab45d65ee 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -1,4 +1,4 @@
-//! Functions for reading and writing discriminants of multi-variant layouts (enums and generators).
+//! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
 
 use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::{mir, ty};
@@ -170,11 +170,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     ty::Adt(adt, _) => {
                         adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
-                    ty::Generator(def_id, args, _) => {
-                        let args = args.as_generator();
+                    ty::Coroutine(def_id, args, _) => {
+                        let args = args.as_coroutine();
                         args.discriminants(def_id, *self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
-                    _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
+                    _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-coroutine"),
                 }
                 .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
                 // Return the cast value, and the index.
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 1c2e8d807f4..791370660fe 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -963,8 +963,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 | ty::RawPtr(..)
                 | ty::Char
                 | ty::Ref(..)
-                | ty::Generator(..)
-                | ty::GeneratorWitness(..)
+                | ty::Coroutine(..)
+                | ty::CoroutineWitness(..)
                 | ty::Array(..)
                 | ty::Closure(..)
                 | ty::Never
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index b7106c37c7b..c97207a61ac 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -99,8 +99,8 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
             | ty::FnPtr(_)
             | ty::Dynamic(_, _, _)
             | ty::Closure(_, _)
-            | ty::Generator(_, _, _)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(_, _, _)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 59e89819880..b54c6681456 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -218,7 +218,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Unreachable => throw_ub!(Unreachable),
 
             // These should never occur for MIR we actually run.
-            FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | GeneratorDrop => span_bug!(
+            FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | CoroutineDrop => span_bug!(
                 terminator.source_info.span,
                 "{:#?} should have been eliminated by MIR pass",
                 terminator.kind
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index eb639ded70f..416443f5f4d 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -34,7 +34,7 @@ where
             match *ty.kind() {
                 ty::Param(_) => ControlFlow::Break(FoundParam),
                 ty::Closure(def_id, args)
-                | ty::Generator(def_id, args, ..)
+                | ty::Coroutine(def_id, args, ..)
                 | ty::FnDef(def_id, args) => {
                     let instance = ty::InstanceDef::Item(def_id);
                     let unused_params = self.tcx.unused_generic_params(instance);
@@ -42,10 +42,10 @@ where
                         let index = index
                             .try_into()
                             .expect("more generic parameters than can fit into a `u32`");
-                        // Only recurse when generic parameters in fns, closures and generators
+                        // Only recurse when generic parameters in fns, closures and coroutines
                         // are used and have to be instantiated.
                         //
-                        // Just in case there are closures or generators within this subst,
+                        // Just in case there are closures or coroutines within this subst,
                         // recurse.
                         if unused_params.is_used(index) && subst.has_param() {
                             return subst.visit_with(self);
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 082e5466fe2..56b7b6bf826 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -112,13 +112,13 @@ macro_rules! try_validation {
 pub enum PathElem {
     Field(Symbol),
     Variant(Symbol),
-    GeneratorState(VariantIdx),
+    CoroutineState(VariantIdx),
     CapturedVar(Symbol),
     ArrayElem(usize),
     TupleElem(usize),
     Deref,
     EnumTag,
-    GeneratorTag,
+    CoroutineTag,
     DynDowncast,
 }
 
@@ -171,8 +171,8 @@ fn write_path(out: &mut String, path: &[PathElem]) {
             Field(name) => write!(out, ".{name}"),
             EnumTag => write!(out, ".<enum-tag>"),
             Variant(name) => write!(out, ".<enum-variant({name})>"),
-            GeneratorTag => write!(out, ".<generator-tag>"),
-            GeneratorState(idx) => write!(out, ".<generator-state({})>", idx.index()),
+            CoroutineTag => write!(out, ".<coroutine-tag>"),
+            CoroutineState(idx) => write!(out, ".<coroutine-state({})>", idx.index()),
             CapturedVar(name) => write!(out, ".<captured-var({name})>"),
             TupleElem(idx) => write!(out, ".{idx}"),
             ArrayElem(idx) => write!(out, "[{idx}]"),
@@ -206,7 +206,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 if tag_field == field {
                     return match layout.ty.kind() {
                         ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag,
-                        ty::Generator(..) => PathElem::GeneratorTag,
+                        ty::Coroutine(..) => PathElem::CoroutineTag,
                         _ => bug!("non-variant type {:?}", layout.ty),
                     };
                 }
@@ -216,8 +216,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
 
         // Now we know we are projecting to a field, so figure out which one.
         match layout.ty.kind() {
-            // generators and closures.
-            ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
+            // coroutines and closures.
+            ty::Closure(def_id, _) | ty::Coroutine(def_id, _, _) => {
                 let mut name = None;
                 // FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar
                 // https://github.com/rust-lang/project-rfc-2229/issues/46
@@ -225,7 +225,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     let captures = self.ecx.tcx.closure_captures(local_def_id);
                     if let Some(captured_place) = captures.get(field) {
                         // Sometimes the index is beyond the number of upvars (seen
-                        // for a generator).
+                        // for a coroutine).
                         let var_hir_id = captured_place.get_root_variable();
                         let node = self.ecx.tcx.hir().get(var_hir_id);
                         if let hir::Node::Pat(pat) = node {
@@ -580,7 +580,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             | ty::Str
             | ty::Dynamic(..)
             | ty::Closure(..)
-            | ty::Generator(..) => Ok(false),
+            | ty::Coroutine(..) => Ok(false),
             // Some types only occur during typechecking, they have no layout.
             // We should not see them here and we could not check them anyway.
             ty::Error(_)
@@ -589,7 +589,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             | ty::Bound(..)
             | ty::Param(..)
             | ty::Alias(..)
-            | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
+            | ty::CoroutineWitness(..) => bug!("Encountered invalid type {:?}", ty),
         }
     }
 
@@ -692,8 +692,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
     ) -> InterpResult<'tcx> {
         let name = match old_op.layout.ty.kind() {
             ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
-            // Generators also have variants
-            ty::Generator(..) => PathElem::GeneratorState(variant_id),
+            // Coroutines also have variants
+            ty::Coroutine(..) => PathElem::CoroutineState(variant_id),
             _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
         };
         self.with_elem(name, move |this| this.visit_value(new_op))
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 92e7922ad3b..135c99fefbc 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -247,7 +247,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
 
         // `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
         // no need to emit duplicate errors here.
-        if self.ccx.is_async() || body.generator.is_some() {
+        if self.ccx.is_async() || body.coroutine.is_some() {
             tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
             return;
         }
@@ -463,11 +463,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | Rvalue::Len(_) => {}
 
             Rvalue::Aggregate(kind, ..) => {
-                if let AggregateKind::Generator(def_id, ..) = kind.as_ref()
-                    && let Some(generator_kind @ hir::GeneratorKind::Async(..)) =
-                        self.tcx.generator_kind(def_id)
+                if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
+                    && let Some(coroutine_kind @ hir::CoroutineKind::Async(..)) =
+                        self.tcx.coroutine_kind(def_id)
                 {
-                    self.check_op(ops::Generator(generator_kind));
+                    self.check_op(ops::Coroutine(coroutine_kind));
                 }
             }
 
@@ -1042,8 +1042,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
             TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
 
-            TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
-                self.check_op(ops::Generator(hir::GeneratorKind::Gen))
+            TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => {
+                self.check_op(ops::Coroutine(hir::CoroutineKind::Coroutine))
             }
 
             TerminatorKind::UnwindTerminate(_) => {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index e8d1d595820..616fab8fe7d 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -357,10 +357,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
 }
 
 #[derive(Debug)]
-pub struct Generator(pub hir::GeneratorKind);
-impl<'tcx> NonConstOp<'tcx> for Generator {
+pub struct Coroutine(pub hir::CoroutineKind);
+impl<'tcx> NonConstOp<'tcx> for Coroutine {
     fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
-        if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
+        if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
             Status::Unstable(sym::const_async_blocks)
         } else {
             Status::Forbidden
@@ -373,7 +373,7 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
         span: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
-        if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
+        if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
             ccx.tcx.sess.create_feature_err(
                 errors::UnallowedOpInConstContext { span, msg },
                 sym::const_async_blocks,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index fd6bc2ee9af..aff256b3ead 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -111,7 +111,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
             | mir::TerminatorKind::Assert { .. }
             | mir::TerminatorKind::FalseEdge { .. }
             | mir::TerminatorKind::FalseUnwind { .. }
-            | mir::TerminatorKind::GeneratorDrop
+            | mir::TerminatorKind::CoroutineDrop
             | mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::InlineAsm { .. }
             | mir::TerminatorKind::UnwindResume
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 8ede3bdd2b6..05902976638 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -970,7 +970,7 @@ pub fn promote_candidates<'tcx>(
             0,
             vec![],
             body.span,
-            body.generator_kind(),
+            body.coroutine_kind(),
             body.tainted_by_errors,
         );
         promoted.phase = MirPhase::Analysis(AnalysisPhase::Initial);
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 4711f7b47cc..b70a342aa15 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -67,7 +67,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
             let body_abi = match body_ty.kind() {
                 ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
                 ty::Closure(..) => Abi::RustCall,
-                ty::Generator(..) => Abi::Rust,
+                ty::Coroutine(..) => Abi::Rust,
                 _ => {
                     span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase)
                 }
@@ -472,11 +472,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::Yield { resume, drop, .. } => {
-                if self.body.generator.is_none() {
-                    self.fail(location, "`Yield` cannot appear outside generator bodies");
+                if self.body.coroutine.is_none() {
+                    self.fail(location, "`Yield` cannot appear outside coroutine bodies");
                 }
                 if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
-                    self.fail(location, "`Yield` should have been replaced by generator lowering");
+                    self.fail(location, "`Yield` should have been replaced by coroutine lowering");
                 }
                 self.check_edge(location, *resume, EdgeKind::Normal);
                 if let Some(drop) = drop {
@@ -509,14 +509,14 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 }
                 self.check_unwind_edge(location, *unwind);
             }
-            TerminatorKind::GeneratorDrop => {
-                if self.body.generator.is_none() {
-                    self.fail(location, "`GeneratorDrop` cannot appear outside generator bodies");
+            TerminatorKind::CoroutineDrop => {
+                if self.body.coroutine.is_none() {
+                    self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies");
                 }
                 if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
-                        "`GeneratorDrop` should have been replaced by generator lowering",
+                        "`CoroutineDrop` should have been replaced by coroutine lowering",
                     );
                 }
             }
@@ -716,7 +716,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         };
                         check_equal(self, location, f_ty);
                     }
-                    &ty::Generator(def_id, args, _) => {
+                    &ty::Coroutine(def_id, args, _) => {
                         let f_ty = if let Some(var) = parent_ty.variant_index {
                             let gen_body = if def_id == self.body.source.def_id() {
                                 self.body
@@ -724,10 +724,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 self.tcx.optimized_mir(def_id)
                             };
 
-                            let Some(layout) = gen_body.generator_layout() else {
+                            let Some(layout) = gen_body.coroutine_layout() else {
                                 self.fail(
                                     location,
-                                    format!("No generator layout for {parent_ty:?}"),
+                                    format!("No coroutine layout for {parent_ty:?}"),
                                 );
                                 return;
                             };
@@ -747,7 +747,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
 
                             ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
                         } else {
-                            let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index())
+                            let Some(&f_ty) = args.as_coroutine().prefix_tys().get(f.index())
                             else {
                                 fail_out_of_bounds(self, location);
                                 return;
@@ -1211,11 +1211,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
                 let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
-                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Alias(ty::Opaque, ..)) {
+                if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) {
                     self.fail(
                         location,
                         format!(
-                            "`SetDiscriminant` is only allowed on ADTs and generators, not {pty:?}"
+                            "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}"
                         ),
                     );
                 }
@@ -1295,7 +1295,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 54eb14ae8fc..8c7c360acbf 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -51,12 +51,12 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             | ty::FnDef(def_id, args)
             | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
             | ty::Closure(def_id, args)
-            | ty::Generator(def_id, args, _) => self.print_def_path(def_id, args),
+            | ty::Coroutine(def_id, args, _) => self.print_def_path(def_id, args),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
             ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
             ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
-            ty::GeneratorWitness(..) => bug!("type_name: unexpected `GeneratorWitness`"),
+            ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"),
         }
     }
 
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index f77bd53e76c..dce4e199e17 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2021"
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
 bitflags = "1.2.1"
-cfg-if = "1.0"
 ena = "0.14.2"
 indexmap = { version = "2.0.0" }
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
diff --git a/compiler/rustc_data_structures/src/flock.rs b/compiler/rustc_data_structures/src/flock.rs
index efdb44248d1..008565e4c7b 100644
--- a/compiler/rustc_data_structures/src/flock.rs
+++ b/compiler/rustc_data_structures/src/flock.rs
@@ -4,17 +4,20 @@
 //! green/native threading. This is just a bare-bones enough solution for
 //! librustdoc, it is not production quality at all.
 
-cfg_if! {
-    if #[cfg(target_os = "linux")] {
+cfg_match! {
+    cfg(target_os = "linux") => {
         mod linux;
         use linux as imp;
-    } else if #[cfg(unix)] {
+    }
+    cfg(unix) => {
         mod unix;
         use unix as imp;
-    } else if #[cfg(windows)] {
+    }
+    cfg(windows) => {
         mod windows;
         use self::windows as imp;
-    } else {
+    }
+    _ => {
         mod unsupported;
         use unsupported as imp;
     }
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 9511f1700e1..5d7f385c6e4 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -6,43 +6,44 @@
 //!
 //! This API is completely unstable and subject to change.
 
+// tidy-alphabetical-start
+#![allow(internal_features)]
+#![allow(rustc::default_hash_types)]
+#![allow(rustc::potential_query_instability)]
 #![cfg_attr(not(bootstrap), doc(rust_logo))]
 #![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![deny(rustc::diagnostic_outside_of_impl)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(unsafe_op_in_unsafe_fn)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(allocator_api)]
 #![feature(array_windows)]
 #![feature(auto_traits)]
 #![feature(cell_leak)]
+#![feature(cfg_match)]
 #![feature(core_intrinsics)]
 #![feature(extend_one)]
 #![feature(hash_raw_entry)]
 #![feature(hasher_prefixfree_extras)]
+#![feature(lazy_cell)]
+#![feature(lint_reasons)]
+#![feature(macro_metavar_expr)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
+#![feature(negative_impls)]
 #![feature(never_type)]
-#![feature(type_alias_impl_trait)]
-#![feature(lazy_cell)]
+#![feature(ptr_alignment_type)]
 #![feature(rustc_attrs)]
-#![feature(negative_impls)]
+#![feature(strict_provenance)]
 #![feature(test)]
 #![feature(thread_id_value)]
-#![feature(allocator_api)]
-#![feature(lint_reasons)]
+#![feature(type_alias_impl_trait)]
 #![feature(unwrap_infallible)]
-#![feature(strict_provenance)]
-#![feature(ptr_alignment_type)]
-#![feature(macro_metavar_expr)]
-#![allow(rustc::default_hash_types)]
-#![allow(rustc::potential_query_instability)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-#![allow(internal_features)]
-#![deny(unsafe_op_in_unsafe_fn)]
+// tidy-alphabetical-end
 
 #[macro_use]
 extern crate tracing;
 #[macro_use]
-extern crate cfg_if;
-#[macro_use]
 extern crate rustc_macros;
 
 use std::fmt;
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index b067f9d4502..a8c442377fb 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -1,11 +1,12 @@
-cfg_if!(
-    if #[cfg(not(parallel_compiler))] {
+cfg_match! {
+    cfg(not(parallel_compiler)) => {
         pub auto trait DynSend {}
         pub auto trait DynSync {}
 
         impl<T> DynSend for T {}
         impl<T> DynSync for T {}
-    } else {
+    }
+    _ => {
         #[rustc_on_unimplemented(
             message = "`{Self}` doesn't implement `DynSend`. \
             Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`"
@@ -48,13 +49,10 @@ cfg_if!(
             [std::io::StdoutLock<'_>]
             [std::io::StderrLock<'_>]
         );
-        cfg_if!(
-            // Consistent with `std`
-            // `os_imp::Env` is `!Send` in these platforms
-            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
-                impl !DynSend for std::env::VarsOs {}
-            }
-        );
+
+        #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
+        // Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
+        impl !DynSend for std::env::VarsOs {}
 
         macro_rules! already_send {
             ($([$ty: ty])*) => {
@@ -123,13 +121,10 @@ cfg_if!(
             [std::sync::mpsc::Receiver<T> where T]
             [std::sync::mpsc::Sender<T> where T]
         );
-        cfg_if!(
-            // Consistent with `std`
-            // `os_imp::Env` is `!Sync` in these platforms
-            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
-                impl !DynSync for std::env::VarsOs {}
-            }
-        );
+
+        #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))]
+        // Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms
+        impl !DynSync for std::env::VarsOs {}
 
         macro_rules! already_sync {
             ($([$ty: ty])*) => {
@@ -183,7 +178,7 @@ cfg_if!(
             [thin_vec::ThinVec<T> where T: DynSync]
         );
     }
-);
+}
 
 pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
 pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index e688feb5fe1..ef7375a7320 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -859,8 +859,8 @@ fn get_thread_id() -> u32 {
 }
 
 // Memory reporting
-cfg_if! {
-    if #[cfg(windows)] {
+cfg_match! {
+    cfg(windows) => {
         pub fn get_resident_set_size() -> Option<usize> {
             use std::mem;
 
@@ -885,7 +885,8 @@ cfg_if! {
 
             Some(pmc.WorkingSetSize)
         }
-    } else if #[cfg(target_os = "macos")] {
+    }
+    cfg(target_os = "macos")  => {
         pub fn get_resident_set_size() -> Option<usize> {
             use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
             use std::mem;
@@ -903,7 +904,8 @@ cfg_if! {
                 }
             }
         }
-    } else if #[cfg(unix)] {
+    }
+    cfg(unix) => {
         pub fn get_resident_set_size() -> Option<usize> {
             let field = 1;
             let contents = fs::read("/proc/self/statm").ok()?;
@@ -912,7 +914,8 @@ cfg_if! {
             let npages = s.parse::<usize>().ok()?;
             Some(npages * 4096)
         }
-    } else {
+    }
+    _ => {
         pub fn get_resident_set_size() -> Option<usize> {
             None
         }
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index cca043ba0d1..62fff604f81 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -109,8 +109,8 @@ mod mode {
 
 pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
 
-cfg_if! {
-    if #[cfg(not(parallel_compiler))] {
+cfg_match! {
+    cfg(not(parallel_compiler)) => {
         use std::ops::Add;
         use std::cell::Cell;
 
@@ -251,7 +251,8 @@ cfg_if! {
                 MTLock(self.0.clone())
             }
         }
-    } else {
+    }
+    _ => {
         pub use std::marker::Send as Send;
         pub use std::marker::Sync as Sync;
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0626.md b/compiler/rustc_error_codes/src/error_codes/E0626.md
index cc6e03d1ca7..e2534415d83 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0626.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0626.md
@@ -1,11 +1,11 @@
-This error occurs because a borrow in a generator persists across a
+This error occurs because a borrow in a coroutine persists across a
 yield point.
 
 Erroneous code example:
 
 ```compile_fail,E0626
-# #![feature(generators, generator_trait, pin)]
-# use std::ops::Generator;
+# #![feature(coroutines, coroutine_trait, pin)]
+# use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = || {
     let a = &String::new(); // <-- This borrow...
@@ -23,8 +23,8 @@ resolve the previous example by removing the borrow and just storing
 the integer by value:
 
 ```
-# #![feature(generators, generator_trait, pin)]
-# use std::ops::Generator;
+# #![feature(coroutines, coroutine_trait, pin)]
+# use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = || {
     let a = 3;
@@ -41,8 +41,8 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
 This error also frequently arises with iteration:
 
 ```compile_fail,E0626
-# #![feature(generators, generator_trait, pin)]
-# use std::ops::Generator;
+# #![feature(coroutines, coroutine_trait, pin)]
+# use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = || {
   let v = vec![1,2,3];
@@ -57,8 +57,8 @@ Such cases can sometimes be resolved by iterating "by value" (or using
 `into_iter()`) to avoid borrowing:
 
 ```
-# #![feature(generators, generator_trait, pin)]
-# use std::ops::Generator;
+# #![feature(coroutines, coroutine_trait, pin)]
+# use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = || {
   let v = vec![1,2,3];
@@ -72,8 +72,8 @@ Pin::new(&mut b).resume(());
 If taking ownership is not an option, using indices can work too:
 
 ```
-# #![feature(generators, generator_trait, pin)]
-# use std::ops::Generator;
+# #![feature(coroutines, coroutine_trait, pin)]
+# use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = || {
   let v = vec![1,2,3];
diff --git a/compiler/rustc_error_codes/src/error_codes/E0627.md b/compiler/rustc_error_codes/src/error_codes/E0627.md
index 21358e1e567..5d366f78fc5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0627.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0627.md
@@ -1,28 +1,28 @@
-A yield expression was used outside of the generator literal.
+A yield expression was used outside of the coroutine literal.
 
 Erroneous code example:
 
 ```compile_fail,E0627
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-fn fake_generator() -> &'static str {
+fn fake_coroutine() -> &'static str {
     yield 1;
     return "foo"
 }
 
 fn main() {
-    let mut generator = fake_generator;
+    let mut coroutine = fake_coroutine;
 }
 ```
 
-The error occurs because keyword `yield` can only be used inside the generator
-literal. This can be fixed by constructing the generator correctly.
+The error occurs because keyword `yield` can only be used inside the coroutine
+literal. This can be fixed by constructing the coroutine correctly.
 
 ```
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 fn main() {
-    let mut generator = || {
+    let mut 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 40040c9a56a..ce19bcd56cc 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0628.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0628.md
@@ -1,13 +1,13 @@
-More than one parameter was used for a generator.
+More than one parameter was used for a coroutine.
 
 Erroneous code example:
 
 ```compile_fail,E0628
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 fn main() {
-    let generator = |a: i32, b: i32| {
-        // error: too many parameters for a generator
+    let coroutine = |a: i32, b: i32| {
+        // error: too many parameters for a coroutine
         // Allowed only 0 or 1 parameter
         yield a;
     };
@@ -15,15 +15,15 @@ fn main() {
 ```
 
 At present, it is not permitted to pass more than one explicit
-parameter for a generator.This can be fixed by using
-at most 1 parameter for the generator. For example, we might resolve
+parameter for a coroutine.This can be fixed by using
+at most 1 parameter for the coroutine. For example, we might resolve
 the previous example by passing only one parameter.
 
 ```
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 fn main() {
-    let generator = |a: i32| {
+    let coroutine = |a: i32| {
         yield a;
     };
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0698.md b/compiler/rustc_error_codes/src/error_codes/E0698.md
index 9bc652e642f..d0649712936 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0698.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0698.md
@@ -1,7 +1,7 @@
 #### Note: this error code is no longer emitted by the compiler.
 
-When using generators (or async) all type variables must be bound so a
-generator can be constructed.
+When using coroutines (or async) all type variables must be bound so a
+coroutine can be constructed.
 
 Erroneous code example:
 
@@ -15,7 +15,7 @@ async fn foo() {
 
 In the above example `T` is unknowable by the compiler.
 To fix this you must bind `T` to a concrete type such as `String`
-so that a generator can then be constructed:
+so that a coroutine can then be constructed:
 
 ```edition2018
 async fn bar<T>() -> () {}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0727.md b/compiler/rustc_error_codes/src/error_codes/E0727.md
index 386daea0c57..fde35885c92 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(generators)]
+#![feature(coroutines)]
 
 fn main() {
-    let generator = || {
+    let 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(generators)]
+#![feature(coroutines)]
 
 fn main() {
-    let generator = || {
+    let coroutine = || {
         yield;
     };
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md
index 2aee9dfbdbd..b52543c48d8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0790.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0790.md
@@ -4,24 +4,24 @@ method.
 Erroneous code example:
 
 ```compile_fail,E0790
-trait Generator {
+trait Coroutine {
     fn create() -> u32;
 }
 
 struct Impl;
 
-impl Generator for Impl {
+impl Coroutine for Impl {
     fn create() -> u32 { 1 }
 }
 
 struct AnotherImpl;
 
-impl Generator for AnotherImpl {
+impl Coroutine for AnotherImpl {
     fn create() -> u32 { 2 }
 }
 
-let cont: u32 = Generator::create();
-// error, impossible to choose one of Generator trait implementation
+let cont: u32 = Coroutine::create();
+// error, impossible to choose one of Coroutine trait implementation
 // Should it be Impl or AnotherImpl, maybe something else?
 ```
 
@@ -30,18 +30,18 @@ information to the compiler. In this case, the solution is to use a concrete
 type:
 
 ```
-trait Generator {
+trait Coroutine {
     fn create() -> u32;
 }
 
 struct AnotherImpl;
 
-impl Generator for AnotherImpl {
+impl Coroutine for AnotherImpl {
     fn create() -> u32 { 2 }
 }
 
 let gen1 = AnotherImpl::create();
 
 // if there are multiple methods with same name (different traits)
-let gen2 = <AnotherImpl as Generator>::create();
+let gen2 = <AnotherImpl as Coroutine>::create();
 ```
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 339f596144c..ac133f8b039 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -42,7 +42,7 @@ declare_features! (
      Some("subsumed by `.await` syntax")),
     /// Allows using the `box $expr` syntax.
     (removed, box_syntax, "1.70.0", Some(49733), None, Some("replaced with `#[rustc_box]`")),
-    /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
+    /// Allows capturing disjoint fields in a closure/coroutine (RFC 2229).
     (removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
     /// Allows comparing raw pointers during const eval.
     (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
@@ -96,6 +96,10 @@ declare_features! (
     /// Allows `#[doc(include = "some-file")]`.
     (removed, external_doc, "1.54.0", Some(44732), None,
      Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
+    /// Allows generators to be cloned.
+    (removed, generator_clone, "1.65.0", Some(95360), None, Some("renamed to `coroutine_clone`")),
+    /// Allows defining generators.
+    (removed, generators, "1.21.0", Some(43122), None, Some("renamed to `coroutine`")),
     /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
     (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
      Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 27cdf1ba831..8185a8a3e43 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -371,9 +371,9 @@ declare_features! (
     (unstable, cfg_version, "1.45.0", Some(64796), None),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
     (unstable, cfi_encoding, "1.71.0", Some(89653), None),
-    /// Allows `for<...>` on closures and generators.
+    /// Allows `for<...>` on closures and coroutines.
     (unstable, closure_lifetime_binder, "1.64.0", Some(97362), None),
-    /// Allows `#[track_caller]` on closures and generators.
+    /// Allows `#[track_caller]` on closures and coroutines.
     (unstable, closure_track_caller, "1.57.0", Some(87417), None),
     /// Allows to use the `#[cmse_nonsecure_entry]` attribute.
     (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835), None),
@@ -399,6 +399,10 @@ declare_features! (
     (unstable, const_trait_impl, "1.42.0", Some(67792), None),
     /// Allows the `?` operator in const contexts.
     (unstable, const_try, "1.56.0", Some(74935), None),
+    /// Allows coroutines to be cloned.
+    (unstable, coroutine_clone, "1.65.0", Some(95360), None),
+    /// Allows defining coroutines.
+    (unstable, coroutines, "1.21.0", Some(43122), None),
     /// Allows function attribute `#[coverage(on/off)]`, to control coverage
     /// instrumentation of that function.
     (unstable, coverage_attribute, "1.74.0", Some(84605), None),
@@ -451,10 +455,6 @@ declare_features! (
     (unstable, ffi_returns_twice, "1.34.0", Some(58314), None),
     /// Allows using `#[repr(align(...))]` on function items
     (unstable, fn_align, "1.53.0", Some(82232), None),
-    /// Allows generators to be cloned.
-    (unstable, generator_clone, "1.65.0", Some(95360), None),
-    /// Allows defining generators.
-    (unstable, generators, "1.21.0", Some(43122), None),
     /// Infer generic args for both consts and types.
     (unstable, generic_arg_infer, "1.55.0", Some(85077), None),
     /// An extension to the `generic_associated_types` feature, allowing incomplete features.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 3a4eb90f7f9..ed1dc751fba 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -118,7 +118,7 @@ pub enum DefKind {
         of_trait: bool,
     },
     Closure,
-    Generator,
+    Coroutine,
 }
 
 impl DefKind {
@@ -126,7 +126,7 @@ impl DefKind {
     ///
     /// If you have access to `TyCtxt`, use `TyCtxt::def_descr` or
     /// `TyCtxt::def_kind_descr` instead, because they give better
-    /// information for generators and associated functions.
+    /// information for coroutines and associated functions.
     pub fn descr(self, def_id: DefId) -> &'static str {
         match self {
             DefKind::Fn => "function",
@@ -161,7 +161,7 @@ impl DefKind {
             DefKind::Field => "field",
             DefKind::Impl { .. } => "implementation",
             DefKind::Closure => "closure",
-            DefKind::Generator => "generator",
+            DefKind::Coroutine => "coroutine",
             DefKind::ExternCrate => "extern crate",
             DefKind::GlobalAsm => "global assembly block",
         }
@@ -171,7 +171,7 @@ impl DefKind {
     ///
     /// If you have access to `TyCtxt`, use `TyCtxt::def_descr_article` or
     /// `TyCtxt::def_kind_descr_article` instead, because they give better
-    /// information for generators and associated functions.
+    /// information for coroutines and associated functions.
     pub fn article(&self) -> &'static str {
         match *self {
             DefKind::AssocTy
@@ -220,7 +220,7 @@ impl DefKind {
             | DefKind::LifetimeParam
             | DefKind::ExternCrate
             | DefKind::Closure
-            | DefKind::Generator
+            | DefKind::Coroutine
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::GlobalAsm
@@ -230,7 +230,7 @@ impl DefKind {
 
     #[inline]
     pub fn is_fn_like(self) -> bool {
-        matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator)
+        matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Coroutine)
     }
 
     /// Whether `query get_codegen_attrs` should be used with this definition.
@@ -240,7 +240,7 @@ impl DefKind {
             | DefKind::AssocFn
             | DefKind::Ctor(..)
             | DefKind::Closure
-            | DefKind::Generator
+            | DefKind::Coroutine
             | DefKind::Static(_) => true,
             DefKind::Mod
             | DefKind::Struct
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 3eec66611ed..f8d55192a37 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1485,7 +1485,7 @@ pub struct BodyId {
 ///
 /// - an `params` array containing the `(x, y)` pattern
 /// - a `value` containing the `x + y` expression (maybe wrapped in a block)
-/// - `generator_kind` would be `None`
+/// - `coroutine_kind` would be `None`
 ///
 /// All bodies have an **owner**, which can be accessed via the HIR
 /// map using `body_owner_def_id()`.
@@ -1493,7 +1493,7 @@ pub struct BodyId {
 pub struct Body<'hir> {
     pub params: &'hir [Param<'hir>],
     pub value: &'hir Expr<'hir>,
-    pub generator_kind: Option<GeneratorKind>,
+    pub coroutine_kind: Option<CoroutineKind>,
 }
 
 impl<'hir> Body<'hir> {
@@ -1501,48 +1501,48 @@ impl<'hir> Body<'hir> {
         BodyId { hir_id: self.value.hir_id }
     }
 
-    pub fn generator_kind(&self) -> Option<GeneratorKind> {
-        self.generator_kind
+    pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
+        self.coroutine_kind
     }
 }
 
-/// The type of source expression that caused this generator to be created.
+/// The type of source expression that caused this coroutine to be created.
 #[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum GeneratorKind {
+pub enum CoroutineKind {
     /// An explicit `async` block or the body of an async function.
-    Async(AsyncGeneratorKind),
+    Async(AsyncCoroutineKind),
 
-    /// A generator literal created via a `yield` inside a closure.
-    Gen,
+    /// A coroutine literal created via a `yield` inside a closure.
+    Coroutine,
 }
 
-impl fmt::Display for GeneratorKind {
+impl fmt::Display for CoroutineKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            GeneratorKind::Async(k) => fmt::Display::fmt(k, f),
-            GeneratorKind::Gen => f.write_str("generator"),
+            CoroutineKind::Async(k) => fmt::Display::fmt(k, f),
+            CoroutineKind::Coroutine => f.write_str("coroutine"),
         }
     }
 }
 
-impl GeneratorKind {
+impl CoroutineKind {
     pub fn descr(&self) -> &'static str {
         match self {
-            GeneratorKind::Async(ask) => ask.descr(),
-            GeneratorKind::Gen => "generator",
+            CoroutineKind::Async(ask) => ask.descr(),
+            CoroutineKind::Coroutine => "coroutine",
         }
     }
 }
 
-/// In the case of a generator created as part of an async construct,
+/// In the case of a coroutine created as part of an async construct,
 /// which kind of async construct caused it to be created?
 ///
 /// This helps error messages but is also used to drive coercions in
 /// type-checking (see #60424).
 #[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum AsyncGeneratorKind {
+pub enum AsyncCoroutineKind {
     /// An explicit `async` block written by the user.
     Block,
 
@@ -1553,22 +1553,22 @@ pub enum AsyncGeneratorKind {
     Fn,
 }
 
-impl fmt::Display for AsyncGeneratorKind {
+impl fmt::Display for AsyncCoroutineKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match self {
-            AsyncGeneratorKind::Block => "async block",
-            AsyncGeneratorKind::Closure => "async closure body",
-            AsyncGeneratorKind::Fn => "async fn body",
+            AsyncCoroutineKind::Block => "async block",
+            AsyncCoroutineKind::Closure => "async closure body",
+            AsyncCoroutineKind::Fn => "async fn body",
         })
     }
 }
 
-impl AsyncGeneratorKind {
+impl AsyncCoroutineKind {
     pub fn descr(&self) -> &'static str {
         match self {
-            AsyncGeneratorKind::Block => "`async` block",
-            AsyncGeneratorKind::Closure => "`async` closure body",
-            AsyncGeneratorKind::Fn => "`async fn` body",
+            AsyncCoroutineKind::Block => "`async` block",
+            AsyncCoroutineKind::Closure => "`async` closure body",
+            AsyncCoroutineKind::Fn => "`async fn` body",
         }
     }
 }
@@ -2004,7 +2004,7 @@ pub enum ExprKind<'hir> {
     ///
     /// The `Span` is the argument block `|...|`.
     ///
-    /// This may also be a generator literal or an `async block` as indicated by the
+    /// This may also be a coroutine literal or an `async block` as indicated by the
     /// `Option<Movability>`.
     Closure(&'hir Closure<'hir>),
     /// A block (e.g., `'label: { ... }`).
@@ -2055,7 +2055,7 @@ pub enum ExprKind<'hir> {
     /// to be repeated; the second is the number of times to repeat it.
     Repeat(&'hir Expr<'hir>, ArrayLen),
 
-    /// A suspension point for generators (i.e., `yield <expr>`).
+    /// A suspension point for coroutines (i.e., `yield <expr>`).
     Yield(&'hir Expr<'hir>, YieldSource),
 
     /// A placeholder for an expression that wasn't syntactically well formed in some way.
@@ -2247,12 +2247,12 @@ impl fmt::Display for YieldSource {
     }
 }
 
-impl From<GeneratorKind> for YieldSource {
-    fn from(kind: GeneratorKind) -> Self {
+impl From<CoroutineKind> for YieldSource {
+    fn from(kind: CoroutineKind) -> Self {
         match kind {
-            // Guess based on the kind of the current generator.
-            GeneratorKind::Gen => Self::Yield,
-            GeneratorKind::Async(_) => Self::Await { expr: None },
+            // Guess based on the kind of the current coroutine.
+            CoroutineKind::Coroutine => Self::Yield,
+            CoroutineKind::Async(_) => Self::Await { expr: None },
         }
     }
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index d9195a374c2..8a672855989 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -62,7 +62,7 @@
 //! respectively. (This follows from RPO respecting CFG domination).
 //!
 //! This order consistency is required in a few places in rustc, for
-//! example generator inference, and possibly also HIR borrowck.
+//! example coroutine inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
 use rustc_ast::walk_list;
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 4a89a6f7e39..cdfc67d5740 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -211,8 +211,8 @@ language_item_table! {
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
 
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
-    GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum,           GenericRequirement::None;
-    Generator,               sym::generator,           gen_trait,                  Target::Trait,          GenericRequirement::Minimum(1);
+    CoroutineState,          sym::coroutine_state,     gen_state,                  Target::Enum,           GenericRequirement::None;
+    Coroutine,               sym::coroutine,           gen_trait,                  Target::Trait,          GenericRequirement::Minimum(1);
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
     Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 1745488dfd3..360d31b863c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -291,7 +291,7 @@ fn check_opaque_meets_bounds<'tcx>(
 
     let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
 
-    // `ReErased` regions appear in the "parent_args" of closures/generators.
+    // `ReErased` regions appear in the "parent_args" of closures/coroutines.
     // We're ignoring them here and replacing them with fresh region variables.
     // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
     //
@@ -1394,7 +1394,7 @@ fn opaque_type_cycle_error(
                                 self.opaques.push(def);
                                 ControlFlow::Continue(())
                             }
-                            ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
+                            ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
                                 self.closures.push(def_id);
                                 t.super_visit_with(self)
                             }
@@ -1446,11 +1446,11 @@ fn opaque_type_cycle_error(
                     {
                         label_match(capture.place.ty(), capture.get_path_span(tcx));
                     }
-                    // Label any generator locals that capture the opaque
-                    if let DefKind::Generator = tcx.def_kind(closure_def_id)
-                        && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
+                    // Label any coroutine locals that capture the opaque
+                    if let DefKind::Coroutine = tcx.def_kind(closure_def_id)
+                        && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id)
                     {
-                        for interior_ty in &generator_layout.field_tys {
+                        for interior_ty in &coroutine_layout.field_tys {
                             label_match(interior_ty.ty, interior_ty.source_info.span);
                         }
                     }
@@ -1464,14 +1464,14 @@ fn opaque_type_cycle_error(
     err.emit()
 }
 
-pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Generator));
+pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine));
 
     let typeck = tcx.typeck(def_id);
     let param_env = tcx.param_env(def_id);
 
-    let generator_interior_predicates = &typeck.generator_interior_predicates[&def_id];
-    debug!(?generator_interior_predicates);
+    let coroutine_interior_predicates = &typeck.coroutine_interior_predicates[&def_id];
+    debug!(?coroutine_interior_predicates);
 
     let infcx = tcx
         .infer_ctxt()
@@ -1483,15 +1483,15 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         .build();
 
     let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
-    for (predicate, cause) in generator_interior_predicates {
+    for (predicate, cause) in coroutine_interior_predicates {
         let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
         fulfillment_cx.register_predicate_obligation(&infcx, obligation);
     }
 
     if (tcx.features().unsized_locals || tcx.features().unsized_fn_params)
-        && let Some(generator) = tcx.mir_generator_witnesses(def_id)
+        && let Some(coroutine) = tcx.mir_coroutine_witnesses(def_id)
     {
-        for field_ty in generator.field_tys.iter() {
+        for field_ty in coroutine.field_tys.iter() {
             fulfillment_cx.register_bound(
                 &infcx,
                 param_env,
@@ -1500,7 +1500,7 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 ObligationCause::new(
                     field_ty.source_info.span,
                     def_id,
-                    ObligationCauseCode::SizedGeneratorInterior(def_id),
+                    ObligationCauseCode::SizedCoroutineInterior(def_id),
                 ),
             );
         }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index a1470cc69c3..74e2b157dd0 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1557,38 +1557,24 @@ fn compare_number_of_generics<'tcx>(
                 DiagnosticId::Error("E0049".into()),
             );
 
-            let mut suffix = None;
-
+            let msg =
+                format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
             if let Some(spans) = trait_spans {
                 let mut spans = spans.iter();
                 if let Some(span) = spans.next() {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "expected {} {} parameter{}",
-                            trait_count,
-                            kind,
-                            pluralize!(trait_count),
-                        ),
-                    );
+                    err.span_label(*span, msg);
                 }
                 for span in spans {
                     err.span_label(*span, "");
                 }
             } else {
-                suffix = Some(format!(", expected {trait_count}"));
+                err.span_label(tcx.def_span(trait_.def_id), msg);
             }
 
             if let Some(span) = span {
                 err.span_label(
                     span,
-                    format!(
-                        "found {} {} parameter{}{}",
-                        impl_count,
-                        kind,
-                        pluralize!(impl_count),
-                        suffix.unwrap_or_default(),
-                    ),
+                    format!("found {} {} parameter{}", impl_count, kind, pluralize!(impl_count),),
                 );
             }
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 5d67a36288c..8da953e6e2e 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -114,7 +114,7 @@ pub fn provide(providers: &mut Providers) {
         region_scope_tree,
         collect_return_position_impl_trait_in_trait_tys,
         compare_impl_const: compare_impl_item::compare_impl_const_raw,
-        check_generator_obligations: check::check_generator_obligations,
+        check_coroutine_obligations: check::check_coroutine_obligations,
         ..*providers
     };
 }
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 463fab93e3f..40b33117f7c 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -598,7 +598,7 @@ fn resolve_local<'tcx>(
     }
 
     // Make sure we visit the initializer first, so expr_and_pat_count remains correct.
-    // The correct order, as shared between generator_interior, drop_ranges and intravisitor,
+    // The correct order, as shared between coroutine_interior, drop_ranges and intravisitor,
     // is to walk initializer, followed by pattern bindings, finally followed by the `else` block.
     if let Some(expr) = init {
         visitor.visit_expr(expr);
@@ -825,7 +825,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
             resolve_local(self, None, Some(&body.value));
         }
 
-        if body.generator_kind.is_some() {
+        if body.coroutine_kind.is_some() {
             self.scope_tree.body_expr_count.insert(body_id, self.expr_and_pat_count);
         }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 8fafbc4167f..e5e192e0079 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -162,7 +162,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
     // trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else
     // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
     // even if they do not carry that attribute.
-    use rustc_type_ir::sty::TyKind::*;
+    use rustc_type_ir::TyKind::*;
     match (source.kind(), target.kind()) {
         (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
             if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 0042d683b19..1b4df31b50c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -155,8 +155,8 @@ impl<'tcx> InherentCollect<'tcx> {
             }
             ty::FnDef(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Bound(..)
             | ty::Placeholder(_)
             | ty::Infer(_) => {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 69020b1f11d..faddb0c3829 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -243,8 +243,8 @@ fn do_orphan_check_impl<'tcx>(
             | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
 
             ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Bound(..)
             | ty::Placeholder(..)
             | ty::Infer(..) => {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 8e124d8eb1a..640138a3e5e 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -76,7 +76,7 @@ pub fn provide(providers: &mut Providers) {
         fn_sig,
         impl_trait_ref,
         impl_polarity,
-        generator_kind,
+        coroutine_kind,
         collect_mod_item_types,
         is_type_alias_impl_trait,
         ..*providers
@@ -1548,12 +1548,12 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     fty
 }
 
-fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
+fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
     match tcx.hir().get_by_def_id(def_id) {
         Node::Expr(&rustc_hir::Expr {
             kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
             ..
-        }) => tcx.hir().body(body).generator_kind(),
+        }) => tcx.hir().body(body).coroutine_kind(),
         _ => None,
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 61d9c989e2f..5f8b1ace68b 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -235,7 +235,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // leaf type -- noop
             }
 
-            ty::FnDef(..) | ty::Generator(..) | ty::Closure(..) => {
+            ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
@@ -312,7 +312,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // types, where we use Error as the Self type
             }
 
-            ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Bound(..) | ty::Infer(..) => {
+            ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Bound(..) | ty::Infer(..) => {
                 bug!("unexpected type encountered in variance inference: {}", ty);
             }
         }
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 9950a226333..4fd9391acc3 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -150,5 +150,5 @@ hir_typeck_union_pat_multiple_fields = union patterns should have exactly one fi
 hir_typeck_use_is_empty =
     consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything
 
-hir_typeck_yield_expr_outside_of_generator =
-    yield expression outside of generator literal
+hir_typeck_yield_expr_outside_of_coroutine =
+    yield expression outside of coroutine literal
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index aef880acbe1..84e986488a6 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -121,6 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         prior_arm_ty,
                         prior_arm_span,
                         scrut_span: scrut.span,
+                        scrut_hir_id: scrut.hir_id,
                         source: match_src,
                         prior_arms: other_arms.clone(),
                         opt_suggest_box_span,
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 78d30f3aa12..5eb68cf6b28 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -304,8 +304,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir::ExprKind::Block(..),
         ) = (parent_node, callee_node)
         {
-            let fn_decl_span = if hir.body(body).generator_kind
-                == Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
+            let fn_decl_span = if hir.body(body).coroutine_kind
+                == Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Closure))
             {
                 // Actually need to unwrap one more layer of HIR to get to
                 // the _real_ closure...
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 419e154a17a..a834ea15047 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -128,13 +128,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | ty::Uint(..)
             | ty::Float(_)
             | ty::Array(..)
-            | ty::GeneratorWitness(..)
+            | ty::CoroutineWitness(..)
             | ty::RawPtr(_)
             | ty::Ref(..)
             | ty::FnDef(..)
             | ty::FnPtr(..)
             | ty::Closure(..)
-            | ty::Generator(..)
+            | ty::Coroutine(..)
             | ty::Adt(..)
             | ty::Never
             | ty::Dynamic(_, _, ty::DynStar)
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 26ea7b0fdb9..e7060dac844 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -2,8 +2,8 @@ use std::cell::RefCell;
 
 use crate::coercion::CoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
+use crate::CoroutineTypes;
 use crate::FnCtxt;
-use crate::GeneratorTypes;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
@@ -31,9 +31,9 @@ pub(super) fn check_fn<'a, 'tcx>(
     decl: &'tcx hir::FnDecl<'tcx>,
     fn_def_id: LocalDefId,
     body: &'tcx hir::Body<'tcx>,
-    can_be_generator: Option<hir::Movability>,
+    can_be_coroutine: Option<hir::Movability>,
     params_can_be_unsized: bool,
-) -> Option<GeneratorTypes<'tcx>> {
+) -> Option<CoroutineTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
 
     let tcx = fcx.tcx;
@@ -55,10 +55,10 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
-    if let Some(kind) = body.generator_kind
-        && can_be_generator.is_some()
+    if let Some(kind) = body.coroutine_kind
+        && can_be_coroutine.is_some()
     {
-        let yield_ty = if kind == hir::GeneratorKind::Gen {
+        let yield_ty = if kind == hir::CoroutineKind::Coroutine {
             let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
                 kind: TypeVariableOriginKind::TypeInference,
                 span,
@@ -69,7 +69,7 @@ pub(super) fn check_fn<'a, 'tcx>(
             Ty::new_unit(tcx)
         };
 
-        // Resume type defaults to `()` if the generator has no argument.
+        // Resume type defaults to `()` if the coroutine has no argument.
         let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| Ty::new_unit(tcx));
 
         fcx.resume_yield_tys = Some((resume_ty, yield_ty));
@@ -124,13 +124,13 @@ pub(super) fn check_fn<'a, 'tcx>(
     fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
     fcx.check_return_expr(&body.value, false);
 
-    // We insert the deferred_generator_interiors entry after visiting the body.
-    // This ensures that all nested generators appear before the entry of this generator.
-    // resolve_generator_interiors relies on this property.
-    let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
+    // We insert the deferred_coroutine_interiors entry after visiting the body.
+    // This ensures that all nested coroutines appear before the entry of this coroutine.
+    // resolve_coroutine_interiors relies on this property.
+    let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_coroutine, body.coroutine_kind) {
         let interior = fcx
             .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
-        fcx.deferred_generator_interiors.borrow_mut().push((
+        fcx.deferred_coroutine_interiors.borrow_mut().push((
             fn_def_id,
             body.id(),
             interior,
@@ -138,11 +138,11 @@ pub(super) fn check_fn<'a, 'tcx>(
         ));
 
         let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
-        Some(GeneratorTypes {
+        Some(CoroutineTypes {
             resume_ty,
             yield_ty,
             interior,
-            movability: can_be_generator.unwrap(),
+            movability: can_be_coroutine.unwrap(),
         })
     } else {
         None
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 06542b0cc24..cf8a4cafbb6 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -1,6 +1,6 @@
 //! Code for type-checking closure expressions.
 
-use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
+use super::{check_fn, CoroutineTypes, Expectation, FnCtxt};
 
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
@@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!(?bound_sig, ?liberated_sig);
 
         let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
-        let generator_types = check_fn(
+        let coroutine_types = check_fn(
             &mut fcx,
             liberated_sig,
             closure.fn_decl,
@@ -105,11 +105,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span: self.tcx.def_span(expr_def_id),
         });
 
-        if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
+        if let Some(CoroutineTypes { resume_ty, yield_ty, interior, movability }) = coroutine_types
         {
-            let generator_args = ty::GeneratorArgs::new(
+            let coroutine_args = ty::CoroutineArgs::new(
                 self.tcx,
-                ty::GeneratorArgsParts {
+                ty::CoroutineArgsParts {
                     parent_args,
                     resume_ty,
                     yield_ty,
@@ -119,10 +119,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 },
             );
 
-            return Ty::new_generator(
+            return Ty::new_coroutine(
                 self.tcx,
                 expr_def_id.to_def_id(),
-                generator_args.args,
+                coroutine_args.args,
                 movability,
             );
         }
@@ -285,7 +285,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
-    /// everything we need to know about a closure or generator.
+    /// everything we need to know about a closure or coroutine.
     ///
     /// The `cause_span` should be the span that caused us to
     /// have this expected signature, or `None` if we can't readily
@@ -306,14 +306,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let is_gen = gen_trait == Some(trait_def_id);
 
         if !is_fn && !is_gen {
-            debug!("not fn or generator");
+            debug!("not fn or coroutine");
             return None;
         }
 
-        // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
+        // Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return`
         // associated item and not yield.
         if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
-            debug!("not `Return` assoc item of `Generator`");
+            debug!("not `Return` assoc item of `Coroutine`");
             return None;
         }
 
@@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => return None,
             }
         } else {
-            // Generators with a `()` resume type may be defined with 0 or 1 explicit arguments,
+            // Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments,
             // else they must have exactly 1 argument. For now though, just give up in this case.
             return None;
         };
@@ -623,7 +623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let astconv: &dyn AstConv<'_> = self;
 
         trace!("decl = {:#?}", decl);
-        debug!(?body.generator_kind);
+        debug!(?body.coroutine_kind);
 
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(expr_def_id);
         let bound_vars = self.tcx.late_bound_vars(hir_id);
@@ -632,11 +632,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
         let supplied_return = match decl.output {
             hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output),
-            hir::FnRetTy::DefaultReturn(_) => match body.generator_kind {
+            hir::FnRetTy::DefaultReturn(_) => match body.coroutine_kind {
                 // In the case of the async block that we create for a function body,
                 // we expect the return type of the block to match that of the enclosing
                 // function.
-                Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
+                Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Fn)) => {
                     debug!("closure is async fn body");
                     let def_id = self.tcx.hir().body_owner_def_id(body.id());
                     self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else(
@@ -675,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.normalize(self.tcx.hir().span(hir_id), result)
     }
 
-    /// Invoked when we are translating the generator that results
+    /// Invoked when we are translating the coroutine that results
     /// from desugaring an `async fn`. Returns the "sugared" return
     /// type of the `async fn` -- that is, the return type that the
     /// user specified. The "desugared" return type is an `impl
@@ -688,7 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         body_def_id: LocalDefId,
     ) -> Option<Ty<'tcx>> {
         let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
-            span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
+            span_bug!(self.tcx.def_span(expr_def_id), "async fn coroutine outside of a fn")
         });
 
         let closure_span = self.tcx.def_span(expr_def_id);
@@ -729,7 +729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Error(_) => return None,
             _ => span_bug!(
                 closure_span,
-                "async fn generator return type not an inference variable: {ret_ty}"
+                "async fn coroutine return type not an inference variable: {ret_ty}"
             ),
         };
 
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 8efccd5ba3e..aff1baa1960 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -62,8 +62,8 @@ pub struct RustCallIncorrectArgs {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_yield_expr_outside_of_generator, code = "E0627")]
-pub struct YieldExprOutsideOfGenerator {
+#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = "E0627")]
+pub struct YieldExprOutsideOfCoroutine {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 96df0346ac6..be225ceb843 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -10,7 +10,7 @@ use crate::errors::TypeMismatchFruTypo;
 use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
 use crate::errors::{
     FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
-    YieldExprOutsideOfGenerator,
+    YieldExprOutsideOfCoroutine,
 };
 use crate::fatally_break_rust;
 use crate::method::{MethodCallComponents, SelfSource};
@@ -3019,7 +3019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_unit(self.tcx)
             }
             _ => {
-                self.tcx.sess.emit_err(YieldExprOutsideOfGenerator { span: expr.span });
+                self.tcx.sess.emit_err(YieldExprOutsideOfCoroutine { span: expr.span });
                 // Avoid expressions without types during writeback (#78653).
                 self.check_expr(value);
                 Ty::new_unit(self.tcx)
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 8bc66ac5509..6be3ad6577b 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -779,7 +779,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         let closure_def_id = closure_expr.def_id;
         let upvars = tcx.upvars_mentioned(self.body_owner);
 
-        // For purposes of this function, generator and closures are equivalent.
+        // For purposes of this function, coroutine and closures are equivalent.
         let body_owner_is_closure =
             matches!(tcx.hir().body_owner_kind(self.body_owner), hir::BodyOwnerKind::Closure,);
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6e0e02b7814..afa5a3b9379 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -509,40 +509,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         typeck_results.rvalue_scopes = rvalue_scopes;
     }
 
-    /// Unify the inference variables corresponding to generator witnesses, and save all the
+    /// Unify the inference variables corresponding to coroutine witnesses, and save all the
     /// predicates that were stalled on those inference variables.
     ///
-    /// This process allows to conservatively save all predicates that do depend on the generator
-    /// interior types, for later processing by `check_generator_obligations`.
+    /// This process allows to conservatively save all predicates that do depend on the coroutine
+    /// interior types, for later processing by `check_coroutine_obligations`.
     ///
     /// We must not attempt to select obligations after this method has run, or risk query cycle
     /// ICE.
     #[instrument(level = "debug", skip(self))]
-    pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
+    pub(in super::super) fn resolve_coroutine_interiors(&self, def_id: DefId) {
         // Try selecting all obligations that are not blocked on inference variables.
-        // Once we start unifying generator witnesses, trying to select obligations on them will
+        // Once we start unifying coroutine witnesses, trying to select obligations on them will
         // trigger query cycle ICEs, as doing so requires MIR.
         self.select_obligations_where_possible(|_| {});
 
-        let generators = std::mem::take(&mut *self.deferred_generator_interiors.borrow_mut());
-        debug!(?generators);
+        let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut());
+        debug!(?coroutines);
 
-        for &(expr_def_id, body_id, interior, _) in generators.iter() {
+        for &(expr_def_id, body_id, interior, _) in coroutines.iter() {
             debug!(?expr_def_id);
 
-            // Create the `GeneratorWitness` type that we will unify with `interior`.
+            // Create the `CoroutineWitness` type that we will unify with `interior`.
             let args = ty::GenericArgs::identity_for_item(
                 self.tcx,
                 self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
             );
-            let witness = Ty::new_generator_witness(self.tcx, expr_def_id.to_def_id(), args);
+            let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args);
 
             // Unify `interior` with `witness` and collect all the resulting obligations.
             let span = self.tcx.hir().body(body_id).value.span;
             let ok = self
                 .at(&self.misc(span), self.param_env)
                 .eq(DefineOpaqueTypes::No, interior, witness)
-                .expect("Failed to unify generator interior type");
+                .expect("Failed to unify coroutine interior type");
             let mut obligations = ok.obligations;
 
             // Also collect the obligations that were unstalled by this unification.
@@ -553,7 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             debug!(?obligations);
             self.typeck_results
                 .borrow_mut()
-                .generator_interior_predicates
+                .coroutine_interior_predicates
                 .insert(expr_def_id, obligations);
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 522d0e2616b..facbeb8badf 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -366,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. },
             ),
         ) = error.code
-            && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) =
+            && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
                 expected_trait_ref.skip_binder().self_ty().kind()
             && span.overlaps(self.tcx.def_span(*def_id))
         {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 9f1800b45c3..33dfa16a651 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -367,13 +367,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 }
 
-                // For this check, we do *not* want to treat async generator closures (async blocks)
+                // For this check, we do *not* want to treat async coroutine closures (async blocks)
                 // as proper closures. Doing so would regress type inference when feeding
                 // the return value of an argument-position async block to an argument-position
                 // closure wrapped in a block.
                 // See <https://github.com/rust-lang/rust/issues/112225>.
                 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
-                    !tcx.generator_is_async(closure.def_id.to_def_id())
+                    !tcx.coroutine_is_async(closure.def_id.to_def_id())
                 } else {
                     false
                 };
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 14d69141343..04220397872 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -9,7 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
-    AsyncGeneratorKind, Expr, ExprKind, GeneratorKind, GenericBound, HirId, Node, Path, QPath,
+    AsyncCoroutineKind, CoroutineKind, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath,
     Stmt, StmtKind, TyKind, WherePredicate,
 };
 use rustc_hir_analysis::astconv::AstConv;
@@ -532,10 +532,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Tuple(tuple) if tuple.is_empty() => {
                     errors::SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span }
                 }
-                ty::Generator(def_id, ..)
+                ty::Coroutine(def_id, ..)
                     if matches!(
-                        self.tcx.generator_kind(def_id),
-                        Some(GeneratorKind::Async(AsyncGeneratorKind::Closure))
+                        self.tcx.coroutine_kind(def_id),
+                        Some(CoroutineKind::Async(AsyncCoroutineKind::Closure))
                     ) =>
                 {
                     errors::SuggestBoxing::AsyncBody
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index bee79242fd1..efd0b8577cf 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -55,8 +55,8 @@ pub struct Inherited<'tcx> {
 
     pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
 
-    pub(super) deferred_generator_interiors:
-        RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
+    pub(super) deferred_coroutine_interiors:
+        RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>, hir::CoroutineKind)>>,
 
     /// Whenever we introduce an adjustment from `!` into a type variable,
     /// we record that type variable here. This is later used to inform
@@ -94,7 +94,7 @@ impl<'tcx> Inherited<'tcx> {
             deferred_cast_checks: RefCell::new(Vec::new()),
             deferred_transmute_checks: RefCell::new(Vec::new()),
             deferred_asm_checks: RefCell::new(Vec::new()),
-            deferred_generator_interiors: RefCell::new(Vec::new()),
+            deferred_coroutine_interiors: RefCell::new(Vec::new()),
             diverging_type_vars: RefCell::new(Default::default()),
             infer_var_info: RefCell::new(Default::default()),
         }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index cd6adb345e7..46dcc455558 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -255,11 +255,11 @@ fn typeck_with_fallback<'tcx>(
     fcx.check_casts();
     fcx.select_obligations_where_possible(|_| {});
 
-    // Closure and generator analysis may run after fallback
+    // Closure and coroutine analysis may run after fallback
     // because they don't constrain other type variables.
     fcx.closure_analyze(body);
     assert!(fcx.deferred_call_resolutions.borrow().is_empty());
-    // Before the generator analysis, temporary scopes shall be marked to provide more
+    // Before the coroutine analysis, temporary scopes shall be marked to provide more
     // precise information on types to be captured.
     fcx.resolve_rvalue_scopes(def_id.to_def_id());
 
@@ -273,7 +273,7 @@ fn typeck_with_fallback<'tcx>(
     debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
 
     // This must be the last thing before `report_ambiguity_errors`.
-    fcx.resolve_generator_interiors(def_id.to_def_id());
+    fcx.resolve_coroutine_interiors(def_id.to_def_id());
 
     debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
 
@@ -298,20 +298,20 @@ fn typeck_with_fallback<'tcx>(
     typeck_results
 }
 
-/// When `check_fn` is invoked on a generator (i.e., a body that
+/// When `check_fn` is invoked on a coroutine (i.e., a body that
 /// includes yield), it returns back some information about the yield
 /// points.
-struct GeneratorTypes<'tcx> {
-    /// Type of generator argument / values returned by `yield`.
+struct CoroutineTypes<'tcx> {
+    /// Type of coroutine argument / values returned by `yield`.
     resume_ty: Ty<'tcx>,
 
     /// Type of value that is yielded.
     yield_ty: Ty<'tcx>,
 
-    /// Types that are captured (see `GeneratorInterior` for more).
+    /// Types that are captured (see `CoroutineInterior` for more).
     interior: Ty<'tcx>,
 
-    /// Indicates if the generator is movable or static (immovable).
+    /// Indicates if the coroutine is movable or static (immovable).
     movability: hir::Movability,
 }
 
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index c46e641b10d..d0d3b0e5b73 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -20,7 +20,7 @@ use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
-use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::TyKind::*;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 4d641390368..75c70ec59fb 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.node_ty(closure_hir_id);
         let (closure_def_id, args) = match *ty.kind() {
             ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)),
-            ty::Generator(def_id, args, _) => (def_id, UpvarArgs::Generator(args)),
+            ty::Coroutine(def_id, args, _) => (def_id, UpvarArgs::Coroutine(args)),
             ty::Error(_) => {
                 // #51714: skip analysis when we have already encountered type errors
                 return;
@@ -366,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Note that we *always* infer a minimal kind, even if
     /// we don't always *use* that in the final result (i.e., sometimes
     /// we've taken the closure kind from the expectations instead, and
-    /// for generators we don't even implement the closure traits
+    /// for coroutines we don't even implement the closure traits
     /// really).
     ///
     /// If we inferred that the closure needs to be FnMut/FnOnce, last element of the returned tuple
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 322859154bb..896aacc6993 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_coercion_casts();
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
-        wbcx.visit_generator_interior();
+        wbcx.visit_coroutine_interior();
         wbcx.visit_offset_of_container_types();
 
         wbcx.typeck_results.rvalue_scopes =
@@ -540,16 +540,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         );
     }
 
-    fn visit_generator_interior(&mut self) {
+    fn visit_coroutine_interior(&mut self) {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
         self.tcx().with_stable_hashing_context(move |ref hcx| {
             for (&expr_def_id, predicates) in
-                fcx_typeck_results.generator_interior_predicates.to_sorted(hcx, false).into_iter()
+                fcx_typeck_results.coroutine_interior_predicates.to_sorted(hcx, false).into_iter()
             {
                 let predicates =
                     self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
-                self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
+                self.typeck_results.coroutine_interior_predicates.insert(expr_def_id, predicates);
             }
         })
     }
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index b36fb6a4dba..2de87cbe631 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -181,19 +181,19 @@ infer_more_targeted = {$has_param_name ->
 
 infer_msl_introduces_static = introduces a `'static` lifetime requirement
 infer_msl_unmet_req = because this has an unmet lifetime requirement
-infer_need_type_info_in_generator =
-    type inside {$generator_kind ->
+infer_need_type_info_in_coroutine =
+    type inside {$coroutine_kind ->
     [async_block] `async` block
     [async_closure] `async` closure
     [async_fn] `async fn` body
-    *[generator] generator
+    *[coroutine] coroutine
     } must be known in this context
 
 
 infer_nothing = {""}
 
 infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
-infer_oc_closure_selfref = closure/generator type that references itself
+infer_oc_closure_selfref = closure/coroutine type that references itself
 infer_oc_const_compat = const not compatible with trait
 infer_oc_fn_lang_correct_type = {$lang_item_name ->
         [panic_impl] `#[panic_handler]`
@@ -284,7 +284,7 @@ infer_sbfrit_change_return_type = you could change the return type to be a boxed
 infer_source_kind_closure_return =
     try giving this closure an explicit return type
 
-# generator_kind  may need to be translated
+# coroutine_kind  may need to be translated
 infer_source_kind_fully_qualified =
     try using a fully qualified path to specify the expected types
 
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 4124c9eada9..0e2f9ba70fe 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -457,8 +457,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
             }
 
             ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Bool
             | ty::Char
             | ty::Int(..)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 496bb1766a7..97ab3d0b751 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -776,6 +776,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ref prior_arms,
                 opt_suggest_box_span,
                 scrut_span,
+                scrut_hir_id,
                 ..
             }) => match source {
                 hir::MatchSource::TryDesugar(scrut_hir_id) => {
@@ -843,6 +844,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ) {
                         err.subdiagnostic(subdiag);
                     }
+                    if let Some(hir::Node::Expr(m)) = self.tcx.hir().find_parent(scrut_hir_id)
+                        && let Some(hir::Node::Stmt(stmt)) = self.tcx.hir().find_parent(m.hir_id)
+                        && let hir::StmtKind::Expr(_) = stmt.kind
+                    {
+                        err.span_suggestion_verbose(
+                            stmt.span.shrink_to_hi(),
+                            "consider using a semicolon here, but this will discard any values \
+                             in the match arms",
+                            ";",
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                     if let Some(ret_sp) = opt_suggest_box_span {
                         // Get return type span and point to it.
                         self.suggest_boxing_for_return_impl_trait(
@@ -2821,7 +2834,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             // say, also take a look at the error code, maybe we can
             // tailor to that.
             _ => match terr {
-                TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => Error0644,
+                TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => Error0644,
                 TypeError::IntrinsicCast => Error0308,
                 _ => Error0308,
             },
@@ -2868,7 +2881,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             // say, also take a look at the error code, maybe we can
             // tailor to that.
             _ => match terr {
-                TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
+                TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => {
                     ObligationCauseFailureCode::ClosureSelfref { span }
                 }
                 TypeError::IntrinsicCast => {
@@ -2936,7 +2949,7 @@ pub enum TyCategory {
     Closure,
     Opaque,
     OpaqueFuture,
-    Generator(hir::GeneratorKind),
+    Coroutine(hir::CoroutineKind),
     Foreign,
 }
 
@@ -2946,7 +2959,7 @@ impl TyCategory {
             Self::Closure => "closure",
             Self::Opaque => "opaque type",
             Self::OpaqueFuture => "future",
-            Self::Generator(gk) => gk.descr(),
+            Self::Coroutine(gk) => gk.descr(),
             Self::Foreign => "foreign type",
         }
     }
@@ -2959,8 +2972,8 @@ impl TyCategory {
                     if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque };
                 Some((kind, def_id))
             }
-            ty::Generator(def_id, ..) => {
-                Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
+            ty::Coroutine(def_id, ..) => {
+                Some((Self::Coroutine(tcx.coroutine_kind(def_id).unwrap()), def_id))
             }
             ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
             _ => None,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 5408b99235d..7bc414ff522 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -864,11 +864,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 GenericArgKind::Type(ty) => {
                     if matches!(
                         ty.kind(),
-                        ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Generator(..)
+                        ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Coroutine(..)
                     ) {
                         // Opaque types can't be named by the user right now.
                         //
-                        // Both the generic arguments of closures and generators can
+                        // Both the generic arguments of closures and coroutines can
                         // also not be named. We may want to only look into the closure
                         // signature in case it has no captures, as that can be represented
                         // using `fn(T) -> R`.
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 3da6d8a89e1..faea8bc98aa 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -215,7 +215,7 @@ impl<T> Trait<T> for X {
                              #traits-as-parameters",
                         );
                     }
-                    (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
+                    (ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => {
                         let generics = tcx.generics_of(body_owner_def_id);
                         let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
                         if !sp.contains(p_span) {
@@ -325,7 +325,7 @@ impl<T> Trait<T> for X {
             }
             CyclicTy(ty) => {
                 // Watch out for various cases of cyclic types and try to explain.
-                if ty.is_closure() || ty.is_generator() {
+                if ty.is_closure() || ty.is_coroutine() {
                     diag.note(
                         "closures cannot capture themselves or take themselves as argument;\n\
                          this error may be the result of a recent compiler bug-fix,\n\
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 1c3a5c36076..e1a14ed0faf 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -454,16 +454,16 @@ where
                 args.as_closure().sig_as_fn_ptr_ty().visit_with(self);
             }
 
-            ty::Generator(_, ref args, _) => {
+            ty::Coroutine(_, ref args, _) => {
                 // Skip lifetime parameters of the enclosing item(s)
                 // Also skip the witness type, because that has no free regions.
 
-                for upvar in args.as_generator().upvar_tys() {
+                for upvar in args.as_coroutine().upvar_tys() {
                     upvar.visit_with(self);
                 }
-                args.as_generator().return_ty().visit_with(self);
-                args.as_generator().yield_ty().visit_with(self);
-                args.as_generator().resume_ty().visit_with(self);
+                args.as_coroutine().return_ty().visit_with(self);
+                args.as_coroutine().yield_ty().visit_with(self);
+                args.as_coroutine().resume_ty().visit_with(self);
             }
 
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref args, .. }) => {
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 6a9d40daab6..38819e8ad8a 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -102,17 +102,17 @@ fn compute_components<'tcx>(
                 compute_components(tcx, tupled_ty, out, visited);
             }
 
-            ty::Generator(_, ref args, _) => {
+            ty::Coroutine(_, ref args, _) => {
                 // Same as the closure case
-                let tupled_ty = args.as_generator().tupled_upvars_ty();
+                let tupled_ty = args.as_coroutine().tupled_upvars_ty();
                 compute_components(tcx, tupled_ty, out, visited);
 
-                // We ignore regions in the generator interior as we don't
+                // We ignore regions in the coroutine interior as we don't
                 // want these to affect region inference
             }
 
             // All regions are bound inside a witness
-            ty::GeneratorWitness(..) => (),
+            ty::CoroutineWitness(..) => (),
 
             // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
             // is implied by the environment is done in regionck.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 718dbaaafcc..7a7e9024bd8 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -799,9 +799,9 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
     });
 
     tcx.hir().par_body_owners(|def_id| {
-        if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) {
-            tcx.ensure().mir_generator_witnesses(def_id);
-            tcx.ensure().check_generator_obligations(def_id);
+        if let rustc_hir::def::DefKind::Coroutine = tcx.def_kind(def_id) {
+            tcx.ensure().mir_coroutine_witnesses(def_id);
+            tcx.ensure().check_coroutine_obligations(def_id);
         }
     });
 
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 4c4d2933bf4..068f1372c0e 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -551,19 +551,19 @@ lint_unused_closure =
 
 lint_unused_comparisons = comparison is useless due to type limits
 
+lint_unused_coroutine =
+    unused {$pre}{$count ->
+        [one] coroutine
+        *[other] coroutine
+    }{$post} that must be used
+    .note = coroutines are lazy and do nothing unless resumed
+
 lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
     .suggestion = use `let _ = ...` to ignore the resulting value
 
 lint_unused_delim = unnecessary {$delim} around {$item}
     .suggestion = remove these {$delim}
 
-lint_unused_generator =
-    unused {$pre}{$count ->
-        [one] generator
-        *[other] generator
-    }{$post} that must be used
-    .note = generators are lazy and do nothing unless resumed
-
 lint_unused_import_braces = braces around {$node} is unnecessary
 
 lint_unused_op = unused {$op} that must be used
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index f6c7f4071dc..6f6150a4172 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2475,7 +2475,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             ty: Ty<'tcx>,
             init: InitKind,
         ) -> Option<InitError> {
-            use rustc_type_ir::sty::TyKind::*;
+            use rustc_type_ir::TyKind::*;
             match ty.kind() {
                 // Primitive types that don't like 0 as a value.
                 Ref(..) => Some("references must be non-null".into()),
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index e1df69bdaf2..86b3b4ad0ca 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -262,7 +262,7 @@ fn structurally_same_type_impl<'tcx>(
         true
     } else {
         // Do a full, depth-first comparison between the two.
-        use rustc_type_ir::sty::TyKind::*;
+        use rustc_type_ir::TyKind::*;
         let a_kind = a.kind();
         let b_kind = b.kind();
 
@@ -369,8 +369,8 @@ fn structurally_same_type_impl<'tcx>(
                 (Dynamic(..), Dynamic(..))
                 | (Error(..), Error(..))
                 | (Closure(..), Closure(..))
-                | (Generator(..), Generator(..))
-                | (GeneratorWitness(..), GeneratorWitness(..))
+                | (Coroutine(..), Coroutine(..))
+                | (CoroutineWitness(..), CoroutineWitness(..))
                 | (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
                 | (Alias(ty::Inherent, ..), Alias(ty::Inherent, ..))
                 | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 4eaf8bbf5de..756899e50a8 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1700,9 +1700,9 @@ pub struct UnusedClosure<'a> {
 // FIXME(davidtwco): this isn't properly translatable because of the
 // pre/post strings
 #[derive(LintDiagnostic)]
-#[diag(lint_unused_generator)]
+#[diag(lint_unused_coroutine)]
 #[note]
-pub struct UnusedGenerator<'a> {
+pub struct UnusedCoroutine<'a> {
     pub count: usize,
     pub pre: &'a str,
     pub post: &'a str,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f89b63e6f9f..c04053d1865 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1272,8 +1272,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             | ty::Bound(..)
             | ty::Error(_)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Placeholder(..)
             | ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
         }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 65de7e10272..6b31fb079e0 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,7 +1,7 @@
 use crate::lints::{
     PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
-    UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
-    UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
+    UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
+    UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
     UnusedResult,
 };
 use crate::Lint;
@@ -257,8 +257,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             Array(Box<Self>, u64),
             /// The root of the unused_closures lint.
             Closure(Span),
-            /// The root of the unused_generators lint.
-            Generator(Span),
+            /// The root of the unused_coroutines lint.
+            Coroutine(Span),
         }
 
         #[instrument(skip(cx, expr), level = "debug", ret)]
@@ -350,16 +350,16 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         .map(|inner| MustUsePath::Array(Box::new(inner), len)),
                 },
                 ty::Closure(..) => Some(MustUsePath::Closure(span)),
-                ty::Generator(def_id, ..) => {
+                ty::Coroutine(def_id, ..) => {
                     // async fn should be treated as "implementor of `Future`"
-                    let must_use = if cx.tcx.generator_is_async(def_id) {
+                    let must_use = if cx.tcx.coroutine_is_async(def_id) {
                         let def_id = cx.tcx.lang_items().future_trait()?;
                         is_def_must_use(cx, def_id, span)
                             .map(|inner| MustUsePath::Opaque(Box::new(inner)))
                     } else {
                         None
                     };
-                    must_use.or(Some(MustUsePath::Generator(span)))
+                    must_use.or(Some(MustUsePath::Coroutine(span)))
                 }
                 _ => None,
             }
@@ -482,11 +482,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
                     );
                 }
-                MustUsePath::Generator(span) => {
+                MustUsePath::Coroutine(span) => {
                     cx.emit_spanned_lint(
                         UNUSED_MUST_USE,
                         *span,
-                        UnusedGenerator { count: plural_len, pre: descr_pre, post: descr_post },
+                        UnusedCoroutine { count: plural_len, pre: descr_pre, post: descr_post },
                     );
                 }
                 MustUsePath::Def(span, def_id, reason) => {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index c8d42937f7b..918e484b9f4 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3953,8 +3953,13 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a
-    /// pattern for a `#[non_exhaustive]` struct or enum is reachable.
+    /// The `non_exhaustive_omitted_patterns` lint aims to help consumers of a `#[non_exhaustive]`
+    /// struct or enum who want to match all of its fields/variants explicitly.
+    ///
+    /// The `#[non_exhaustive]` annotation forces matches to use wildcards, so exhaustiveness
+    /// checking cannot be used to ensure that all fields/variants are matched explicitly. To remedy
+    /// this, this allow-by-default lint warns the user when a match mentions some but not all of
+    /// the fields/variants of a `#[non_exhaustive]` struct or enum.
     ///
     /// ### Example
     ///
@@ -3968,9 +3973,9 @@ declare_lint! {
     ///
     /// // in crate B
     /// #![feature(non_exhaustive_omitted_patterns_lint)]
+    /// #[warn(non_exhaustive_omitted_patterns)]
     /// match Bar::A {
     ///     Bar::A => {},
-    ///     #[warn(non_exhaustive_omitted_patterns)]
     ///     _ => {},
     /// }
     /// ```
@@ -3978,29 +3983,32 @@ declare_lint! {
     /// This will produce:
     ///
     /// ```text
-    /// warning: reachable patterns not covered of non exhaustive enum
+    /// warning: some variants are not matched explicitly
     ///    --> $DIR/reachable-patterns.rs:70:9
     ///    |
-    /// LL |         _ => {}
-    ///    |         ^ pattern `B` not covered
+    /// LL |         match Bar::A {
+    ///    |               ^ pattern `Bar::B` not covered
     ///    |
     ///  note: the lint level is defined here
     ///   --> $DIR/reachable-patterns.rs:69:16
     ///    |
     /// LL |         #[warn(non_exhaustive_omitted_patterns)]
     ///    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    ///    = help: ensure that all possible cases are being handled by adding the suggested match arms
+    ///    = help: ensure that all variants are matched explicitly by adding the suggested match arms
     ///    = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found
     /// ```
     ///
+    /// Warning: setting this to `deny` will make upstream non-breaking changes (adding fields or
+    /// variants to a `#[non_exhaustive]` struct or enum) break your crate. This goes against
+    /// expected semver behavior.
+    ///
     /// ### Explanation
     ///
-    /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a
-    /// (potentially redundant) wildcard when pattern-matching, to allow for future
-    /// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint
-    /// detects when such a wildcard happens to actually catch some fields/variants.
-    /// In other words, when the match without the wildcard would not be exhaustive.
-    /// This lets the user be informed if new fields/variants were added.
+    /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a (potentially
+    /// redundant) wildcard when pattern-matching, to allow for future addition of fields or
+    /// variants. The `non_exhaustive_omitted_patterns` lint detects when such a wildcard happens to
+    /// actually catch some fields/variants. In other words, when the match without the wildcard
+    /// would not be exhaustive. This lets the user be informed if new fields/variants were added.
     pub NON_EXHAUSTIVE_OMITTED_PATTERNS,
     Allow,
     "detect when patterns of types marked `non_exhaustive` are missed",
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index ddeb39669dc..ec2517b581e 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -4,8 +4,9 @@
 #![cfg_attr(not(bootstrap), allow(internal_features))]
 #![feature(decl_macro)]
 #![feature(extract_if)]
-#![feature(generators)]
-#![feature(iter_from_generator)]
+#![cfg_attr(bootstrap, feature(generators))]
+#![cfg_attr(not(bootstrap), feature(coroutines))]
+#![feature(iter_from_coroutine)]
 #![feature(let_chains)]
 #![feature(proc_macro_internals)]
 #![feature(macro_metavar_expr)]
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index d6ceaa8a091..354023cea9e 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1239,7 +1239,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         id: DefIndex,
         sess: &'a Session,
     ) -> impl Iterator<Item = ModChild> + 'a {
-        iter::from_generator(move || {
+        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.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6b6c0d52742..595d816e949 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -221,7 +221,7 @@ provide! { tcx, def_id, other, cdata,
     optimized_mir => { table }
     mir_for_ctfe => { table }
     closure_saved_names_of_captured_variables => { table }
-    mir_generator_witnesses => { table }
+    mir_coroutine_witnesses => { table }
     promoted_mir => { table }
     def_span => { table }
     def_ident_span => { table }
@@ -241,7 +241,7 @@ provide! { tcx, def_id, other, cdata,
     rendered_const => { table }
     asyncness => { table_direct }
     fn_arg_names => { table }
-    generator_kind => { table }
+    coroutine_kind => { table }
     trait_def => { table }
     deduced_param_attrs => { table }
     is_type_alias_impl_trait => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 345b3d5e57f..de436c16ca9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -856,7 +856,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::Field
         | DefKind::Impl { .. }
         | DefKind::Closure
-        | DefKind::Generator => true,
+        | DefKind::Coroutine => true,
         DefKind::ForeignMod | DefKind::GlobalAsm => false,
     }
 }
@@ -897,7 +897,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
         | DefKind::OpaqueTy
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
-        | DefKind::Generator => false,
+        | DefKind::Coroutine => false,
     }
 }
 
@@ -933,7 +933,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::Generator => false,
+        | DefKind::Coroutine => false,
     }
 }
 
@@ -968,7 +968,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::GlobalAsm
         | DefKind::Impl { .. }
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ExternCrate => false,
     }
 }
@@ -1004,7 +1004,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ExternCrate => false,
     }
 }
@@ -1060,8 +1060,8 @@ fn should_encode_mir(
                 || tcx.is_const_default_method(def_id.to_def_id());
             (is_const_fn, opt)
         }
-        // Generators require optimized MIR to compute layout.
-        DefKind::Generator => (false, true),
+        // Coroutines require optimized MIR to compute layout.
+        DefKind::Coroutine => (false, true),
         // The others don't have MIR.
         _ => (false, false),
     }
@@ -1097,7 +1097,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
         | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ExternCrate => false,
         DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
     }
@@ -1127,7 +1127,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::Field
         | DefKind::TyParam
         | DefKind::Closure
-        | DefKind::Generator => true,
+        | DefKind::Coroutine => true,
         DefKind::Mod
         | DefKind::ForeignMod
         | DefKind::ConstParam
@@ -1156,7 +1156,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ConstParam
         | DefKind::AnonConst
         | DefKind::InlineConst => true,
@@ -1217,7 +1217,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
         | DefKind::Impl { .. }
         | DefKind::AssocConst
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ConstParam
         | DefKind::AnonConst
         | DefKind::InlineConst
@@ -1256,7 +1256,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
         | DefKind::OpaqueTy
         | DefKind::Impl { of_trait: false }
         | DefKind::ForeignTy
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ConstParam
         | DefKind::InlineConst
         | DefKind::AssocTy
@@ -1291,7 +1291,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
         | DefKind::Impl { .. }
         | DefKind::AssocFn
         | DefKind::Closure
-        | DefKind::Generator
+        | DefKind::Coroutine
         | DefKind::ConstParam
         | DefKind::AssocTy
         | DefKind::TyParam
@@ -1446,9 +1446,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     self.encode_info_for_assoc_item(def_id);
                 }
             }
-            if let DefKind::Generator = def_kind {
-                let data = self.tcx.generator_kind(def_id).unwrap();
-                record!(self.tables.generator_kind[def_id] <- data);
+            if let DefKind::Coroutine = def_kind {
+                let data = self.tcx.coroutine_kind(def_id).unwrap();
+                record!(self.tables.coroutine_kind[def_id] <- data);
             }
             if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
                 self.encode_info_for_adt(local_id);
@@ -1629,10 +1629,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
                     <- tcx.closure_saved_names_of_captured_variables(def_id));
 
-                if let DefKind::Generator = self.tcx.def_kind(def_id)
-                    && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+                if let DefKind::Coroutine = self.tcx.def_kind(def_id)
+                    && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
                 {
-                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
+                    record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
                 }
             }
             if encode_const {
@@ -1656,10 +1656,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
 
-            if let DefKind::Generator = self.tcx.def_kind(def_id)
-                && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+            if let DefKind::Coroutine = self.tcx.def_kind(def_id)
+                && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
             {
-                record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
+                record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
             }
 
             let instance = ty::InstanceDef::Item(def_id.to_def_id());
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 2609767a85c..9ae5c0af0b2 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -429,7 +429,7 @@ define_tables! {
     mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
     cross_crate_inlinable: Table<DefIndex, bool>,
     closure_saved_names_of_captured_variables: Table<DefIndex, LazyValue<IndexVec<FieldIdx, Symbol>>>,
-    mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
+    mir_coroutine_witnesses: Table<DefIndex, LazyValue<mir::CoroutineLayout<'static>>>,
     promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
     thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::Const<'static>>>>,
     impl_parent: Table<DefIndex, RawDefId>,
@@ -442,7 +442,7 @@ define_tables! {
     rendered_const: Table<DefIndex, LazyValue<String>>,
     asyncness: Table<DefIndex, ty::Asyncness>,
     fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
-    generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
+    coroutine_kind: Table<DefIndex, LazyValue<hir::CoroutineKind>>,
     trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
     trait_item_def_id: Table<DefIndex, RawDefId>,
     expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 34118e9e8a3..027994c40ab 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -167,7 +167,7 @@ fixed_size_enum! {
         ( Impl { of_trait: false }                 )
         ( Impl { of_trait: true }                  )
         ( Closure                                  )
-        ( Generator                                )
+        ( Coroutine                                )
         ( Static(ast::Mutability::Not)             )
         ( Static(ast::Mutability::Mut)             )
         ( Ctor(CtorOf::Struct, CtorKind::Fn)       )
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 82162fd8571..37ff5bcf1e2 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -5,12 +5,12 @@ middle_assert_async_resume_after_panic = `async fn` resumed after panicking
 
 middle_assert_async_resume_after_return = `async fn` resumed after completion
 
-middle_assert_divide_by_zero =
-    attempt to divide `{$val}` by zero
+middle_assert_coroutine_resume_after_panic = coroutine resumed after panicking
 
-middle_assert_generator_resume_after_panic = generator resumed after panicking
+middle_assert_coroutine_resume_after_return = coroutine resumed after completion
 
-middle_assert_generator_resume_after_return = generator resumed after completion
+middle_assert_divide_by_zero =
+    attempt to divide `{$val}` by zero
 
 middle_assert_misaligned_ptr_deref =
     misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 77643715fff..3ca26ec98c6 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -240,7 +240,7 @@ impl<'hir> Map<'hir> {
             Node::Field(_) => DefKind::Field,
             Node::Expr(expr) => match expr.kind {
                 ExprKind::Closure(Closure { movability: None, .. }) => DefKind::Closure,
-                ExprKind::Closure(Closure { movability: Some(_), .. }) => DefKind::Generator,
+                ExprKind::Closure(Closure { movability: Some(_), .. }) => DefKind::Coroutine,
                 _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
             },
             Node::GenericParam(param) => match param.kind {
@@ -445,7 +445,7 @@ impl<'hir> Map<'hir> {
             }
             DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
             DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
-            DefKind::Closure | DefKind::Generator => BodyOwnerKind::Closure,
+            DefKind::Closure | DefKind::Coroutine => BodyOwnerKind::Closure,
             DefKind::Static(mt) => BodyOwnerKind::Static(mt),
             dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
         }
diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs
index 6896837aa91..adbe81bb22c 100644
--- a/compiler/rustc_middle/src/hir/nested_filter.rs
+++ b/compiler/rustc_middle/src/hir/nested_filter.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::nested_filter::NestedFilter;
 /// that are inside of an item-like.
 ///
 /// Notably, possible occurrences of bodies in non-item-like things
-/// include: closures/generators, inline `const {}` blocks, and
+/// include: closures/coroutines, inline `const {}` blocks, and
 /// constant arguments of types, e.g. in `let _: [(); /* HERE */];`.
 ///
 /// **This is the most common choice.** A very common pattern is
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index dee18dc1162..448a3029ae9 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -32,11 +32,12 @@
 #![feature(core_intrinsics)]
 #![feature(discriminant_kind)]
 #![feature(exhaustive_patterns)]
-#![feature(generators)]
+#![cfg_attr(bootstrap, feature(generators))]
+#![cfg_attr(not(bootstrap), feature(coroutines))]
 #![feature(get_mut_unchecked)]
 #![feature(if_let_guard)]
 #![feature(inline_const)]
-#![feature(iter_from_generator)]
+#![feature(iter_from_coroutine)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(extern_types)]
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index c50c5e6f701..56fed05c63f 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -308,7 +308,7 @@ pub struct ScopeTree {
 
     /// The number of visit_expr and visit_pat calls done in the body.
     /// Used to sanity check visit_expr/visit_pat call count when
-    /// calculating generator interiors.
+    /// calculating coroutine interiors.
     pub body_expr_count: FxHashMap<hir::BodyId, usize>,
 }
 
@@ -413,7 +413,7 @@ impl ScopeTree {
 
     /// Gives the number of expressions visited in a body.
     /// Used to sanity check visit_expr call count when
-    /// calculating generator interiors.
+    /// calculating coroutine interiors.
     pub fn body_expr_count(&self, body_id: hir::BodyId) -> Option<usize> {
         self.body_expr_count.get(&body_id).copied()
     }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 3a5ff4dc91f..a85af7c3fb5 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -17,7 +17,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
-use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
+use rustc_hir::{self, CoroutineKind, ImplicitSelfKind};
 use rustc_hir::{self as hir, HirId};
 use rustc_session::Session;
 use rustc_target::abi::{FieldIdx, VariantIdx};
@@ -246,19 +246,19 @@ impl<'tcx> MirSource<'tcx> {
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
-pub struct GeneratorInfo<'tcx> {
-    /// The yield type of the function, if it is a generator.
+pub struct CoroutineInfo<'tcx> {
+    /// The yield type of the function, if it is a coroutine.
     pub yield_ty: Option<Ty<'tcx>>,
 
-    /// Generator drop glue.
-    pub generator_drop: Option<Body<'tcx>>,
+    /// Coroutine drop glue.
+    pub coroutine_drop: Option<Body<'tcx>>,
 
-    /// The layout of a generator. Produced by the state transformation.
-    pub generator_layout: Option<GeneratorLayout<'tcx>>,
+    /// The layout of a coroutine. Produced by the state transformation.
+    pub coroutine_layout: Option<CoroutineLayout<'tcx>>,
 
-    /// If this is a generator then record the type of source expression that caused this generator
+    /// If this is a coroutine then record the type of source expression that caused this coroutine
     /// to be created.
-    pub generator_kind: GeneratorKind,
+    pub coroutine_kind: CoroutineKind,
 }
 
 /// The lowered representation of a single function.
@@ -284,7 +284,7 @@ pub struct Body<'tcx> {
     /// and used for debuginfo. Indexed by a `SourceScope`.
     pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
 
-    pub generator: Option<Box<GeneratorInfo<'tcx>>>,
+    pub coroutine: Option<Box<CoroutineInfo<'tcx>>>,
 
     /// Declarations of locals.
     ///
@@ -365,7 +365,7 @@ impl<'tcx> Body<'tcx> {
         arg_count: usize,
         var_debug_info: Vec<VarDebugInfo<'tcx>>,
         span: Span,
-        generator_kind: Option<GeneratorKind>,
+        coroutine_kind: Option<CoroutineKind>,
         tainted_by_errors: Option<ErrorGuaranteed>,
     ) -> Self {
         // We need `arg_count` locals, and one for the return place.
@@ -382,12 +382,12 @@ impl<'tcx> Body<'tcx> {
             source,
             basic_blocks: BasicBlocks::new(basic_blocks),
             source_scopes,
-            generator: generator_kind.map(|generator_kind| {
-                Box::new(GeneratorInfo {
+            coroutine: coroutine_kind.map(|coroutine_kind| {
+                Box::new(CoroutineInfo {
                     yield_ty: None,
-                    generator_drop: None,
-                    generator_layout: None,
-                    generator_kind,
+                    coroutine_drop: None,
+                    coroutine_layout: None,
+                    coroutine_kind,
                 })
             }),
             local_decls,
@@ -418,7 +418,7 @@ impl<'tcx> Body<'tcx> {
             source: MirSource::item(CRATE_DEF_ID.to_def_id()),
             basic_blocks: BasicBlocks::new(basic_blocks),
             source_scopes: IndexVec::new(),
-            generator: None,
+            coroutine: None,
             local_decls: IndexVec::new(),
             user_type_annotations: IndexVec::new(),
             arg_count: 0,
@@ -548,22 +548,22 @@ impl<'tcx> Body<'tcx> {
 
     #[inline]
     pub fn yield_ty(&self) -> Option<Ty<'tcx>> {
-        self.generator.as_ref().and_then(|generator| generator.yield_ty)
+        self.coroutine.as_ref().and_then(|coroutine| coroutine.yield_ty)
     }
 
     #[inline]
-    pub fn generator_layout(&self) -> Option<&GeneratorLayout<'tcx>> {
-        self.generator.as_ref().and_then(|generator| generator.generator_layout.as_ref())
+    pub fn coroutine_layout(&self) -> Option<&CoroutineLayout<'tcx>> {
+        self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_layout.as_ref())
     }
 
     #[inline]
-    pub fn generator_drop(&self) -> Option<&Body<'tcx>> {
-        self.generator.as_ref().and_then(|generator| generator.generator_drop.as_ref())
+    pub fn coroutine_drop(&self) -> Option<&Body<'tcx>> {
+        self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref())
     }
 
     #[inline]
-    pub fn generator_kind(&self) -> Option<GeneratorKind> {
-        self.generator.as_ref().map(|generator| generator.generator_kind)
+    pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
+        self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 3b3b61e4e21..dee25df53bd 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -130,8 +130,8 @@ fn dump_matched_mir_node<'tcx, F>(
             Some(promoted) => write!(file, "::{promoted:?}`")?,
         }
         writeln!(file, " {disambiguator} {pass_name}")?;
-        if let Some(ref layout) = body.generator_layout() {
-            writeln!(file, "/* generator_layout = {layout:#?} */")?;
+        if let Some(ref layout) = body.coroutine_layout() {
+            writeln!(file, "/* coroutine_layout = {layout:#?} */")?;
         }
         writeln!(file)?;
         extra_data(PassWhere::BeforeCFG, &mut file)?;
@@ -782,7 +782,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             Goto { .. } => write!(fmt, "goto"),
             SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"),
             Return => write!(fmt, "return"),
-            GeneratorDrop => write!(fmt, "generator_drop"),
+            CoroutineDrop => write!(fmt, "coroutine_drop"),
             UnwindResume => write!(fmt, "resume"),
             UnwindTerminate(reason) => {
                 write!(fmt, "abort({})", reason.as_short_str())
@@ -865,7 +865,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         use self::TerminatorKind::*;
         match *self {
-            Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![],
+            Return | UnwindResume | UnwindTerminate(_) | Unreachable | CoroutineDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref targets, .. } => targets
                 .values
@@ -1046,8 +1046,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         struct_fmt.finish()
                     }),
 
-                    AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
-                        let name = format!("{{generator@{:?}}}", tcx.def_span(def_id));
+                    AggregateKind::Coroutine(def_id, _, _) => ty::tls::with(|tcx| {
+                        let name = format!("{{coroutine@{:?}}}", tcx.def_span(def_id));
                         let mut struct_fmt = fmt.debug_struct(&name);
 
                         // FIXME(project-rfc-2229#48): This should be a list of capture names/places
@@ -1301,8 +1301,8 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                     self.push(&format!("+ args: {args:#?}"));
                 }
 
-                AggregateKind::Generator(def_id, args, movability) => {
-                    self.push("generator");
+                AggregateKind::Coroutine(def_id, args, movability) => {
+                    self.push("coroutine");
                     self.push(&format!("+ def_id: {def_id:?}"));
                     self.push(&format!("+ args: {args:#?}"));
                     self.push(&format!("+ movability: {movability:?}"));
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index f407dc4d7ae..0540eb0efd6 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -133,11 +133,11 @@ pub struct UnsafetyCheckResult {
 rustc_index::newtype_index! {
     #[derive(HashStable)]
     #[debug_format = "_{}"]
-    pub struct GeneratorSavedLocal {}
+    pub struct CoroutineSavedLocal {}
 }
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub struct GeneratorSavedTy<'tcx> {
+pub struct CoroutineSavedTy<'tcx> {
     pub ty: Ty<'tcx>,
     /// Source info corresponding to the local in the original MIR body.
     pub source_info: SourceInfo,
@@ -145,18 +145,18 @@ pub struct GeneratorSavedTy<'tcx> {
     pub ignore_for_traits: bool,
 }
 
-/// The layout of generator state.
+/// The layout of coroutine state.
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub struct GeneratorLayout<'tcx> {
-    /// The type of every local stored inside the generator.
-    pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
+pub struct CoroutineLayout<'tcx> {
+    /// The type of every local stored inside the coroutine.
+    pub field_tys: IndexVec<CoroutineSavedLocal, CoroutineSavedTy<'tcx>>,
 
     /// The name for debuginfo.
-    pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>,
+    pub field_names: IndexVec<CoroutineSavedLocal, Option<Symbol>>,
 
     /// Which of the above fields are in each variant. Note that one field may
     /// be stored in multiple variants.
-    pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>,
+    pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>>,
 
     /// The source that led to each variant being created (usually, a yield or
     /// await).
@@ -167,10 +167,10 @@ pub struct GeneratorLayout<'tcx> {
     /// layout.
     #[type_foldable(identity)]
     #[type_visitable(ignore)]
-    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
+    pub storage_conflicts: BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
 }
 
-impl Debug for GeneratorLayout<'_> {
+impl Debug for CoroutineLayout<'_> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         /// Prints an iterator of (key, value) tuples as a map.
         struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
@@ -185,7 +185,7 @@ impl Debug for GeneratorLayout<'_> {
             }
         }
 
-        /// Prints the generator variant name.
+        /// Prints the coroutine variant name.
         struct GenVariantPrinter(VariantIdx);
         impl From<VariantIdx> for GenVariantPrinter {
             fn from(idx: VariantIdx) -> Self {
@@ -194,7 +194,7 @@ impl Debug for GeneratorLayout<'_> {
         }
         impl Debug for GenVariantPrinter {
             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-                let variant_name = ty::GeneratorArgs::variant_name(self.0);
+                let variant_name = ty::CoroutineArgs::variant_name(self.0);
                 if fmt.alternate() {
                     write!(fmt, "{:9}({:?})", variant_name, self.0)
                 } else {
@@ -211,7 +211,7 @@ impl Debug for GeneratorLayout<'_> {
             }
         }
 
-        fmt.debug_struct("GeneratorLayout")
+        fmt.debug_struct("CoroutineLayout")
             .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
             .field(
                 "variant_fields",
@@ -259,7 +259,7 @@ pub struct ConstQualifs {
 ///
 /// The requirements are listed as being between various `RegionVid`. The 0th
 /// region refers to `'static`; subsequent region vids refer to the free
-/// regions that appear in the closure (or generator's) type, in order of
+/// regions that appear in the closure (or coroutine's) type, in order of
 /// appearance. (This numbering is actually defined by the `UniversalRegions`
 /// struct in the NLL region checker. See for example
 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7a645fb5d62..b89c7bc512e 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -15,7 +15,7 @@ use crate::ty::{Region, UserTypeAnnotationIndex};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir};
-use rustc_hir::{self, GeneratorKind};
+use rustc_hir::{self, CoroutineKind};
 use rustc_index::IndexVec;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 
@@ -82,10 +82,10 @@ pub enum MirPhase {
     ///    that Rust itself has them. Where exactly these are is generally subject to change, and so we
     ///    don't document this here. Runtime MIR has most retags explicit (though implicit retags
     ///    can still occur at `Rvalue::{Ref,AddrOf}`).
-    ///  - Generator bodies: In analysis MIR, locals may actually be behind a pointer that user code has
-    ///    access to. This occurs in generator bodies. Such locals do not behave like other locals,
+    ///  - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code has
+    ///    access to. This occurs in coroutine bodies. Such locals do not behave like other locals,
     ///    because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
-    ///    all generator bodies are lowered and so all places that look like locals really are locals.
+    ///    all coroutine bodies are lowered and so all places that look like locals really are locals.
     ///
     /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
     /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
@@ -137,7 +137,7 @@ pub enum RuntimePhase {
     /// In addition to the semantic changes, beginning with this phase, the following variants are
     /// disallowed:
     /// * [`TerminatorKind::Yield`]
-    /// * [`TerminatorKind::GeneratorDrop`]
+    /// * [`TerminatorKind::CoroutineDrop`]
     /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
     /// * [`PlaceElem::OpaqueCast`]
     ///
@@ -292,7 +292,7 @@ pub enum StatementKind<'tcx> {
 
     /// Write the discriminant for a variant to the enum Place.
     ///
-    /// This is permitted for both generators and ADTs. This does not necessarily write to the
+    /// This is permitted for both coroutines and ADTs. This does not necessarily write to the
     /// entire place; instead, it writes to the minimum set of bytes as required by the layout for
     /// the type.
     SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
@@ -626,8 +626,8 @@ pub enum TerminatorKind<'tcx> {
     /// `dest = move _0`. It might additionally do other things, like have side-effects in the
     /// aliasing model.
     ///
-    /// If the body is a generator body, this has slightly different semantics; it instead causes a
-    /// `GeneratorState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
+    /// If the body is a coroutine body, this has slightly different semantics; it instead causes a
+    /// `CoroutineState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
     /// to the return place.
     Return,
 
@@ -709,14 +709,14 @@ pub enum TerminatorKind<'tcx> {
 
     /// Marks a suspend point.
     ///
-    /// Like `Return` terminators in generator bodies, this computes `value` and then a
-    /// `GeneratorState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
+    /// Like `Return` terminators in coroutine bodies, this computes `value` and then a
+    /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
     /// the return place of the function calling this one, and execution continues in the calling
     /// function. When next invoked with the same first argument, execution of this function
     /// continues at the `resume` basic block, with the second argument written to the `resume_arg`
-    /// place. If the generator is dropped before then, the `drop` basic block is invoked.
+    /// place. If the coroutine is dropped before then, the `drop` basic block is invoked.
     ///
-    /// Not permitted in bodies that are not generator bodies, or after generator lowering.
+    /// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.
     ///
     /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?
     Yield {
@@ -726,21 +726,21 @@ pub enum TerminatorKind<'tcx> {
         resume: BasicBlock,
         /// The place to store the resume argument in.
         resume_arg: Place<'tcx>,
-        /// Cleanup to be done if the generator is dropped at this suspend point.
+        /// Cleanup to be done if the coroutine is dropped at this suspend point.
         drop: Option<BasicBlock>,
     },
 
-    /// Indicates the end of dropping a generator.
+    /// Indicates the end of dropping a coroutine.
     ///
-    /// Semantically just a `return` (from the generators drop glue). Only permitted in the same situations
+    /// Semantically just a `return` (from the coroutines drop glue). Only permitted in the same situations
     /// as `yield`.
     ///
-    /// **Needs clarification**: Is that even correct? The generator drop code is always confusing
+    /// **Needs clarification**: Is that even correct? The coroutine drop code is always confusing
     /// to me, because it's not even really in the current body.
     ///
     /// **Needs clarification**: Are there type system constraints on these terminators? Should
     /// there be a "block type" like `cleanup` blocks for them?
-    GeneratorDrop,
+    CoroutineDrop,
 
     /// A block where control flow only ever takes one real path, but borrowck needs to be more
     /// conservative.
@@ -815,7 +815,7 @@ impl TerminatorKind<'_> {
             TerminatorKind::Call { .. } => "Call",
             TerminatorKind::Assert { .. } => "Assert",
             TerminatorKind::Yield { .. } => "Yield",
-            TerminatorKind::GeneratorDrop => "GeneratorDrop",
+            TerminatorKind::CoroutineDrop => "CoroutineDrop",
             TerminatorKind::FalseEdge { .. } => "FalseEdge",
             TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
             TerminatorKind::InlineAsm { .. } => "InlineAsm",
@@ -883,8 +883,8 @@ pub enum AssertKind<O> {
     OverflowNeg(O),
     DivisionByZero(O),
     RemainderByZero(O),
-    ResumedAfterReturn(GeneratorKind),
-    ResumedAfterPanic(GeneratorKind),
+    ResumedAfterReturn(CoroutineKind),
+    ResumedAfterPanic(CoroutineKind),
     MisalignedPointerDereference { required: O, found: O },
 }
 
@@ -961,8 +961,8 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 ///    was unsized and so had metadata associated with it, then the metadata is retained if the
 ///    field is unsized and thrown out if it is sized.
 ///
-///    These projections are only legal for tuples, ADTs, closures, and generators. If the ADT or
-///    generator has more than one variant, the parent place's variant index must be set, indicating
+///    These projections are only legal for tuples, ADTs, closures, and coroutines. If the ADT or
+///    coroutine has more than one variant, the parent place's variant index must be set, indicating
 ///    which variant is being used. If it has just one variant, the variant index may or may not be
 ///    included - the single possible variant is inferred if it is not included.
 ///  - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
@@ -1068,7 +1068,7 @@ pub enum ProjectionElem<V, T> {
         from_end: bool,
     },
 
-    /// "Downcast" to a variant of an enum or a generator.
+    /// "Downcast" to a variant of an enum or a coroutine.
     ///
     /// The included Symbol is the name of the variant, used for printing MIR.
     Downcast(Option<Symbol>, VariantIdx),
@@ -1278,8 +1278,8 @@ pub enum Rvalue<'tcx> {
     /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
     /// has a destructor.
     ///
-    /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
-    /// generator lowering, `Generator` aggregate kinds are disallowed too.
+    /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
+    /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
     Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>),
 
     /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
@@ -1344,7 +1344,7 @@ pub enum AggregateKind<'tcx> {
     Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
 
     Closure(DefId, GenericArgsRef<'tcx>),
-    Generator(DefId, GenericArgsRef<'tcx>, hir::Movability),
+    Coroutine(DefId, GenericArgsRef<'tcx>, hir::Movability),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 44ae75e2de7..931ee7fd05e 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -11,7 +11,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx};
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct PlaceTy<'tcx> {
     pub ty: Ty<'tcx>,
-    /// Downcast to a particular variant of an enum or a generator, if included.
+    /// Downcast to a particular variant of an enum or a coroutine, if included.
     pub variant_index: Option<VariantIdx>,
 }
 
@@ -205,8 +205,8 @@ impl<'tcx> Rvalue<'tcx> {
                 }
                 AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
                 AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
-                AggregateKind::Generator(did, args, movability) => {
-                    Ty::new_generator(tcx, did, args, movability)
+                AggregateKind::Coroutine(did, args, movability) => {
+                    Ty::new_coroutine(tcx, did, args, movability)
                 }
             },
             Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 02aab4a892d..e3d346c0698 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -139,10 +139,10 @@ impl<O> AssertKind<O> {
             Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
             DivisionByZero(_) => "attempt to divide by zero",
             RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero",
-            ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion",
-            ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
-            ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
-            ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
+            ResumedAfterReturn(CoroutineKind::Coroutine) => "coroutine resumed after completion",
+            ResumedAfterReturn(CoroutineKind::Async(_)) => "`async fn` resumed after completion",
+            ResumedAfterPanic(CoroutineKind::Coroutine) => "coroutine resumed after panicking",
+            ResumedAfterPanic(CoroutineKind::Async(_)) => "`async fn` resumed after panicking",
             BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
                 bug!("Unexpected AssertKind")
             }
@@ -228,10 +228,14 @@ impl<O> AssertKind<O> {
             OverflowNeg(_) => middle_assert_overflow_neg,
             DivisionByZero(_) => middle_assert_divide_by_zero,
             RemainderByZero(_) => middle_assert_remainder_by_zero,
-            ResumedAfterReturn(GeneratorKind::Async(_)) => middle_assert_async_resume_after_return,
-            ResumedAfterReturn(GeneratorKind::Gen) => middle_assert_generator_resume_after_return,
-            ResumedAfterPanic(GeneratorKind::Async(_)) => middle_assert_async_resume_after_panic,
-            ResumedAfterPanic(GeneratorKind::Gen) => middle_assert_generator_resume_after_panic,
+            ResumedAfterReturn(CoroutineKind::Async(_)) => middle_assert_async_resume_after_return,
+            ResumedAfterReturn(CoroutineKind::Coroutine) => {
+                middle_assert_coroutine_resume_after_return
+            }
+            ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
+            ResumedAfterPanic(CoroutineKind::Coroutine) => {
+                middle_assert_coroutine_resume_after_panic
+            }
 
             MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
         }
@@ -331,7 +335,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             UnwindResume
             | UnwindTerminate(_)
-            | GeneratorDrop
+            | CoroutineDrop
             | Return
             | Unreachable
             | Call { target: None, unwind: _, .. }
@@ -373,7 +377,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             UnwindResume
             | UnwindTerminate(_)
-            | GeneratorDrop
+            | CoroutineDrop
             | Return
             | Unreachable
             | Call { target: None, unwind: _, .. }
@@ -392,7 +396,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
@@ -411,7 +415,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
@@ -493,7 +497,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
         use TerminatorKind::*;
         match *self {
-            Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => {
+            Return | UnwindResume | UnwindTerminate(_) | CoroutineDrop | Unreachable => {
                 TerminatorEdges::None
             }
 
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 8d427fdb6f5..d5c81b6cd79 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -19,8 +19,8 @@ TrivialTypeTraversalImpls! {
     hir::Movability,
     BasicBlock,
     SwitchTargets,
-    GeneratorKind,
-    GeneratorSavedLocal,
+    CoroutineKind,
+    CoroutineSavedLocal,
 }
 
 TrivialTypeTraversalImpls! {
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 95c1848bc9b..0f0ca3a1420 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -473,7 +473,7 @@ macro_rules! make_mir_visitor {
                     TerminatorKind::Goto { .. } |
                     TerminatorKind::UnwindResume |
                     TerminatorKind::UnwindTerminate(_) |
-                    TerminatorKind::GeneratorDrop |
+                    TerminatorKind::CoroutineDrop |
                     TerminatorKind::Unreachable |
                     TerminatorKind::FalseEdge { .. } |
                     TerminatorKind::FalseUnwind { .. } => {}
@@ -735,12 +735,12 @@ macro_rules! make_mir_visitor {
                             ) => {
                                 self.visit_args(closure_args, location);
                             }
-                            AggregateKind::Generator(
+                            AggregateKind::Coroutine(
                                 _,
-                                generator_args,
+                                coroutine_args,
                                 _movability,
                             ) => {
-                                self.visit_args(generator_args, location);
+                                self.visit_args(coroutine_args, location);
                             }
                         }
 
@@ -992,7 +992,7 @@ macro_rules! extra_body_methods {
 macro_rules! super_body {
     ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
         let span = $body.span;
-        if let Some(gen) = &$($mutability)? $body.generator {
+        if let Some(gen) = &$($mutability)? $body.coroutine {
             if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
                 $self.visit_ty(
                     yield_ty,
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 8ba3764bcc3..e20e9d9312c 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -210,7 +210,7 @@ trivial! {
     Option<rustc_attr::Stability>,
     Option<rustc_data_structures::svh::Svh>,
     Option<rustc_hir::def::DefKind>,
-    Option<rustc_hir::GeneratorKind>,
+    Option<rustc_hir::CoroutineKind>,
     Option<rustc_hir::HirId>,
     Option<rustc_middle::middle::stability::DeprecationEntry>,
     Option<rustc_middle::ty::Destructor>,
@@ -239,7 +239,7 @@ trivial! {
     rustc_hir::def::DefKind,
     rustc_hir::Defaultness,
     rustc_hir::definitions::DefKey,
-    rustc_hir::GeneratorKind,
+    rustc_hir::CoroutineKind,
     rustc_hir::HirId,
     rustc_hir::IsAsync,
     rustc_hir::ItemLocalId,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index afe94d10752..cd5206a837f 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -541,28 +541,28 @@ rustc_queries! {
         }
     }
 
-    /// Returns names of captured upvars for closures and generators.
+    /// Returns names of captured upvars for closures and coroutines.
     ///
     /// Here are some examples:
     ///  - `name__field1__field2` when the upvar is captured by value.
     ///  - `_ref__name__field` when the upvar is captured by reference.
     ///
-    /// For generators this only contains upvars that are shared by all states.
+    /// For coroutines this only contains upvars that are shared by all states.
     query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec<abi::FieldIdx, Symbol> {
         arena_cache
         desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
 
-    query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
+    query mir_coroutine_witnesses(key: DefId) -> &'tcx Option<mir::CoroutineLayout<'tcx>> {
         arena_cache
-        desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
+        desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
     }
 
-    query check_generator_obligations(key: LocalDefId) {
-        desc { |tcx| "verify auto trait bounds for generator interior type `{}`", tcx.def_path_str(key) }
+    query check_coroutine_obligations(key: LocalDefId) {
+        desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) }
     }
 
     /// MIR after our optimization passes have run. This is MIR that is ready
@@ -743,9 +743,9 @@ rustc_queries! {
         desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
-    query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
-        desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
+    /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine.
+    query coroutine_kind(def_id: DefId) -> Option<hir::CoroutineKind> {
+        desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
 
@@ -1882,12 +1882,6 @@ rustc_queries! {
         desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) }
     }
 
-    /// All items participating in code generation together with items inlined into them.
-    query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet {
-        eval_always
-        desc { "collecting codegened and inlined items" }
-    }
-
     query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> {
         desc { "getting codegen unit `{sym}`" }
     }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 67804998a32..20e3349073d 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -382,9 +382,9 @@ pub enum ExprKind<'tcx> {
     VarRef {
         id: LocalVarId,
     },
-    /// Used to represent upvars mentioned in a closure/generator
+    /// Used to represent upvars mentioned in a closure/coroutine
     UpvarRef {
-        /// DefId of the closure/generator
+        /// DefId of the closure/coroutine
         closure_def_id: DefId,
 
         /// HirId of the root variable
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 99b750c9afc..9e2ff3820af 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -301,8 +301,8 @@ pub enum ObligationCauseCode<'tcx> {
     InlineAsmSized,
     /// Captured closure type must be `Sized`.
     SizedClosureCapture(LocalDefId),
-    /// Types live across generator yields must be `Sized`.
-    SizedGeneratorInterior(LocalDefId),
+    /// Types live across coroutine yields must be `Sized`.
+    SizedCoroutineInterior(LocalDefId),
     /// `[expr; N]` requires `type_of(expr): Copy`.
     RepeatElementCopy {
         /// If element is a `const fn` we display a help message suggesting to move the
@@ -541,6 +541,7 @@ pub struct MatchExpressionArmCause<'tcx> {
     pub prior_arm_ty: Ty<'tcx>,
     pub prior_arm_span: Span,
     pub scrut_span: Span,
+    pub scrut_hir_id: hir::HirId,
     pub source: hir::MatchSource,
     pub prior_arms: Vec<Span>,
     pub opt_suggest_box_span: Option<Span>,
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 90bc5dd8f69..bc6856bc900 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -136,11 +136,11 @@ pub enum SelectionCandidate<'tcx> {
         is_const: bool,
     },
 
-    /// Implementation of a `Generator` trait by one of the anonymous types
-    /// generated for a generator.
-    GeneratorCandidate,
+    /// Implementation of a `Coroutine` trait by one of the anonymous types
+    /// generated for a coroutine.
+    CoroutineCandidate,
 
-    /// Implementation of a `Future` trait by one of the generator types
+    /// Implementation of a `Future` trait by one of the coroutine types
     /// generated for an async construct.
     FutureCandidate,
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index cad3aac23d8..561699d3170 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -65,7 +65,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
-use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
 
@@ -761,9 +761,9 @@ impl<'tcx> TyCtxt<'tcx> {
         self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
     }
 
-    /// Returns `true` if the node pointed to by `def_id` is a generator for an async construct.
-    pub fn generator_is_async(self, def_id: DefId) -> bool {
-        matches!(self.generator_kind(def_id), Some(hir::GeneratorKind::Async(_)))
+    /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct.
+    pub fn coroutine_is_async(self, def_id: DefId) -> bool {
+        matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Async(_)))
     }
 
     pub fn stability(self) -> &'tcx stability::Index {
@@ -951,7 +951,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
         let definitions = &self.untracked.definitions;
-        std::iter::from_generator(|| {
+        std::iter::from_coroutine(|| {
             let mut i = 0;
 
             // Recompute the number of definitions each time, because our caller may be creating
@@ -1382,8 +1382,8 @@ impl<'tcx> TyCtxt<'tcx> {
                     FnDef,
                     FnPtr,
                     Placeholder,
-                    Generator,
-                    GeneratorWitness,
+                    Coroutine,
+                    CoroutineWitness,
                     Dynamic,
                     Closure,
                     Tuple,
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 49014c60a6d..7a782b2c249 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -17,7 +17,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{PredicateOrigin, WherePredicate};
 use rustc_span::{BytePos, Span};
-use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::TyKind::*;
 
 impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
@@ -482,8 +482,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
             FnDef(..)
             | Closure(..)
             | Infer(..)
-            | Generator(..)
-            | GeneratorWitness(..)
+            | Coroutine(..)
+            | CoroutineWitness(..)
             | Bound(_, _)
             | Placeholder(_)
             | Error(_) => {
@@ -567,8 +567,8 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
             // FIXME(compiler-errors): We could replace these with infer, I guess.
             Closure(..)
             | Infer(..)
-            | Generator(..)
-            | GeneratorWitness(..)
+            | Coroutine(..)
+            | CoroutineWitness(..)
             | Bound(_, _)
             | Placeholder(_)
             | Error(_) => {
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 0fe1284eed9..8b4375f0270 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -241,8 +241,8 @@ impl<'tcx> Ty<'tcx> {
             }
             ty::Dynamic(..) => "trait object".into(),
             ty::Closure(..) => "closure".into(),
-            ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
-            ty::GeneratorWitness(..) => "generator witness".into(),
+            ty::Coroutine(def_id, ..) => tcx.coroutine_kind(def_id).unwrap().descr().into(),
+            ty::CoroutineWitness(..) => "coroutine witness".into(),
             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
             ty::Infer(ty::IntVar(_)) => "integer".into(),
             ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
@@ -299,8 +299,8 @@ impl<'tcx> Ty<'tcx> {
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(..) => "trait object".into(),
             ty::Closure(..) => "closure".into(),
-            ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
-            ty::GeneratorWitness(..) => "generator witness".into(),
+            ty::Coroutine(def_id, ..) => tcx.coroutine_kind(def_id).unwrap().descr().into(),
+            ty::CoroutineWitness(..) => "coroutine witness".into(),
             ty::Tuple(..) => "tuple".into(),
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 16935d5b380..75ea53195a3 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -28,8 +28,8 @@ pub enum SimplifiedType {
     MarkerTraitObject,
     Trait(DefId),
     Closure(DefId),
-    Generator(DefId),
-    GeneratorWitness(DefId),
+    Coroutine(DefId),
+    CoroutineWitness(DefId),
     Function(usize),
     Placeholder,
 }
@@ -128,8 +128,8 @@ pub fn simplify_type<'tcx>(
         },
         ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)),
         ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)),
-        ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)),
-        ty::GeneratorWitness(def_id, _) => Some(SimplifiedType::GeneratorWitness(def_id)),
+        ty::Coroutine(def_id, _, _) => Some(SimplifiedType::Coroutine(def_id)),
+        ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)),
         ty::Never => Some(SimplifiedType::Never),
         ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
         ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())),
@@ -164,8 +164,8 @@ impl SimplifiedType {
             | SimplifiedType::Foreign(d)
             | SimplifiedType::Trait(d)
             | SimplifiedType::Closure(d)
-            | SimplifiedType::Generator(d)
-            | SimplifiedType::GeneratorWitness(d) => Some(d),
+            | SimplifiedType::Coroutine(d)
+            | SimplifiedType::CoroutineWitness(d) => Some(d),
             _ => None,
         }
     }
@@ -234,8 +234,8 @@ impl DeepRejectCtxt {
             | ty::Foreign(..) => {}
             ty::FnDef(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Placeholder(..)
             | ty::Bound(..)
             | ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"),
@@ -310,7 +310,7 @@ impl DeepRejectCtxt {
             },
 
             // Impls cannot contain these types as these cannot be named directly.
-            ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
+            ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) => false,
 
             // Placeholder types don't unify with anything on their own
             ty::Placeholder(..) | ty::Bound(..) => false,
@@ -337,7 +337,7 @@ impl DeepRejectCtxt {
 
             ty::Error(_) => true,
 
-            ty::GeneratorWitness(..) => {
+            ty::CoroutineWitness(..) => {
                 bug!("unexpected obligation type: {:?}", obligation_ty)
             }
         }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 7ed31fbbfd8..d75315b7ac9 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -111,8 +111,8 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            ty::Generator(_, args, _) => {
-                let args = args.as_generator();
+            ty::Coroutine(_, args, _) => {
+                let args = args.as_coroutine();
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 self.add_args(args.parent_args());
@@ -127,7 +127,7 @@ impl FlagComputation {
                 self.add_ty(args.tupled_upvars_ty());
             }
 
-            ty::GeneratorWitness(_, args) => {
+            ty::CoroutineWitness(_, args) => {
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 self.add_args(args);
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index a861af47859..41a1bf04e5f 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -2,7 +2,7 @@
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-use crate::ty::sty::{ClosureArgs, GeneratorArgs, InlineConstArgs};
+use crate::ty::sty::{ClosureArgs, CoroutineArgs, InlineConstArgs};
 use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
@@ -266,12 +266,12 @@ impl<'tcx> GenericArgs<'tcx> {
         ClosureArgs { args: self }
     }
 
-    /// Interpret these generic args as the args of a generator type.
-    /// Generator args have a particular structure controlled by the
-    /// compiler that encodes information like the signature and generator kind;
-    /// see `ty::GeneratorArgs` struct for more comments.
-    pub fn as_generator(&'tcx self) -> GeneratorArgs<'tcx> {
-        GeneratorArgs { args: self }
+    /// Interpret these generic args as the args of a coroutine type.
+    /// Coroutine args have a particular structure controlled by the
+    /// compiler that encodes information like the signature and coroutine kind;
+    /// see `ty::CoroutineArgs` struct for more comments.
+    pub fn as_coroutine(&'tcx self) -> CoroutineArgs<'tcx> {
+        CoroutineArgs { args: self }
     }
 
     /// Interpret these generic args as the args of an inline const.
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 4dac6891b30..68ac54e899a 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -47,7 +47,7 @@ use crate::query::Providers;
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
 
-use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::TyKind::*;
 
 pub mod inhabited_predicate;
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 0b308d5dec1..a7d6e97c941 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -36,7 +36,7 @@ pub enum InstanceDef<'tcx> {
     /// This includes:
     /// - `fn` items
     /// - closures
-    /// - generators
+    /// - coroutines
     Item(DefId),
 
     /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
@@ -653,15 +653,15 @@ fn polymorphize<'tcx>(
     let unused = tcx.unused_generic_params(instance);
     debug!("polymorphize: unused={:?}", unused);
 
-    // If this is a closure or generator then we need to handle the case where another closure
+    // If this is a closure or coroutine then we need to handle the case where another closure
     // from the function is captured as an upvar and hasn't been polymorphized. In this case,
     // the unpolymorphized upvar closure would result in a polymorphized closure producing
     // multiple mono items (and eventually symbol clashes).
     let def_id = instance.def_id();
     let upvars_ty = if tcx.is_closure(def_id) {
         Some(args.as_closure().tupled_upvars_ty())
-    } else if tcx.type_of(def_id).skip_binder().is_generator() {
-        Some(args.as_generator().tupled_upvars_ty())
+    } else if tcx.type_of(def_id).skip_binder().is_coroutine() {
+        Some(args.as_coroutine().tupled_upvars_ty())
     } else {
         None
     };
@@ -689,13 +689,13 @@ fn polymorphize<'tcx>(
                         Ty::new_closure(self.tcx, def_id, polymorphized_args)
                     }
                 }
-                ty::Generator(def_id, args, movability) => {
+                ty::Coroutine(def_id, args, movability) => {
                     let polymorphized_args =
                         polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
                     if args == polymorphized_args {
                         ty
                     } else {
-                        Ty::new_generator(self.tcx, def_id, polymorphized_args, movability)
+                        Ty::new_coroutine(self.tcx, def_id, polymorphized_args, movability)
                     }
                 }
                 _ => ty.super_fold_with(self),
@@ -715,7 +715,7 @@ fn polymorphize<'tcx>(
                 upvars_ty == Some(args[param.index as usize].expect_ty()) => {
                     // ..then double-check that polymorphization marked it used..
                     debug_assert!(!is_unused);
-                    // ..and polymorphize any closures/generators captured as upvars.
+                    // ..and polymorphize any closures/coroutines captured as upvars.
                     let upvars_ty = upvars_ty.unwrap();
                     let polymorphized_upvars_ty = upvars_ty.fold_with(
                         &mut PolymorphizationFolder { tcx });
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 5ef7ee52636..4223e503f5e 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -809,7 +809,7 @@ where
                 | ty::FnPtr(_)
                 | ty::Never
                 | ty::FnDef(..)
-                | ty::GeneratorWitness(..)
+                | ty::CoroutineWitness(..)
                 | ty::Foreign(..)
                 | ty::Dynamic(_, _, ty::Dyn) => {
                     bug!("TyAndLayout::field({:?}): not applicable", this)
@@ -898,16 +898,16 @@ where
                 ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element),
                 ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
 
-                // Tuples, generators and closures.
+                // Tuples, coroutines and closures.
                 ty::Closure(_, ref args) => field_ty_or_layout(
                     TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this },
                     cx,
                     i,
                 ),
 
-                ty::Generator(def_id, ref args, _) => match this.variants {
+                ty::Coroutine(def_id, ref args, _) => match this.variants {
                     Variants::Single { index } => TyMaybeWithLayout::Ty(
-                        args.as_generator()
+                        args.as_coroutine()
                             .state_tys(def_id, tcx)
                             .nth(index.as_usize())
                             .unwrap()
@@ -918,7 +918,7 @@ where
                         if i == tag_field {
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
-                        TyMaybeWithLayout::Ty(args.as_generator().prefix_tys()[i])
+                        TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
                     }
                 },
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e6cd3dd4d82..9b0ceb23e3e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -20,7 +20,7 @@ pub use self::Variance::*;
 use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
-use crate::mir::{Body, GeneratorLayout};
+use crate::mir::{Body, CoroutineLayout};
 use crate::query::Providers;
 use crate::traits::{self, Reveal};
 use crate::ty;
@@ -98,8 +98,8 @@ pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
     BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid,
-    EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef,
-    FnSig, FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs,
+    CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate,
+    ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs,
     InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
     PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid,
     TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
@@ -2421,10 +2421,10 @@ impl<'tcx> TyCtxt<'tcx> {
         self.def_kind(trait_def_id) == DefKind::TraitAlias
     }
 
-    /// Returns layout of a generator. Layout might be unavailable if the
-    /// generator is tainted by errors.
-    pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
-        self.optimized_mir(def_id).generator_layout()
+    /// Returns layout of a coroutine. Layout might be unavailable if the
+    /// coroutine is tainted by errors.
+    pub fn coroutine_layout(self, def_id: DefId) -> Option<&'tcx CoroutineLayout<'tcx>> {
+        self.optimized_mir(def_id).coroutine_layout()
     }
 
     /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 6491936c219..8d895732dff 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -152,14 +152,14 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                 Ty::new_closure(self.tcx, def_id, args)
             }
 
-            ty::Generator(def_id, args, movability) => {
+            ty::Coroutine(def_id, args, movability) => {
                 let args = self.fold_closure_args(def_id, args);
-                Ty::new_generator(self.tcx, def_id, args, movability)
+                Ty::new_coroutine(self.tcx, def_id, args, movability)
             }
 
-            ty::GeneratorWitness(def_id, args) => {
+            ty::CoroutineWitness(def_id, args) => {
                 let args = self.fold_closure_args(def_id, args);
-                Ty::new_generator_witness(self.tcx, def_id, args)
+                Ty::new_coroutine_witness(self.tcx, def_id, args)
             }
 
             ty::Param(param) => {
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 9aa673e4418..9afa50cf584 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -82,7 +82,7 @@ trivially_parameterized_over_tcx! {
     rustc_attr::Stability,
     rustc_hir::Constness,
     rustc_hir::Defaultness,
-    rustc_hir::GeneratorKind,
+    rustc_hir::CoroutineKind,
     rustc_hir::IsAsync,
     rustc_hir::LangItem,
     rustc_hir::def::DefKind,
@@ -123,7 +123,7 @@ macro_rules! parameterized_over_tcx {
 parameterized_over_tcx! {
     crate::middle::exported_symbols::ExportedSymbol,
     crate::mir::Body,
-    crate::mir::GeneratorLayout,
+    crate::mir::CoroutineLayout,
     ty::Ty,
     ty::FnSig,
     ty::GenericPredicates,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 107b44285ac..164e4232e4c 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -261,8 +261,8 @@ fn characteristic_def_id_of_type_cached<'a>(
 
         ty::FnDef(def_id, _)
         | ty::Closure(def_id, _)
-        | ty::Generator(def_id, _, _)
-        | ty::GeneratorWitness(def_id, _)
+        | ty::Coroutine(def_id, _, _)
+        | ty::CoroutineWitness(def_id, _)
         | ty::Foreign(def_id) => Some(def_id),
 
         ty::Bool
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 117aa69596c..38b3096f851 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -784,11 +784,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 }
             }
             ty::Str => p!("str"),
-            ty::Generator(did, args, movability) => {
+            ty::Coroutine(did, args, movability) => {
                 p!(write("{{"));
-                let generator_kind = self.tcx().generator_kind(did).unwrap();
+                let coroutine_kind = self.tcx().coroutine_kind(did).unwrap();
                 let should_print_movability =
-                    self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen;
+                    self.should_print_verbose() || coroutine_kind == hir::CoroutineKind::Coroutine;
 
                 if should_print_movability {
                     match movability {
@@ -798,7 +798,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 }
 
                 if !self.should_print_verbose() {
-                    p!(write("{}", generator_kind));
+                    p!(write("{}", coroutine_kind));
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         let span = self.tcx().def_span(did);
@@ -814,24 +814,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 } else {
                     p!(print_def_path(did, args));
                     p!(" upvar_tys=(");
-                    if !args.as_generator().is_valid() {
+                    if !args.as_coroutine().is_valid() {
                         p!("unavailable");
                     } else {
-                        self = self.comma_sep(args.as_generator().upvar_tys().iter())?;
+                        self = self.comma_sep(args.as_coroutine().upvar_tys().iter())?;
                     }
                     p!(")");
 
-                    if args.as_generator().is_valid() {
-                        p!(" ", print(args.as_generator().witness()));
+                    if args.as_coroutine().is_valid() {
+                        p!(" ", print(args.as_coroutine().witness()));
                     }
                 }
 
                 p!("}}")
             }
-            ty::GeneratorWitness(did, args) => {
+            ty::CoroutineWitness(did, args) => {
                 p!(write("{{"));
                 if !self.tcx().sess.verbose() {
-                    p!("generator witness");
+                    p!("coroutine witness");
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         let span = self.tcx().def_span(did);
@@ -1048,16 +1048,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     }
 
                     for (assoc_item_def_id, term) in assoc_items {
-                        // Skip printing `<{generator@} as Generator<_>>::Return` from async blocks,
-                        // unless we can find out what generator return type it comes from.
+                        // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
+                        // unless we can find out what coroutine return type it comes from.
                         let term = if let Some(ty) = term.skip_binder().ty()
                             && let ty::Alias(ty::Projection, proj) = ty.kind()
                             && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
                             && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
                             && assoc.name == rustc_span::sym::Return
                         {
-                            if let ty::Generator(_, args, _) = args.type_at(0).kind() {
-                                let return_ty = args.as_generator().return_ty();
+                            if let ty::Coroutine(_, args, _) = args.type_at(0).kind() {
+                                let return_ty = args.as_coroutine().return_ty();
                                 if !return_ty.is_ty_var() {
                                     return_ty.into()
                                 } else {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index fdfdd6cc8d6..27e9be37fbf 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -352,19 +352,19 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
 }
 
 #[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
-struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
+struct CoroutineWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
-impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
+impl<'tcx> Relate<'tcx> for CoroutineWitness<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: GeneratorWitness<'tcx>,
-        b: GeneratorWitness<'tcx>,
-    ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
+        a: CoroutineWitness<'tcx>,
+        b: CoroutineWitness<'tcx>,
+    ) -> RelateResult<'tcx, CoroutineWitness<'tcx>> {
         assert_eq!(a.0.len(), b.0.len());
         let tcx = relation.tcx();
         let types =
             tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
-        Ok(GeneratorWitness(types))
+        Ok(CoroutineWitness(types))
     }
 }
 
@@ -457,24 +457,24 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr))
         }
 
-        (&ty::Generator(a_id, a_args, movability), &ty::Generator(b_id, b_args, _))
+        (&ty::Coroutine(a_id, a_args, movability), &ty::Coroutine(b_id, b_args, _))
             if a_id == b_id =>
         {
-            // All Generator types with the same id represent
-            // the (anonymous) type of the same generator expression. So
+            // All Coroutine types with the same id represent
+            // the (anonymous) type of the same coroutine expression. So
             // all of their regions should be equated.
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_generator(tcx, a_id, args, movability))
+            Ok(Ty::new_coroutine(tcx, a_id, args, movability))
         }
 
-        (&ty::GeneratorWitness(a_id, a_args), &ty::GeneratorWitness(b_id, b_args))
+        (&ty::CoroutineWitness(a_id, a_args), &ty::CoroutineWitness(b_id, b_args))
             if a_id == b_id =>
         {
-            // All GeneratorWitness types with the same id represent
-            // the (anonymous) type of the same generator expression. So
+            // All CoroutineWitness types with the same id represent
+            // the (anonymous) type of the same coroutine expression. So
             // all of their regions should be equated.
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_generator_witness(tcx, a_id, args))
+            Ok(Ty::new_coroutine_witness(tcx, a_id, args))
         }
 
         (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => {
@@ -710,14 +710,14 @@ impl<'tcx> Relate<'tcx> for ty::ClosureArgs<'tcx> {
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::GeneratorArgs<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::CoroutineArgs<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::GeneratorArgs<'tcx>,
-        b: ty::GeneratorArgs<'tcx>,
-    ) -> RelateResult<'tcx, ty::GeneratorArgs<'tcx>> {
+        a: ty::CoroutineArgs<'tcx>,
+        b: ty::CoroutineArgs<'tcx>,
+    ) -> RelateResult<'tcx, ty::CoroutineArgs<'tcx>> {
         let args = relate_args_invariantly(relation, a.args, b.args)?;
-        Ok(ty::GeneratorArgs { args })
+        Ok(ty::CoroutineArgs { args })
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 2adbe9e0309..012bb749412 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -654,11 +654,11 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
             ty::Ref(r, ty, mutbl) => {
                 ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
             }
-            ty::Generator(did, args, movability) => {
-                ty::Generator(did, args.try_fold_with(folder)?, movability)
+            ty::Coroutine(did, args, movability) => {
+                ty::Coroutine(did, args.try_fold_with(folder)?, movability)
             }
-            ty::GeneratorWitness(did, args) => {
-                ty::GeneratorWitness(did, args.try_fold_with(folder)?)
+            ty::CoroutineWitness(did, args) => {
+                ty::CoroutineWitness(did, args.try_fold_with(folder)?)
             }
             ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?),
             ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
@@ -706,8 +706,8 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
                 r.visit_with(visitor)?;
                 ty.visit_with(visitor)
             }
-            ty::Generator(_did, ref args, _) => args.visit_with(visitor),
-            ty::GeneratorWitness(_did, ref args) => args.visit_with(visitor),
+            ty::Coroutine(_did, ref args, _) => args.visit_with(visitor),
+            ty::CoroutineWitness(_did, ref args) => args.visit_with(visitor),
             ty::Closure(_did, ref args) => args.visit_with(visitor),
             ty::Alias(_, ref data) => data.visit_with(visitor),
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index fc207a2c350..46aa5d950cb 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -33,13 +33,13 @@ use std::marker::PhantomData;
 use std::ops::{ControlFlow, Deref, Range};
 use ty::util::IntTypeExt;
 
-use rustc_type_ir::sty::TyKind::*;
 use rustc_type_ir::CollectAndApply;
 use rustc_type_ir::ConstKind as IrConstKind;
 use rustc_type_ir::DebugWithInfcx;
 use rustc_type_ir::DynKind;
 use rustc_type_ir::RegionKind as IrRegionKind;
 use rustc_type_ir::TyKind as IrTyKind;
+use rustc_type_ir::TyKind::*;
 
 use super::GenericParamDefKind;
 
@@ -215,20 +215,20 @@ impl<'tcx> Article for TyKind<'tcx> {
 /// closure C (which would then require fixed point iteration to
 /// handle). Plus it fixes an ICE. :P
 ///
-/// ## Generators
+/// ## Coroutines
 ///
-/// Generators are handled similarly in `GeneratorArgs`. The set of
+/// Coroutines are handled similarly in `CoroutineArgs`. The set of
 /// type parameters is similar, but `CK` and `CS` are replaced by the
 /// following type parameters:
 ///
-/// * `GS`: The generator's "resume type", which is the type of the
+/// * `GS`: The coroutine's "resume type", which is the type of the
 ///   argument passed to `resume`, and the type of `yield` expressions
-///   inside the generator.
+///   inside the coroutine.
 /// * `GY`: The "yield type", which is the type of values passed to
-///   `yield` inside the generator.
+///   `yield` inside the coroutine.
 /// * `GR`: The "return type", which is the type of value returned upon
-///   completion of the generator.
-/// * `GW`: The "generator witness".
+///   completion of the coroutine.
+/// * `GW`: The "coroutine witness".
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct ClosureArgs<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
@@ -352,11 +352,11 @@ impl<'tcx> ClosureArgs<'tcx> {
 
 /// Similar to `ClosureArgs`; see the above documentation for more.
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
-pub struct GeneratorArgs<'tcx> {
+pub struct CoroutineArgs<'tcx> {
     pub args: GenericArgsRef<'tcx>,
 }
 
-pub struct GeneratorArgsParts<'tcx, T> {
+pub struct CoroutineArgsParts<'tcx, T> {
     pub parent_args: &'tcx [GenericArg<'tcx>],
     pub resume_ty: T,
     pub yield_ty: T,
@@ -365,14 +365,14 @@ pub struct GeneratorArgsParts<'tcx, T> {
     pub tupled_upvars_ty: T,
 }
 
-impl<'tcx> GeneratorArgs<'tcx> {
-    /// Construct `GeneratorArgs` from `GeneratorArgsParts`, containing `Args`
-    /// for the generator parent, alongside additional generator-specific components.
+impl<'tcx> CoroutineArgs<'tcx> {
+    /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
+    /// for the coroutine parent, alongside additional coroutine-specific components.
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        parts: GeneratorArgsParts<'tcx, Ty<'tcx>>,
-    ) -> GeneratorArgs<'tcx> {
-        GeneratorArgs {
+        parts: CoroutineArgsParts<'tcx, Ty<'tcx>>,
+    ) -> CoroutineArgs<'tcx> {
+        CoroutineArgs {
             args: tcx.mk_args_from_iter(
                 parts.parent_args.iter().copied().chain(
                     [
@@ -389,12 +389,12 @@ impl<'tcx> GeneratorArgs<'tcx> {
         }
     }
 
-    /// Divides the generator args into their respective components.
-    /// The ordering assumed here must match that used by `GeneratorArgs::new` above.
-    fn split(self) -> GeneratorArgsParts<'tcx, GenericArg<'tcx>> {
+    /// Divides the coroutine args into their respective components.
+    /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
+    fn split(self) -> CoroutineArgsParts<'tcx, GenericArg<'tcx>> {
         match self.args[..] {
             [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
-                GeneratorArgsParts {
+                CoroutineArgsParts {
                     parent_args,
                     resume_ty,
                     yield_ty,
@@ -403,34 +403,34 @@ impl<'tcx> GeneratorArgs<'tcx> {
                     tupled_upvars_ty,
                 }
             }
-            _ => bug!("generator args missing synthetics"),
+            _ => bug!("coroutine args missing synthetics"),
         }
     }
 
     /// Returns `true` only if enough of the synthetic types are known to
-    /// allow using all of the methods on `GeneratorArgs` without panicking.
+    /// allow using all of the methods on `CoroutineArgs` without panicking.
     ///
-    /// Used primarily by `ty::print::pretty` to be able to handle generator
+    /// Used primarily by `ty::print::pretty` to be able to handle coroutine
     /// types that haven't had their synthetic types substituted in.
     pub fn is_valid(self) -> bool {
         self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_))
     }
 
-    /// Returns the substitutions of the generator's parent.
+    /// Returns the substitutions of the coroutine's parent.
     pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
         self.split().parent_args
     }
 
-    /// This describes the types that can be contained in a generator.
+    /// This describes the types that can be contained in a coroutine.
     /// It will be a type variable initially and unified in the last stages of typeck of a body.
-    /// It contains a tuple of all the types that could end up on a generator frame.
+    /// It contains a tuple of all the types that could end up on a coroutine frame.
     /// The state transformation MIR pass may only produce layouts which mention types
     /// in this tuple. Upvars are not counted here.
     pub fn witness(self) -> Ty<'tcx> {
         self.split().witness.expect_ty()
     }
 
-    /// Returns an iterator over the list of types of captured paths by the generator.
+    /// Returns an iterator over the list of types of captured paths by the coroutine.
     /// In case there was a type error in figuring out the types of the captured path, an
     /// empty iterator is returned.
     #[inline]
@@ -443,28 +443,28 @@ impl<'tcx> GeneratorArgs<'tcx> {
         }
     }
 
-    /// Returns the tuple type representing the upvars for this generator.
+    /// Returns the tuple type representing the upvars for this coroutine.
     #[inline]
     pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
         self.split().tupled_upvars_ty.expect_ty()
     }
 
-    /// Returns the type representing the resume type of the generator.
+    /// Returns the type representing the resume type of the coroutine.
     pub fn resume_ty(self) -> Ty<'tcx> {
         self.split().resume_ty.expect_ty()
     }
 
-    /// Returns the type representing the yield type of the generator.
+    /// Returns the type representing the yield type of the coroutine.
     pub fn yield_ty(self) -> Ty<'tcx> {
         self.split().yield_ty.expect_ty()
     }
 
-    /// Returns the type representing the return type of the generator.
+    /// Returns the type representing the return type of the coroutine.
     pub fn return_ty(self) -> Ty<'tcx> {
         self.split().return_ty.expect_ty()
     }
 
-    /// Returns the "generator signature", which consists of its yield
+    /// Returns the "coroutine signature", which consists of its yield
     /// and return types.
     ///
     /// N.B., some bits of the code prefers to see this wrapped in a
@@ -474,7 +474,7 @@ impl<'tcx> GeneratorArgs<'tcx> {
         ty::Binder::dummy(self.sig())
     }
 
-    /// Returns the "generator signature", which consists of its resume, yield
+    /// Returns the "coroutine signature", which consists of its resume, yield
     /// and return types.
     pub fn sig(self) -> GenSig<'tcx> {
         ty::GenSig {
@@ -485,23 +485,23 @@ impl<'tcx> GeneratorArgs<'tcx> {
     }
 }
 
-impl<'tcx> GeneratorArgs<'tcx> {
-    /// Generator has not been resumed yet.
+impl<'tcx> CoroutineArgs<'tcx> {
+    /// Coroutine has not been resumed yet.
     pub const UNRESUMED: usize = 0;
-    /// Generator has returned or is completed.
+    /// Coroutine has returned or is completed.
     pub const RETURNED: usize = 1;
-    /// Generator has been poisoned.
+    /// Coroutine has been poisoned.
     pub const POISONED: usize = 2;
 
     const UNRESUMED_NAME: &'static str = "Unresumed";
     const RETURNED_NAME: &'static str = "Returned";
     const POISONED_NAME: &'static str = "Panicked";
 
-    /// The valid variant indices of this generator.
+    /// The valid variant indices of this coroutine.
     #[inline]
     pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
-        FIRST_VARIANT..tcx.generator_layout(def_id).unwrap().variant_fields.next_index()
+        FIRST_VARIANT..tcx.coroutine_layout(def_id).unwrap().variant_fields.next_index()
     }
 
     /// The discriminant for the given variant. Panics if the `variant_index` is
@@ -513,13 +513,13 @@ impl<'tcx> GeneratorArgs<'tcx> {
         tcx: TyCtxt<'tcx>,
         variant_index: VariantIdx,
     ) -> Discr<'tcx> {
-        // Generators don't support explicit discriminant values, so they are
+        // Coroutines don't support explicit discriminant values, so they are
         // the same as the variant index.
         assert!(self.variant_range(def_id, tcx).contains(&variant_index));
         Discr { val: variant_index.as_usize() as u128, ty: self.discr_ty(tcx) }
     }
 
-    /// The set of all discriminants for the generator, enumerated with their
+    /// The set of all discriminants for the coroutine, enumerated with their
     /// variant indices.
     #[inline]
     pub fn discriminants(
@@ -543,15 +543,15 @@ impl<'tcx> GeneratorArgs<'tcx> {
         }
     }
 
-    /// The type of the state discriminant used in the generator type.
+    /// The type of the state discriminant used in the coroutine type.
     #[inline]
     pub fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         tcx.types.u32
     }
 
     /// This returns the types of the MIR locals which had to be stored across suspension points.
-    /// It is calculated in rustc_mir_transform::generator::StateTransform.
-    /// All the types here must be in the tuple in GeneratorInterior.
+    /// It is calculated in rustc_mir_transform::coroutine::StateTransform.
+    /// All the types here must be in the tuple in CoroutineInterior.
     ///
     /// The locals are grouped by their variant number. Note that some locals may
     /// be repeated in multiple variants.
@@ -561,7 +561,7 @@ impl<'tcx> GeneratorArgs<'tcx> {
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
     ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
-        let layout = tcx.generator_layout(def_id).unwrap();
+        let layout = tcx.coroutine_layout(def_id).unwrap();
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| {
                 ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
@@ -569,7 +569,7 @@ impl<'tcx> GeneratorArgs<'tcx> {
         })
     }
 
-    /// This is the types of the fields of a generator which are not stored in a
+    /// This is the types of the fields of a coroutine which are not stored in a
     /// variant.
     #[inline]
     pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
@@ -580,18 +580,18 @@ impl<'tcx> GeneratorArgs<'tcx> {
 #[derive(Debug, Copy, Clone, HashStable)]
 pub enum UpvarArgs<'tcx> {
     Closure(GenericArgsRef<'tcx>),
-    Generator(GenericArgsRef<'tcx>),
+    Coroutine(GenericArgsRef<'tcx>),
 }
 
 impl<'tcx> UpvarArgs<'tcx> {
-    /// Returns an iterator over the list of types of captured paths by the closure/generator.
+    /// Returns an iterator over the list of types of captured paths by the closure/coroutine.
     /// In case there was a type error in figuring out the types of the captured path, an
     /// empty iterator is returned.
     #[inline]
     pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
         let tupled_tys = match self {
             UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
-            UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(),
+            UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
         };
 
         match tupled_tys.kind() {
@@ -606,7 +606,7 @@ impl<'tcx> UpvarArgs<'tcx> {
     pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
         match self {
             UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
-            UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(),
+            UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
         }
     }
 }
@@ -2165,27 +2165,27 @@ impl<'tcx> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn new_generator(
+    pub fn new_coroutine(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        generator_args: GenericArgsRef<'tcx>,
+        coroutine_args: GenericArgsRef<'tcx>,
         movability: hir::Movability,
     ) -> Ty<'tcx> {
         debug_assert_eq!(
-            generator_args.len(),
+            coroutine_args.len(),
             tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
-            "generator constructed with incorrect number of substitutions"
+            "coroutine constructed with incorrect number of substitutions"
         );
-        Ty::new(tcx, Generator(def_id, generator_args, movability))
+        Ty::new(tcx, Coroutine(def_id, coroutine_args, movability))
     }
 
     #[inline]
-    pub fn new_generator_witness(
+    pub fn new_coroutine_witness(
         tcx: TyCtxt<'tcx>,
         id: DefId,
         args: GenericArgsRef<'tcx>,
     ) -> Ty<'tcx> {
-        Ty::new(tcx, GeneratorWitness(id, args))
+        Ty::new(tcx, CoroutineWitness(id, args))
     }
 
     // misc
@@ -2495,8 +2495,8 @@ impl<'tcx> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn is_generator(self) -> bool {
-        matches!(self.kind(), Generator(..))
+    pub fn is_coroutine(self) -> bool {
+        matches!(self.kind(), Coroutine(..))
     }
 
     #[inline]
@@ -2652,13 +2652,13 @@ impl<'tcx> Ty<'tcx> {
 
     /// If the type contains variants, returns the valid range of variant indices.
     //
-    // FIXME: This requires the optimized MIR in the case of generators.
+    // FIXME: This requires the optimized MIR in the case of coroutines.
     #[inline]
     pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
         match self.kind() {
             TyKind::Adt(adt, _) => Some(adt.variant_range()),
-            TyKind::Generator(def_id, args, _) => {
-                Some(args.as_generator().variant_range(*def_id, tcx))
+            TyKind::Coroutine(def_id, args, _) => {
+                Some(args.as_coroutine().variant_range(*def_id, tcx))
             }
             _ => None,
         }
@@ -2667,7 +2667,7 @@ impl<'tcx> Ty<'tcx> {
     /// If the type contains variants, returns the variant for `variant_index`.
     /// Panics if `variant_index` is out of range.
     //
-    // FIXME: This requires the optimized MIR in the case of generators.
+    // FIXME: This requires the optimized MIR in the case of coroutines.
     #[inline]
     pub fn discriminant_for_variant(
         self,
@@ -2678,8 +2678,8 @@ impl<'tcx> Ty<'tcx> {
             TyKind::Adt(adt, _) if adt.is_enum() => {
                 Some(adt.discriminant_for_variant(tcx, variant_index))
             }
-            TyKind::Generator(def_id, args, _) => {
-                Some(args.as_generator().discriminant_for_variant(*def_id, tcx, variant_index))
+            TyKind::Coroutine(def_id, args, _) => {
+                Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index))
             }
             _ => None,
         }
@@ -2689,7 +2689,7 @@ impl<'tcx> Ty<'tcx> {
     pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self.kind() {
             ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
-            ty::Generator(_, args, _) => args.as_generator().discr_ty(tcx),
+            ty::Coroutine(_, args, _) => args.as_coroutine().discr_ty(tcx),
 
             ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx.associated_item_def_ids(
@@ -2714,7 +2714,7 @@ impl<'tcx> Ty<'tcx> {
             | ty::FnPtr(..)
             | ty::Dynamic(..)
             | ty::Closure(..)
-            | ty::GeneratorWitness(..)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Error(_)
@@ -2748,8 +2748,8 @@ impl<'tcx> Ty<'tcx> {
             | ty::RawPtr(..)
             | ty::Char
             | ty::Ref(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Array(..)
             | ty::Closure(..)
             | ty::Never
@@ -2836,8 +2836,8 @@ impl<'tcx> Ty<'tcx> {
             | ty::RawPtr(..)
             | ty::Char
             | ty::Ref(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Array(..)
             | ty::Closure(..)
             | ty::Never
@@ -2900,7 +2900,7 @@ impl<'tcx> Ty<'tcx> {
             // anything with custom metadata it might be more complicated.
             ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false,
 
-            ty::Generator(..) | ty::GeneratorWitness(..) => false,
+            ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
 
             // Might be, but not "trivial" so just giving the safe answer.
             ty::Adt(..) | ty::Closure(..) => false,
@@ -2975,8 +2975,8 @@ impl<'tcx> Ty<'tcx> {
             | FnPtr(_)
             | Dynamic(_, _, _)
             | Closure(_, _)
-            | Generator(_, _, _)
-            | GeneratorWitness(..)
+            | Coroutine(_, _, _)
+            | CoroutineWitness(..)
             | Never
             | Tuple(_) => true,
             Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false,
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index a44224e4dc7..7d516410b20 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -189,9 +189,9 @@ pub struct TypeckResults<'tcx> {
     /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
     pub rvalue_scopes: RvalueScopes,
 
-    /// Stores the predicates that apply on generator witness types.
-    /// formatting modified file tests/ui/generator/retain-resume-ref.rs
-    pub generator_interior_predicates:
+    /// Stores the predicates that apply on coroutine witness types.
+    /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
+    pub coroutine_interior_predicates:
         LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
 
     /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
@@ -231,7 +231,7 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_min_captures: Default::default(),
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
-            generator_interior_predicates: Default::default(),
+            coroutine_interior_predicates: Default::default(),
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 31b52677b27..be48c0e8926 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -548,15 +548,15 @@ impl<'tcx> TyCtxt<'tcx> {
     /// those are not yet phased out). The parent of the closure's
     /// `DefId` will also be the context where it appears.
     pub fn is_closure(self, def_id: DefId) -> bool {
-        matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator)
+        matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Coroutine)
     }
 
     /// Returns `true` if `def_id` refers to a definition that does not have its own
-    /// type-checking context, i.e. closure, generator or inline const.
+    /// type-checking context, i.e. closure, coroutine or inline const.
     pub fn is_typeck_child(self, def_id: DefId) -> bool {
         matches!(
             self.def_kind(def_id),
-            DefKind::Closure | DefKind::Generator | DefKind::InlineConst
+            DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst
         )
     }
 
@@ -686,13 +686,13 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Return the set of types that should be taken into account when checking
-    /// trait bounds on a generator's internal state.
-    pub fn generator_hidden_types(
+    /// trait bounds on a coroutine's internal state.
+    pub fn coroutine_hidden_types(
         self,
         def_id: DefId,
     ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
-        let generator_layout = self.mir_generator_witnesses(def_id);
-        generator_layout
+        let coroutine_layout = self.mir_coroutine_witnesses(def_id);
+        coroutine_layout
             .as_ref()
             .map_or_else(|| [].iter(), |l| l.field_tys.iter())
             .filter(|decl| !decl.ignore_for_traits)
@@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
             found_recursion: false,
             found_any_recursion: false,
             check_recursion: false,
-            expand_generators: false,
+            expand_coroutines: false,
             tcx: self,
         };
         val.fold_with(&mut visitor)
@@ -729,7 +729,7 @@ impl<'tcx> TyCtxt<'tcx> {
             found_recursion: false,
             found_any_recursion: false,
             check_recursion: true,
-            expand_generators: true,
+            expand_coroutines: true,
             tcx: self,
         };
 
@@ -746,9 +746,9 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
         match def_kind {
             DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
-            DefKind::Generator => match self.generator_kind(def_id).unwrap() {
-                rustc_hir::GeneratorKind::Async(..) => "async closure",
-                rustc_hir::GeneratorKind::Gen => "generator",
+            DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
+                rustc_hir::CoroutineKind::Async(..) => "async closure",
+                rustc_hir::CoroutineKind::Coroutine => "coroutine",
             },
             _ => def_kind.descr(def_id),
         }
@@ -763,9 +763,9 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
         match def_kind {
             DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
-            DefKind::Generator => match self.generator_kind(def_id).unwrap() {
-                rustc_hir::GeneratorKind::Async(..) => "an",
-                rustc_hir::GeneratorKind::Gen => "a",
+            DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
+                rustc_hir::CoroutineKind::Async(..) => "an",
+                rustc_hir::CoroutineKind::Coroutine => "a",
             },
             _ => def_kind.article(),
         }
@@ -804,7 +804,7 @@ struct OpaqueTypeExpander<'tcx> {
     primary_def_id: Option<DefId>,
     found_recursion: bool,
     found_any_recursion: bool,
-    expand_generators: bool,
+    expand_coroutines: bool,
     /// Whether or not to check for recursive opaque types.
     /// This is `true` when we're explicitly checking for opaque type
     /// recursion, and 'false' otherwise to avoid unnecessary work.
@@ -842,7 +842,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
         }
     }
 
-    fn expand_generator(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
+    fn expand_coroutine(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
         if self.found_any_recursion {
             return None;
         }
@@ -851,11 +851,11 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
             let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
                 Some(expanded_ty) => *expanded_ty,
                 None => {
-                    for bty in self.tcx.generator_hidden_types(def_id) {
+                    for bty in self.tcx.coroutine_hidden_types(def_id) {
                         let hidden_ty = bty.instantiate(self.tcx, args);
                         self.fold_ty(hidden_ty);
                     }
-                    let expanded_ty = Ty::new_generator_witness(self.tcx, def_id, args);
+                    let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
                     self.expanded_cache.insert((def_id, args), expanded_ty);
                     expanded_ty
                 }
@@ -882,14 +882,14 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
             self.expand_opaque_ty(def_id, args).unwrap_or(t)
-        } else if t.has_opaque_types() || t.has_generators() {
+        } else if t.has_opaque_types() || t.has_coroutines() {
             t.super_fold_with(self)
         } else {
             t
         };
-        if self.expand_generators {
-            if let ty::GeneratorWitness(def_id, args) = *t.kind() {
-                t = self.expand_generator(def_id, args).unwrap_or(t);
+        if self.expand_coroutines {
+            if let ty::CoroutineWitness(def_id, args) = *t.kind() {
+                t = self.expand_coroutine(def_id, args).unwrap_or(t);
             }
         }
         t
@@ -1024,8 +1024,8 @@ impl<'tcx> Ty<'tcx> {
             | ty::Closure(..)
             | ty::Dynamic(..)
             | ty::Foreign(_)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Infer(_)
             | ty::Alias(..)
             | ty::Param(_)
@@ -1063,8 +1063,8 @@ impl<'tcx> Ty<'tcx> {
             | ty::Closure(..)
             | ty::Dynamic(..)
             | ty::Foreign(_)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Infer(_)
             | ty::Alias(..)
             | ty::Param(_)
@@ -1182,7 +1182,7 @@ impl<'tcx> Ty<'tcx> {
             // Conservatively return `false` for all others...
 
             // Anonymous function types
-            ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Generator(..) => false,
+            ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Coroutine(..) => false,
 
             // Generic or inferred types
             //
@@ -1192,7 +1192,7 @@ impl<'tcx> Ty<'tcx> {
                 false
             }
 
-            ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
+            ty::Foreign(_) | ty::CoroutineWitness(..) | ty::Error(_) => false,
         }
     }
 
@@ -1287,7 +1287,7 @@ pub fn needs_drop_components<'tcx>(
         | ty::FnDef(..)
         | ty::FnPtr(_)
         | ty::Char
-        | ty::GeneratorWitness(..)
+        | ty::CoroutineWitness(..)
         | ty::RawPtr(_)
         | ty::Ref(..)
         | ty::Str => Ok(SmallVec::new()),
@@ -1327,7 +1327,7 @@ pub fn needs_drop_components<'tcx>(
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Closure(..)
-        | ty::Generator(..) => Ok(smallvec![ty]),
+        | ty::Coroutine(..) => Ok(smallvec![ty]),
     }
 }
 
@@ -1358,7 +1358,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
 
         // Not trivial because they have components, and instead of looking inside,
         // we'll just perform trait selection.
-        ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Adt(..) => false,
+        ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Adt(..) => false,
 
         ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),
 
@@ -1419,7 +1419,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
         found_recursion: false,
         found_any_recursion: false,
         check_recursion: false,
-        expand_generators: false,
+        expand_coroutines: false,
         tcx,
     };
     val.fold_with(&mut visitor)
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5deb5bfb19e..15de9948644 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -47,7 +47,7 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
     fn has_opaque_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
     }
-    fn has_generators(&self) -> bool {
+    fn has_coroutines(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_GENERATOR)
     }
     fn references_error(&self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a86ff64bd0c..20bdbcb5b7b 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -189,8 +189,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
             }
             ty::Adt(_, args)
             | ty::Closure(_, args)
-            | ty::Generator(_, args, _)
-            | ty::GeneratorWitness(_, args)
+            | ty::Coroutine(_, args, _)
+            | ty::CoroutineWitness(_, args)
             | ty::FnDef(_, args) => {
                 stack.extend(args.iter().rev());
             }
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index a81f70e3346..3de2f45ad9a 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -48,7 +48,7 @@ pub(super) fn build_custom_mir<'tcx>(
         source: MirSource::item(did),
         phase: MirPhase::Built,
         source_scopes: IndexVec::new(),
-        generator: None,
+        coroutine: None,
         local_decls: IndexVec::new(),
         user_type_annotations: IndexVec::new(),
         arg_count: params.len(),
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 4aff406b376..c6a09f6568a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -75,7 +75,7 @@ pub(in crate::build) struct PlaceBuilder<'tcx> {
 
 /// Given a list of MIR projections, convert them to list of HIR ProjectionKind.
 /// The projections are truncated to represent a path that might be captured by a
-/// closure/generator. This implies the vector returned from this function doesn't contain
+/// closure/coroutine. This implies the vector returned from this function doesn't contain
 /// ProjectionElems `Downcast`, `ConstantIndex`, `Index`, or `Subslice` because those will never be
 /// part of a path that is captured by a closure. We stop applying projections once we see the first
 /// projection that isn't captured by a closure.
@@ -213,7 +213,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
 /// projections.
 ///
 /// Supports only HIR projection kinds that represent a path that might be
-/// captured by a closure or a generator, i.e., an `Index` or a `Subslice`
+/// captured by a closure or a coroutine, i.e., an `Index` or a `Subslice`
 /// projection kinds are unsupported.
 fn strip_prefix<'a, 'tcx>(
     mut base_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 7d7542a9a6a..eece8684e36 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -181,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block = success;
 
                 // The `Box<T>` temporary created here is not a part of the HIR,
-                // and therefore is not considered during generator auto-trait
+                // and therefore is not considered during coroutine auto-trait
                 // determination. See the comment about `box` at `yield_in_scope`.
                 let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span));
                 this.cfg.push(
@@ -487,11 +487,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .collect();
 
                 let result = match args {
-                    UpvarArgs::Generator(args) => {
+                    UpvarArgs::Coroutine(args) => {
                         // We implicitly set the discriminant to 0. See
                         // librustc_mir/transform/deaggregator.rs for details.
                         let movability = movability.unwrap();
-                        Box::new(AggregateKind::Generator(closure_id.to_def_id(), args, movability))
+                        Box::new(AggregateKind::Coroutine(closure_id.to_def_id(), args, movability))
                     }
                     UpvarArgs::Closure(args) => {
                         Box::new(AggregateKind::Closure(closure_id.to_def_id(), args))
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index a4de42d45c9..054661cf237 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -547,7 +547,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     source_info,
                     TerminatorKind::Yield { value, resume, resume_arg: destination, drop: None },
                 );
-                this.generator_drop_cleanup(block);
+                this.coroutine_drop_cleanup(block);
                 resume.unit()
             }
 
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index d9098bac1c2..8a3b67b8f03 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -9,7 +9,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{GeneratorKind, Node};
+use rustc_hir::{CoroutineKind, Node};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -173,7 +173,7 @@ struct Builder<'a, 'tcx> {
     check_overflow: bool,
     fn_span: Span,
     arg_count: usize,
-    generator_kind: Option<GeneratorKind>,
+    coroutine_kind: Option<CoroutineKind>,
 
     /// The current set of scopes, updated as we traverse;
     /// see the `scope` module for more details.
@@ -448,7 +448,7 @@ fn construct_fn<'tcx>(
 ) -> Body<'tcx> {
     let span = tcx.def_span(fn_def);
     let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
-    let generator_kind = tcx.generator_kind(fn_def);
+    let coroutine_kind = tcx.coroutine_kind(fn_def);
 
     // The representation of thir for `-Zunpretty=thir-tree` relies on
     // the entry expression being the last element of `thir.exprs`.
@@ -478,12 +478,12 @@ fn construct_fn<'tcx>(
 
     let arguments = &thir.params;
 
-    let (yield_ty, return_ty) = if generator_kind.is_some() {
+    let (yield_ty, return_ty) = if coroutine_kind.is_some() {
         let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
         let gen_sig = match gen_ty.kind() {
-            ty::Generator(_, gen_args, ..) => gen_args.as_generator().sig(),
+            ty::Coroutine(_, gen_args, ..) => gen_args.as_coroutine().sig(),
             _ => {
-                span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
+                span_bug!(span, "coroutine w/o coroutine type: {:?}", gen_ty)
             }
         };
         (Some(gen_sig.yield_ty), gen_sig.return_ty)
@@ -519,7 +519,7 @@ fn construct_fn<'tcx>(
         safety,
         return_ty,
         return_ty_span,
-        generator_kind,
+        coroutine_kind,
     );
 
     let call_site_scope =
@@ -553,7 +553,7 @@ fn construct_fn<'tcx>(
         None
     };
     if yield_ty.is_some() {
-        body.generator.as_mut().unwrap().yield_ty = yield_ty;
+        body.coroutine.as_mut().unwrap().yield_ty = yield_ty;
     }
     body
 }
@@ -619,7 +619,7 @@ fn construct_const<'a, 'tcx>(
 fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
     let span = tcx.def_span(def);
     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
-    let generator_kind = tcx.generator_kind(def);
+    let coroutine_kind = tcx.coroutine_kind(def);
     let body_owner_kind = tcx.hir().body_owner_kind(def);
 
     let ty = Ty::new_error(tcx, err);
@@ -629,8 +629,8 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
             let ty = tcx.type_of(def).instantiate_identity();
             match ty.kind() {
                 ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(),
-                ty::Generator(..) => 2,
-                _ => bug!("expected closure or generator, found {ty:?}"),
+                ty::Coroutine(..) => 2,
+                _ => bug!("expected closure or coroutine, found {ty:?}"),
             }
         }
         hir::BodyOwnerKind::Const { .. } => 0,
@@ -669,10 +669,10 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
         num_params,
         vec![],
         span,
-        generator_kind,
+        coroutine_kind,
         Some(err),
     );
-    body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
+    body.coroutine.as_mut().map(|gen| gen.yield_ty = Some(ty));
     body
 }
 
@@ -687,7 +687,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         safety: Safety,
         return_ty: Ty<'tcx>,
         return_span: Span,
-        generator_kind: Option<GeneratorKind>,
+        coroutine_kind: Option<CoroutineKind>,
     ) -> Builder<'a, 'tcx> {
         let tcx = infcx.tcx;
         let attrs = tcx.hir().attrs(hir_id);
@@ -718,7 +718,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
             arg_count,
-            generator_kind,
+            coroutine_kind,
             scopes: scope::Scopes::new(),
             block_context: BlockContext::new(),
             source_scopes: IndexVec::new(),
@@ -760,7 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.arg_count,
             self.var_debug_info,
             self.fn_span,
-            self.generator_kind,
+            self.coroutine_kind,
             None,
         )
     }
@@ -777,7 +777,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         let upvar_args = match closure_ty.kind() {
             ty::Closure(_, args) => ty::UpvarArgs::Closure(args),
-            ty::Generator(_, args, _) => ty::UpvarArgs::Generator(args),
+            ty::Coroutine(_, args, _) => ty::UpvarArgs::Coroutine(args),
             _ => return,
         };
 
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index bc151cc7058..b3d3863b5db 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -108,8 +108,8 @@ pub struct Scopes<'tcx> {
     /// [DropTree] for more details.
     unwind_drops: DropTree,
 
-    /// Drops that need to be done on paths to the `GeneratorDrop` terminator.
-    generator_drops: DropTree,
+    /// Drops that need to be done on paths to the `CoroutineDrop` terminator.
+    coroutine_drops: DropTree,
 }
 
 #[derive(Debug)]
@@ -133,8 +133,8 @@ struct Scope {
     cached_unwind_block: Option<DropIdx>,
 
     /// The drop index that will drop everything in and below this scope on a
-    /// generator drop path.
-    cached_generator_drop_block: Option<DropIdx>,
+    /// coroutine drop path.
+    cached_coroutine_drop_block: Option<DropIdx>,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -194,7 +194,7 @@ const ROOT_NODE: DropIdx = DropIdx::from_u32(0);
 /// A tree of drops that we have deferred lowering. It's used for:
 ///
 /// * Drops on unwind paths
-/// * Drops on generator drop paths (when a suspended generator is dropped)
+/// * Drops on coroutine drop paths (when a suspended coroutine is dropped)
 /// * Drops on return and loop exit paths
 /// * Drops on the else path in an `if let` chain
 ///
@@ -222,8 +222,8 @@ impl Scope {
     ///  * polluting the cleanup MIR with StorageDead creates
     ///    landing pads even though there's no actual destructors
     ///  * freeing up stack space has no effect during unwinding
-    /// Note that for generators we do emit StorageDeads, for the
-    /// use of optimizations in the MIR generator transform.
+    /// Note that for coroutines we do emit StorageDeads, for the
+    /// use of optimizations in the MIR coroutine transform.
     fn needs_cleanup(&self) -> bool {
         self.drops.iter().any(|drop| match drop.kind {
             DropKind::Value => true,
@@ -233,7 +233,7 @@ impl Scope {
 
     fn invalidate_cache(&mut self) {
         self.cached_unwind_block = None;
-        self.cached_generator_drop_block = None;
+        self.cached_coroutine_drop_block = None;
     }
 }
 
@@ -407,7 +407,7 @@ impl<'tcx> Scopes<'tcx> {
             breakable_scopes: Vec::new(),
             if_then_scope: None,
             unwind_drops: DropTree::new(),
-            generator_drops: DropTree::new(),
+            coroutine_drops: DropTree::new(),
         }
     }
 
@@ -419,7 +419,7 @@ impl<'tcx> Scopes<'tcx> {
             drops: vec![],
             moved_locals: vec![],
             cached_unwind_block: None,
-            cached_generator_drop_block: None,
+            cached_coroutine_drop_block: None,
         });
     }
 
@@ -734,7 +734,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // If we are emitting a `drop` statement, we need to have the cached
         // diverge cleanup pads ready in case that drop panics.
         let needs_cleanup = self.scopes.scopes.last().is_some_and(|scope| scope.needs_cleanup());
-        let is_generator = self.generator_kind.is_some();
+        let is_coroutine = self.coroutine_kind.is_some();
         let unwind_to = if needs_cleanup { self.diverge_cleanup() } else { DropIdx::MAX };
 
         let scope = self.scopes.scopes.last().expect("leave_top_scope called with no scopes");
@@ -744,7 +744,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             scope,
             block,
             unwind_to,
-            is_generator && needs_cleanup,
+            is_coroutine && needs_cleanup,
             self.arg_count,
         ))
     }
@@ -984,11 +984,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // caches gets invalidated. i.e., if a new drop is added into the middle scope, the
         // cache of outer scope stays intact.
         //
-        // Since we only cache drops for the unwind path and the generator drop
+        // Since we only cache drops for the unwind path and the coroutine drop
         // path, we only need to invalidate the cache for drops that happen on
-        // the unwind or generator drop paths. This means that for
-        // non-generators we don't need to invalidate caches for `DropKind::Storage`.
-        let invalidate_caches = needs_drop || self.generator_kind.is_some();
+        // the unwind or coroutine drop paths. This means that for
+        // non-coroutines we don't need to invalidate caches for `DropKind::Storage`.
+        let invalidate_caches = needs_drop || self.coroutine_kind.is_some();
         for scope in self.scopes.scopes.iter_mut().rev() {
             if invalidate_caches {
                 scope.invalidate_cache();
@@ -1101,10 +1101,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             return cached_drop;
         }
 
-        let is_generator = self.generator_kind.is_some();
+        let is_coroutine = self.coroutine_kind.is_some();
         for scope in &mut self.scopes.scopes[uncached_scope..=target] {
             for drop in &scope.drops {
-                if is_generator || drop.kind == DropKind::Value {
+                if is_coroutine || drop.kind == DropKind::Value {
                     cached_drop = self.scopes.unwind_drops.add_drop(*drop, cached_drop);
                 }
             }
@@ -1137,17 +1137,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /// Sets up a path that performs all required cleanup for dropping a
-    /// generator, starting from the given block that ends in
+    /// coroutine, starting from the given block that ends in
     /// [TerminatorKind::Yield].
     ///
-    /// This path terminates in GeneratorDrop.
-    pub(crate) fn generator_drop_cleanup(&mut self, yield_block: BasicBlock) {
+    /// This path terminates in CoroutineDrop.
+    pub(crate) fn coroutine_drop_cleanup(&mut self, yield_block: BasicBlock) {
         debug_assert!(
             matches!(
                 self.cfg.block_data(yield_block).terminator().kind,
                 TerminatorKind::Yield { .. }
             ),
-            "generator_drop_cleanup called on block with non-yield terminator."
+            "coroutine_drop_cleanup called on block with non-yield terminator."
         );
         let (uncached_scope, mut cached_drop) = self
             .scopes
@@ -1156,18 +1156,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .enumerate()
             .rev()
             .find_map(|(scope_idx, scope)| {
-                scope.cached_generator_drop_block.map(|cached_block| (scope_idx + 1, cached_block))
+                scope.cached_coroutine_drop_block.map(|cached_block| (scope_idx + 1, cached_block))
             })
             .unwrap_or((0, ROOT_NODE));
 
         for scope in &mut self.scopes.scopes[uncached_scope..] {
             for drop in &scope.drops {
-                cached_drop = self.scopes.generator_drops.add_drop(*drop, cached_drop);
+                cached_drop = self.scopes.coroutine_drops.add_drop(*drop, cached_drop);
             }
-            scope.cached_generator_drop_block = Some(cached_drop);
+            scope.cached_coroutine_drop_block = Some(cached_drop);
         }
 
-        self.scopes.generator_drops.add_entry(yield_block, cached_drop);
+        self.scopes.coroutine_drops.add_entry(yield_block, cached_drop);
     }
 
     /// Utility function for *non*-scope code to build their own drops
@@ -1274,7 +1274,7 @@ fn build_scope_drops<'tcx>(
     // drops panic (panicking while unwinding will abort, so there's no need for
     // another set of arrows).
     //
-    // For generators, we unwind from a drop on a local to its StorageDead
+    // For coroutines, we unwind from a drop on a local to its StorageDead
     // statement. For other functions we don't worry about StorageDead. The
     // drops for the unwind path should have already been generated by
     // `diverge_cleanup_gen`.
@@ -1346,7 +1346,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         blocks[ROOT_NODE] = continue_block;
 
         drops.build_mir::<ExitScopes>(&mut self.cfg, &mut blocks);
-        let is_generator = self.generator_kind.is_some();
+        let is_coroutine = self.coroutine_kind.is_some();
 
         // Link the exit drop tree to unwind drop tree.
         if drops.drops.iter().any(|(drop, _)| drop.kind == DropKind::Value) {
@@ -1355,7 +1355,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
             for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) {
                 match drop_data.0.kind {
                     DropKind::Storage => {
-                        if is_generator {
+                        if is_coroutine {
                             let unwind_drop = self
                                 .scopes
                                 .unwind_drops
@@ -1381,10 +1381,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         blocks[ROOT_NODE].map(BasicBlock::unit)
     }
 
-    /// Build the unwind and generator drop trees.
+    /// Build the unwind and coroutine drop trees.
     pub(crate) fn build_drop_trees(&mut self) {
-        if self.generator_kind.is_some() {
-            self.build_generator_drop_trees();
+        if self.coroutine_kind.is_some() {
+            self.build_coroutine_drop_trees();
         } else {
             Self::build_unwind_tree(
                 &mut self.cfg,
@@ -1395,18 +1395,18 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         }
     }
 
-    fn build_generator_drop_trees(&mut self) {
-        // Build the drop tree for dropping the generator while it's suspended.
-        let drops = &mut self.scopes.generator_drops;
+    fn build_coroutine_drop_trees(&mut self) {
+        // Build the drop tree for dropping the coroutine while it's suspended.
+        let drops = &mut self.scopes.coroutine_drops;
         let cfg = &mut self.cfg;
         let fn_span = self.fn_span;
         let mut blocks = IndexVec::from_elem(None, &drops.drops);
-        drops.build_mir::<GeneratorDrop>(cfg, &mut blocks);
+        drops.build_mir::<CoroutineDrop>(cfg, &mut blocks);
         if let Some(root_block) = blocks[ROOT_NODE] {
             cfg.terminate(
                 root_block,
                 SourceInfo::outermost(fn_span),
-                TerminatorKind::GeneratorDrop,
+                TerminatorKind::CoroutineDrop,
             );
         }
 
@@ -1416,11 +1416,11 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         Self::build_unwind_tree(cfg, unwind_drops, fn_span, resume_block);
 
         // Build the drop tree for unwinding when dropping a suspended
-        // generator.
+        // coroutine.
         //
         // This is a different tree to the standard unwind paths here to
         // prevent drop elaboration from creating drop flags that would have
-        // to be captured by the generator. I'm not sure how important this
+        // to be captured by the coroutine. I'm not sure how important this
         // optimization is, but it is here.
         for (drop_idx, drop_data) in drops.drops.iter_enumerated() {
             if let DropKind::Value = drop_data.0.kind {
@@ -1461,9 +1461,9 @@ impl<'tcx> DropTreeBuilder<'tcx> for ExitScopes {
     }
 }
 
-struct GeneratorDrop;
+struct CoroutineDrop;
 
-impl<'tcx> DropTreeBuilder<'tcx> for GeneratorDrop {
+impl<'tcx> DropTreeBuilder<'tcx> for CoroutineDrop {
     fn make_block(cfg: &mut CFG<'tcx>) -> BasicBlock {
         cfg.start_new_block()
     }
@@ -1474,7 +1474,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for GeneratorDrop {
         } else {
             span_bug!(
                 term.source_info.span,
-                "cannot enter generator drop tree from {:?}",
+                "cannot enter coroutine drop tree from {:?}",
                 term.kind
             )
         }
@@ -1511,7 +1511,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. } => {
                 span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind)
             }
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 2d221b826c9..00d2afce8c6 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -121,7 +121,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
         self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow
     }
 
-    /// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
+    /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body.
     fn visit_inner_body(&mut self, def: LocalDefId) {
         if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
             let inner_thir = &inner_thir.borrow();
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 4f98932a88d..c09dd186418 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,6 +1,6 @@
 use crate::{
     fluent_generated as fluent,
-    thir::pattern::{deconstruct_pat::DeconstructedPat, MatchCheckCtxt},
+    thir::pattern::{deconstruct_pat::WitnessPat, MatchCheckCtxt},
 };
 use rustc_errors::{
     error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -810,7 +810,7 @@ impl<'tcx> Uncovered<'tcx> {
     pub fn new<'p>(
         span: Span,
         cx: &MatchCheckCtxt<'p, 'tcx>,
-        witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
+        witnesses: Vec<WitnessPat<'tcx>>,
     ) -> Self {
         let witness_1 = witnesses.get(0).unwrap().to_pat(cx);
         Self {
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index e78274b4284..acf4d6bc2a0 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -192,7 +192,7 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
         match self.body[bb].terminator().kind {
             // These terminators return control flow to the caller.
             TerminatorKind::UnwindTerminate(_)
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 0535ea24b82..840c6e13bef 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -574,8 +574,8 @@ impl<'tcx> Cx<'tcx> {
                 let closure_ty = self.typeck_results().expr_ty(expr);
                 let (def_id, args, movability) = match *closure_ty.kind() {
                     ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None),
-                    ty::Generator(def_id, args, movability) => {
-                        (def_id, UpvarArgs::Generator(args), Some(movability))
+                    ty::Coroutine(def_id, args, movability) => {
+                        (def_id, UpvarArgs::Coroutine(args), Some(movability))
                     }
                     _ => {
                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index d98cc76adfb..8bc4cbb9532 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -37,7 +37,7 @@ pub(crate) fn thir_body(
 
         // The resume argument may be missing, in that case we need to provide it here.
         // It will always be `()` in this case.
-        if tcx.def_kind(owner_def) == DefKind::Generator && body.params.is_empty() {
+        if tcx.def_kind(owner_def) == DefKind::Coroutine && body.params.is_empty() {
             cx.thir.params.push(Param {
                 ty: Ty::new_unit(tcx),
                 pat: None,
@@ -148,7 +148,7 @@ impl<'tcx> Cx<'tcx> {
 
                 Some(env_param)
             }
-            DefKind::Generator => {
+            DefKind::Coroutine => {
                 let gen_ty = self.typeck_results.node_type(owner_id);
                 let gen_param =
                     Param { ty: gen_ty, pat: None, ty_span: None, self_kind: None, hir_id: None };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 9d38087fdeb..9156af3425a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1,4 +1,4 @@
-use super::deconstruct_pat::{Constructor, DeconstructedPat};
+use super::deconstruct_pat::{Constructor, DeconstructedPat, WitnessPat};
 use super::usefulness::{
     compute_match_usefulness, MatchArm, MatchCheckCtxt, Reachability, UsefulnessReport,
 };
@@ -279,7 +279,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
 
         let scrut = &self.thir[scrut];
         let scrut_ty = scrut.ty;
-        let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty);
+        let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);
 
         match source {
             // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
@@ -473,7 +473,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         let pattern = self.lower_pattern(&mut cx, pat);
         let pattern_ty = pattern.ty();
         let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false };
-        let report = compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty);
+        let report =
+            compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty, pattern.span());
 
         // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
         // only care about exhaustiveness here.
@@ -662,7 +663,7 @@ fn is_let_irrefutable<'p, 'tcx>(
     pat: &'p DeconstructedPat<'p, 'tcx>,
 ) -> bool {
     let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
-    let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty());
+    let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty(), pat.span());
 
     // Report if the pattern is unreachable, which can only occur when the type is uninhabited.
     // This also reports unreachable sub-patterns though, so we can't just replace it with an
@@ -701,8 +702,8 @@ fn report_arm_reachability<'p, 'tcx>(
     }
 }
 
-fn collect_non_exhaustive_tys<'p, 'tcx>(
-    pat: &DeconstructedPat<'p, 'tcx>,
+fn collect_non_exhaustive_tys<'tcx>(
+    pat: &WitnessPat<'tcx>,
     non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
 ) {
     if matches!(pat.ctor(), Constructor::NonExhaustive) {
@@ -718,7 +719,7 @@ fn non_exhaustive_match<'p, 'tcx>(
     thir: &Thir<'tcx>,
     scrut_ty: Ty<'tcx>,
     sp: Span,
-    witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
+    witnesses: Vec<WitnessPat<'tcx>>,
     arms: &[ArmId],
     expr_span: Span,
 ) -> ErrorGuaranteed {
@@ -896,10 +897,10 @@ fn non_exhaustive_match<'p, 'tcx>(
 
 pub(crate) fn joined_uncovered_patterns<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
-    witnesses: &[DeconstructedPat<'p, 'tcx>],
+    witnesses: &[WitnessPat<'tcx>],
 ) -> String {
     const LIMIT: usize = 3;
-    let pat_to_str = |pat: &DeconstructedPat<'p, 'tcx>| pat.to_pat(cx).to_string();
+    let pat_to_str = |pat: &WitnessPat<'tcx>| pat.to_pat(cx).to_string();
     match witnesses {
         [] => bug!(),
         [witness] => format!("`{}`", witness.to_pat(cx)),
@@ -916,7 +917,7 @@ pub(crate) fn joined_uncovered_patterns<'p, 'tcx>(
 }
 
 pub(crate) fn pattern_not_covered_label(
-    witnesses: &[DeconstructedPat<'_, '_>],
+    witnesses: &[WitnessPat<'_>],
     joined_patterns: &str,
 ) -> String {
     format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns)
@@ -927,7 +928,7 @@ fn adt_defined_here<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     err: &mut Diagnostic,
     ty: Ty<'tcx>,
-    witnesses: &[DeconstructedPat<'p, 'tcx>],
+    witnesses: &[WitnessPat<'tcx>],
 ) {
     let ty = ty.peel_refs();
     if let ty::Adt(def, _) = ty.kind() {
@@ -958,7 +959,7 @@ fn adt_defined_here<'p, 'tcx>(
 fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     def: AdtDef<'tcx>,
-    patterns: impl Iterator<Item = &'a DeconstructedPat<'p, 'tcx>>,
+    patterns: impl Iterator<Item = &'a WitnessPat<'tcx>>,
 ) -> Vec<Span> {
     use Constructor::*;
     let mut covered = vec![];
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index bbc0aeb66cf..86018340a69 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -629,18 +629,11 @@ pub(super) enum Constructor<'tcx> {
     /// `#[doc(hidden)]` ones.
     Hidden,
     /// Fake extra constructor for constructors that are not seen in the matrix, as explained in the
-    /// code for [`Constructor::split`]. The carried `bool` is used for the
-    /// `non_exhaustive_omitted_patterns` lint.
-    Missing {
-        nonexhaustive_enum_missing_visible_variants: bool,
-    },
+    /// code for [`Constructor::split`].
+    Missing,
 }
 
 impl<'tcx> Constructor<'tcx> {
-    pub(super) fn is_wildcard(&self) -> bool {
-        matches!(self, Wildcard)
-    }
-
     pub(super) fn is_non_exhaustive(&self) -> bool {
         matches!(self, NonExhaustive)
     }
@@ -778,14 +771,8 @@ impl<'tcx> Constructor<'tcx> {
                     let all_missing = split_set.present.is_empty();
                     let report_when_all_missing =
                         pcx.is_top_level && !IntRange::is_integral(pcx.ty);
-                    let ctor = if all_missing && !report_when_all_missing {
-                        Wildcard
-                    } else {
-                        Missing {
-                            nonexhaustive_enum_missing_visible_variants: split_set
-                                .nonexhaustive_enum_missing_visible_variants,
-                        }
-                    };
+                    let ctor =
+                        if all_missing && !report_when_all_missing { Wildcard } else { Missing };
                     smallvec![ctor]
                 } else {
                     split_set.present
@@ -905,11 +892,9 @@ pub(super) enum ConstructorSet {
 ///     either fully included in or disjoint from each constructor in the column. This avoids
 ///     non-trivial intersections like between `0..10` and `5..15`.
 #[derive(Debug)]
-struct SplitConstructorSet<'tcx> {
-    present: SmallVec<[Constructor<'tcx>; 1]>,
-    missing: Vec<Constructor<'tcx>>,
-    /// For the `non_exhaustive_omitted_patterns` lint.
-    nonexhaustive_enum_missing_visible_variants: bool,
+pub(super) struct SplitConstructorSet<'tcx> {
+    pub(super) present: SmallVec<[Constructor<'tcx>; 1]>,
+    pub(super) missing: Vec<Constructor<'tcx>>,
 }
 
 impl ConstructorSet {
@@ -1039,7 +1024,7 @@ impl ConstructorSet {
     /// constructors to 1/ determine which constructors of the type (if any) are missing; 2/ split
     /// constructors to handle non-trivial intersections e.g. on ranges or slices.
     #[instrument(level = "debug", skip(self, pcx, ctors), ret)]
-    fn split<'a, 'tcx>(
+    pub(super) fn split<'a, 'tcx>(
         &self,
         pcx: &PatCtxt<'_, '_, 'tcx>,
         ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
@@ -1051,7 +1036,6 @@ impl ConstructorSet {
         let mut missing = Vec::new();
         // Constructors in `ctors`, except wildcards.
         let mut seen = ctors.filter(|c| !(matches!(c, Opaque | Wildcard)));
-        let mut nonexhaustive_enum_missing_visible_variants = false;
         match self {
             ConstructorSet::Single => {
                 if seen.next().is_none() {
@@ -1063,6 +1047,7 @@ impl ConstructorSet {
             ConstructorSet::Variants { visible_variants, hidden_variants, non_exhaustive } => {
                 let seen_set: FxHashSet<_> = seen.map(|c| c.as_variant().unwrap()).collect();
                 let mut skipped_a_hidden_variant = false;
+
                 for variant in visible_variants {
                     let ctor = Variant(*variant);
                     if seen_set.contains(&variant) {
@@ -1071,8 +1056,6 @@ impl ConstructorSet {
                         missing.push(ctor);
                     }
                 }
-                nonexhaustive_enum_missing_visible_variants =
-                    *non_exhaustive && !missing.is_empty();
 
                 for variant in hidden_variants {
                     let ctor = Variant(*variant);
@@ -1159,7 +1142,7 @@ impl ConstructorSet {
             ConstructorSet::Uninhabited => {}
         }
 
-        SplitConstructorSet { present, missing, nonexhaustive_enum_missing_visible_variants }
+        SplitConstructorSet { present, missing }
     }
 
     /// Compute the set of constructors missing from this column.
@@ -1312,9 +1295,10 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
 
 /// Values and patterns can be represented as a constructor applied to some fields. This represents
 /// a pattern in this form.
-/// This also keeps track of whether the pattern has been found reachable during analysis. For this
-/// reason we should be careful not to clone patterns for which we care about that. Use
-/// `clone_and_forget_reachability` if you're sure.
+/// This also uses interior mutability to keep track of whether the pattern has been found reachable
+/// during analysis. For this reason they cannot be cloned.
+/// A `DeconstructedPat` will almost always come from user input; the only exception are some
+/// `Wildcard`s introduced during specialization.
 pub(crate) struct DeconstructedPat<'p, 'tcx> {
     ctor: Constructor<'tcx>,
     fields: Fields<'p, 'tcx>,
@@ -1337,20 +1321,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
         DeconstructedPat { ctor, fields, ty, span, reachable: Cell::new(false) }
     }
 
-    /// Construct a pattern that matches everything that starts with this constructor.
-    /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
-    /// `Some(_)`.
-    pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
-        let fields = Fields::wildcards(pcx, &ctor);
-        DeconstructedPat::new(ctor, fields, pcx.ty, pcx.span)
-    }
-
-    /// Clone this value. This method emphasizes that cloning loses reachability information and
-    /// should be done carefully.
-    pub(super) fn clone_and_forget_reachability(&self) -> Self {
-        DeconstructedPat::new(self.ctor.clone(), self.fields, self.ty, self.span)
-    }
-
     pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
         let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
         let ctor;
@@ -1533,98 +1503,16 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
         DeconstructedPat::new(ctor, fields, pat.ty, pat.span)
     }
 
-    pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
-        let is_wildcard = |pat: &Pat<'_>| {
-            matches!(pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
-        };
-        let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx)));
-        let kind = match &self.ctor {
-            Single | Variant(_) => match self.ty.kind() {
-                ty::Tuple(..) => PatKind::Leaf {
-                    subpatterns: subpatterns
-                        .enumerate()
-                        .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
-                        .collect(),
-                },
-                ty::Adt(adt_def, _) if adt_def.is_box() => {
-                    // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
-                    // of `std`). So this branch is only reachable when the feature is enabled and
-                    // the pattern is a box pattern.
-                    PatKind::Deref { subpattern: subpatterns.next().unwrap() }
-                }
-                ty::Adt(adt_def, args) => {
-                    let variant_index = self.ctor.variant_index_for_adt(*adt_def);
-                    let variant = &adt_def.variant(variant_index);
-                    let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant)
-                        .zip(subpatterns)
-                        .map(|((field, _ty), pattern)| FieldPat { field, pattern })
-                        .collect();
-
-                    if adt_def.is_enum() {
-                        PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns }
-                    } else {
-                        PatKind::Leaf { subpatterns }
-                    }
-                }
-                // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
-                // be careful to reconstruct the correct constant pattern here. However a string
-                // literal pattern will never be reported as a non-exhaustiveness witness, so we
-                // ignore this issue.
-                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
-                _ => bug!("unexpected ctor for type {:?} {:?}", self.ctor, self.ty),
-            },
-            Slice(slice) => {
-                match slice.kind {
-                    FixedLen(_) => PatKind::Slice {
-                        prefix: subpatterns.collect(),
-                        slice: None,
-                        suffix: Box::new([]),
-                    },
-                    VarLen(prefix, _) => {
-                        let mut subpatterns = subpatterns.peekable();
-                        let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix).collect();
-                        if slice.array_len.is_some() {
-                            // Improves diagnostics a bit: if the type is a known-size array, instead
-                            // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
-                            // This is incorrect if the size is not known, since `[_, ..]` captures
-                            // arrays of lengths `>= 1` whereas `[..]` captures any length.
-                            while !prefix.is_empty() && is_wildcard(prefix.last().unwrap()) {
-                                prefix.pop();
-                            }
-                            while subpatterns.peek().is_some()
-                                && is_wildcard(subpatterns.peek().unwrap())
-                            {
-                                subpatterns.next();
-                            }
-                        }
-                        let suffix: Box<[_]> = subpatterns.collect();
-                        let wild = Pat::wildcard_from_ty(self.ty);
-                        PatKind::Slice {
-                            prefix: prefix.into_boxed_slice(),
-                            slice: Some(Box::new(wild)),
-                            suffix,
-                        }
-                    }
-                }
-            }
-            &Str(value) => PatKind::Constant { value },
-            IntRange(range) => return range.to_pat(cx.tcx, self.ty),
-            Wildcard | NonExhaustive | Hidden => PatKind::Wild,
-            Missing { .. } => bug!(
-                "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
-                `Missing` should have been processed in `apply_constructors`"
-            ),
-            F32Range(..) | F64Range(..) | Opaque | Or => {
-                bug!("can't convert to pattern: {:?}", self)
-            }
-        };
-
-        Pat { ty: self.ty, span: DUMMY_SP, kind }
-    }
-
     pub(super) fn is_or_pat(&self) -> bool {
         matches!(self.ctor, Or)
     }
+    pub(super) fn flatten_or_pat(&'p self) -> SmallVec<[&'p Self; 1]> {
+        if self.is_or_pat() {
+            self.iter_fields().flat_map(|p| p.flatten_or_pat()).collect()
+        } else {
+            smallvec![self]
+        }
+    }
 
     pub(super) fn ctor(&self) -> &Constructor<'tcx> {
         &self.ctor
@@ -1804,3 +1692,131 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
         }
     }
 }
+
+/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
+/// purposes. As such they don't use interning and can be cloned.
+#[derive(Debug, Clone)]
+pub(crate) struct WitnessPat<'tcx> {
+    ctor: Constructor<'tcx>,
+    pub(crate) fields: Vec<WitnessPat<'tcx>>,
+    ty: Ty<'tcx>,
+}
+
+impl<'tcx> WitnessPat<'tcx> {
+    pub(super) fn new(ctor: Constructor<'tcx>, fields: Vec<Self>, ty: Ty<'tcx>) -> Self {
+        Self { ctor, fields, ty }
+    }
+    pub(super) fn wildcard(ty: Ty<'tcx>) -> Self {
+        Self::new(Wildcard, Vec::new(), ty)
+    }
+
+    /// Construct a pattern that matches everything that starts with this constructor.
+    /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
+    /// `Some(_)`.
+    pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, '_, 'tcx>, ctor: Constructor<'tcx>) -> Self {
+        // Reuse `Fields::wildcards` to get the types.
+        let fields = Fields::wildcards(pcx, &ctor)
+            .iter_patterns()
+            .map(|deco_pat| Self::wildcard(deco_pat.ty()))
+            .collect();
+        Self::new(ctor, fields, pcx.ty)
+    }
+
+    pub(super) fn ctor(&self) -> &Constructor<'tcx> {
+        &self.ctor
+    }
+    pub(super) fn ty(&self) -> Ty<'tcx> {
+        self.ty
+    }
+
+    pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'_, 'tcx>) -> Pat<'tcx> {
+        let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild);
+        let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx)));
+        let kind = match &self.ctor {
+            Single | Variant(_) => match self.ty.kind() {
+                ty::Tuple(..) => PatKind::Leaf {
+                    subpatterns: subpatterns
+                        .enumerate()
+                        .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
+                        .collect(),
+                },
+                ty::Adt(adt_def, _) if adt_def.is_box() => {
+                    // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
+                    // of `std`). So this branch is only reachable when the feature is enabled and
+                    // the pattern is a box pattern.
+                    PatKind::Deref { subpattern: subpatterns.next().unwrap() }
+                }
+                ty::Adt(adt_def, args) => {
+                    let variant_index = self.ctor.variant_index_for_adt(*adt_def);
+                    let variant = &adt_def.variant(variant_index);
+                    let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant)
+                        .zip(subpatterns)
+                        .map(|((field, _ty), pattern)| FieldPat { field, pattern })
+                        .collect();
+
+                    if adt_def.is_enum() {
+                        PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns }
+                    } else {
+                        PatKind::Leaf { subpatterns }
+                    }
+                }
+                // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
+                // be careful to reconstruct the correct constant pattern here. However a string
+                // literal pattern will never be reported as a non-exhaustiveness witness, so we
+                // ignore this issue.
+                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
+                _ => bug!("unexpected ctor for type {:?} {:?}", self.ctor, self.ty),
+            },
+            Slice(slice) => {
+                match slice.kind {
+                    FixedLen(_) => PatKind::Slice {
+                        prefix: subpatterns.collect(),
+                        slice: None,
+                        suffix: Box::new([]),
+                    },
+                    VarLen(prefix, _) => {
+                        let mut subpatterns = subpatterns.peekable();
+                        let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix).collect();
+                        if slice.array_len.is_some() {
+                            // Improves diagnostics a bit: if the type is a known-size array, instead
+                            // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
+                            // This is incorrect if the size is not known, since `[_, ..]` captures
+                            // arrays of lengths `>= 1` whereas `[..]` captures any length.
+                            while !prefix.is_empty() && is_wildcard(prefix.last().unwrap()) {
+                                prefix.pop();
+                            }
+                            while subpatterns.peek().is_some()
+                                && is_wildcard(subpatterns.peek().unwrap())
+                            {
+                                subpatterns.next();
+                            }
+                        }
+                        let suffix: Box<[_]> = subpatterns.collect();
+                        let wild = Pat::wildcard_from_ty(self.ty);
+                        PatKind::Slice {
+                            prefix: prefix.into_boxed_slice(),
+                            slice: Some(Box::new(wild)),
+                            suffix,
+                        }
+                    }
+                }
+            }
+            &Str(value) => PatKind::Constant { value },
+            IntRange(range) => return range.to_pat(cx.tcx, self.ty),
+            Wildcard | NonExhaustive | Hidden => PatKind::Wild,
+            Missing { .. } => bug!(
+                "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
+                `Missing` should have been processed in `apply_constructors`"
+            ),
+            F32Range(..) | F64Range(..) | Opaque | Or => {
+                bug!("can't convert to pattern: {:?}", self)
+            }
+        };
+
+        Pat { ty: self.ty, span: DUMMY_SP, kind }
+    }
+
+    pub(super) fn iter_fields<'a>(&'a self) -> impl Iterator<Item = &'a WitnessPat<'tcx>> {
+        self.fields.iter()
+    }
+}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 6cd73c7eaa9..a8cee5a61ed 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -213,7 +213,7 @@
 //! or-patterns in the first column are expanded before being stored in the matrix. Specialization
 //! for a single patstack is done from a combination of [`Constructor::is_covered_by`] and
 //! [`PatStack::pop_head_constructor`]. The internals of how it's done mostly live in the
-//! [`Fields`] struct.
+//! [`super::deconstruct_pat::Fields`] struct.
 //!
 //!
 //! # Computing usefulness
@@ -307,7 +307,7 @@
 
 use self::ArmType::*;
 use self::Usefulness::*;
-use super::deconstruct_pat::{Constructor, ConstructorSet, DeconstructedPat, Fields};
+use super::deconstruct_pat::{Constructor, ConstructorSet, DeconstructedPat, WitnessPat};
 use crate::errors::{NonExhaustiveOmittedPattern, Uncovered};
 
 use rustc_data_structures::captures::Captures;
@@ -322,7 +322,6 @@ use rustc_span::{Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
 use std::fmt;
-use std::iter::once;
 
 pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
     pub(crate) tcx: TyCtxt<'tcx>,
@@ -555,20 +554,20 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> {
 /// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of
 /// witnesses of non-exhaustiveness when there are any.
 /// Which variant to use is dictated by `ArmType`.
-#[derive(Debug)]
-enum Usefulness<'p, 'tcx> {
+#[derive(Debug, Clone)]
+enum Usefulness<'tcx> {
     /// If we don't care about witnesses, simply remember if the pattern was useful.
     NoWitnesses { useful: bool },
     /// Carries a list of witnesses of non-exhaustiveness. If empty, indicates that the whole
     /// pattern is unreachable.
-    WithWitnesses(Vec<Witness<'p, 'tcx>>),
+    WithWitnesses(Vec<WitnessStack<'tcx>>),
 }
 
-impl<'p, 'tcx> Usefulness<'p, 'tcx> {
+impl<'tcx> Usefulness<'tcx> {
     fn new_useful(preference: ArmType) -> Self {
         match preference {
             // A single (empty) witness of reachability.
-            FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]),
+            FakeExtraWildcard => WithWitnesses(vec![WitnessStack(vec![])]),
             RealArm => NoWitnesses { useful: true },
         }
     }
@@ -605,8 +604,8 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
     /// with the results of specializing with the other constructors.
     fn apply_constructor(
         self,
-        pcx: &PatCtxt<'_, 'p, 'tcx>,
-        matrix: &Matrix<'p, 'tcx>, // used to compute missing ctors
+        pcx: &PatCtxt<'_, '_, 'tcx>,
+        matrix: &Matrix<'_, 'tcx>, // used to compute missing ctors
         ctor: &Constructor<'tcx>,
     ) -> Self {
         match self {
@@ -627,25 +626,18 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
                     // wildcards for fields, i.e. that matches everything that can be built with it.
                     // For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get
                     // the pattern `Some(_)`.
-                    let new_patterns: Vec<DeconstructedPat<'_, '_>> = missing
+                    let new_patterns: Vec<WitnessPat<'_>> = missing
                         .into_iter()
-                        .map(|missing_ctor| {
-                            DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone())
-                        })
+                        .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor.clone()))
                         .collect();
 
                     witnesses
                         .into_iter()
                         .flat_map(|witness| {
                             new_patterns.iter().map(move |pat| {
-                                Witness(
-                                    witness
-                                        .0
-                                        .iter()
-                                        .chain(once(pat))
-                                        .map(DeconstructedPat::clone_and_forget_reachability)
-                                        .collect(),
-                                )
+                                let mut stack = witness.clone();
+                                stack.0.push(pat.clone());
+                                stack
                             })
                         })
                         .collect()
@@ -667,15 +659,17 @@ enum ArmType {
     RealArm,
 }
 
-/// A witness of non-exhaustiveness for error reporting, represented
-/// as a list of patterns (in reverse order of construction) with
-/// wildcards inside to represent elements that can take any inhabitant
-/// of the type as a value.
+/// A witness-tuple of non-exhaustiveness for error reporting, represented as a list of patterns (in
+/// reverse order of construction) with wildcards inside to represent elements that can take any
+/// inhabitant of the type as a value.
 ///
-/// A witness against a list of patterns should have the same types
-/// and length as the pattern matched against. Because Rust `match`
-/// is always against a single pattern, at the end the witness will
-/// have length 1, but in the middle of the algorithm, it can contain
+/// This mirrors `PatStack`: they function similarly, except `PatStack` contains user patterns we
+/// are inspecting, and `WitnessStack` contains witnesses we are constructing.
+/// FIXME(Nadrieril): use the same order of patterns for both
+///
+/// A `WitnessStack` should have the same types and length as the `PatStacks` we are inspecting
+/// (except we store the patterns in reverse order). Because Rust `match` is always against a single
+/// pattern, at the end the stack will have length 1. In the middle of the algorithm, it can contain
 /// multiple patterns.
 ///
 /// For example, if we are constructing a witness for the match against
@@ -690,23 +684,37 @@ enum ArmType {
 /// # }
 /// ```
 ///
-/// We'll perform the following steps:
-/// 1. Start with an empty witness
-///     `Witness(vec![])`
-/// 2. Push a witness `true` against the `false`
-///     `Witness(vec![true])`
-/// 3. Push a witness `Some(_)` against the `None`
-///     `Witness(vec![true, Some(_)])`
-/// 4. Apply the `Pair` constructor to the witnesses
-///     `Witness(vec![Pair(Some(_), true)])`
+/// We'll perform the following steps (among others):
+/// - Start with a matrix representing the match
+///     `PatStack(vec![Pair(None, _)])`
+///     `PatStack(vec![Pair(_, false)])`
+/// - Specialize with `Pair`
+///     `PatStack(vec![None, _])`
+///     `PatStack(vec![_, false])`
+/// - Specialize with `Some`
+///     `PatStack(vec![_, false])`
+/// - Specialize with `_`
+///     `PatStack(vec![false])`
+/// - Specialize with `true`
+///     // no patstacks left
+/// - This is a non-exhaustive match: we have the empty witness stack as a witness.
+///     `WitnessStack(vec![])`
+/// - Apply `true`
+///     `WitnessStack(vec![true])`
+/// - Apply `_`
+///     `WitnessStack(vec![true, _])`
+/// - Apply `Some`
+///     `WitnessStack(vec![true, Some(_)])`
+/// - Apply `Pair`
+///     `WitnessStack(vec![Pair(Some(_), true)])`
 ///
 /// The final `Pair(Some(_), true)` is then the resulting witness.
-#[derive(Debug)]
-pub(crate) struct Witness<'p, 'tcx>(Vec<DeconstructedPat<'p, 'tcx>>);
+#[derive(Debug, Clone)]
+pub(crate) struct WitnessStack<'tcx>(Vec<WitnessPat<'tcx>>);
 
-impl<'p, 'tcx> Witness<'p, 'tcx> {
+impl<'tcx> WitnessStack<'tcx> {
     /// Asserts that the witness contains a single pattern, and returns it.
-    fn single_pattern(self) -> DeconstructedPat<'p, 'tcx> {
+    fn single_pattern(self) -> WitnessPat<'tcx> {
         assert_eq!(self.0.len(), 1);
         self.0.into_iter().next().unwrap()
     }
@@ -724,13 +732,12 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
     ///
     /// left_ty: struct X { a: (bool, &'static str), b: usize}
     /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
-    fn apply_constructor(mut self, pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Self {
+    fn apply_constructor(mut self, pcx: &PatCtxt<'_, '_, 'tcx>, ctor: &Constructor<'tcx>) -> Self {
         let pat = {
             let len = self.0.len();
             let arity = ctor.arity(pcx);
-            let pats = self.0.drain((len - arity)..).rev();
-            let fields = Fields::from_iter(pcx.cx, pats);
-            DeconstructedPat::new(ctor.clone(), fields, pcx.ty, pcx.span)
+            let fields = self.0.drain((len - arity)..).rev().collect();
+            WitnessPat::new(ctor.clone(), fields, pcx.ty)
         };
 
         self.0.push(pat);
@@ -770,7 +777,7 @@ fn is_useful<'p, 'tcx>(
     lint_root: HirId,
     is_under_guard: bool,
     is_top_level: bool,
-) -> Usefulness<'p, 'tcx> {
+) -> Usefulness<'tcx> {
     debug!(?matrix, ?v);
     let Matrix { patterns: rows, .. } = matrix;
 
@@ -837,8 +844,6 @@ fn is_useful<'p, 'tcx>(
         }
         // We split the head constructor of `v`.
         let split_ctors = v_ctor.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
-        let is_non_exhaustive_and_wild =
-            cx.is_foreign_non_exhaustive_enum(ty) && v_ctor.is_wildcard();
         // For each constructor, we compute whether there's a value that starts with it that would
         // witness the usefulness of `v`.
         let start_matrix = &matrix;
@@ -859,50 +864,6 @@ fn is_useful<'p, 'tcx>(
                 )
             });
             let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor);
-
-            // When all the conditions are met we have a match with a `non_exhaustive` enum
-            // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
-            // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
-            if is_non_exhaustive_and_wild
-                // Only emit a lint on refutable patterns.
-                && cx.refutable
-                // We check that the match has a wildcard pattern and that wildcard is useful,
-                // meaning there are variants that are covered by the wildcard. Without the check
-                // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
-                && usefulness.is_useful() && matches!(witness_preference, RealArm)
-                && matches!(
-                    &ctor,
-                    Constructor::Missing { nonexhaustive_enum_missing_visible_variants: true }
-                )
-            {
-                let missing = ConstructorSet::for_ty(pcx.cx, pcx.ty)
-                    .compute_missing(pcx, matrix.heads().map(DeconstructedPat::ctor));
-                // Construct for each missing constructor a "wild" version of this constructor, that
-                // matches everything that can be built with it. For example, if `ctor` is a
-                // `Constructor::Variant` for `Option::Some`, we get the pattern `Some(_)`.
-                let patterns = missing
-                    .into_iter()
-                    // Because of how we computed `nonexhaustive_enum_missing_visible_variants`,
-                    // this will not return an empty `Vec`.
-                    .filter(|c| !(matches!(c, Constructor::NonExhaustive | Constructor::Hidden)))
-                    .map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor))
-                    .collect::<Vec<_>>();
-
-                // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
-                // is not exhaustive enough.
-                //
-                // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
-                cx.tcx.emit_spanned_lint(
-                    NON_EXHAUSTIVE_OMITTED_PATTERNS,
-                    lint_root,
-                    pcx.span,
-                    NonExhaustiveOmittedPattern {
-                        scrut_ty: pcx.ty,
-                        uncovered: Uncovered::new(pcx.span, pcx.cx, patterns),
-                    },
-                );
-            }
-
             ret.extend(usefulness);
         }
     }
@@ -914,6 +875,80 @@ fn is_useful<'p, 'tcx>(
     ret
 }
 
+/// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned
+/// in a given column. This traverses patterns column-by-column, where a column is the intuitive
+/// notion of "subpatterns that inspect the same subvalue".
+/// Despite similarities with `is_useful`, this traversal is different. Notably this is linear in the
+/// depth of patterns, whereas `is_useful` is worst-case exponential (exhaustiveness is NP-complete).
+fn collect_nonexhaustive_missing_variants<'p, 'tcx>(
+    cx: &MatchCheckCtxt<'p, 'tcx>,
+    column: &[&DeconstructedPat<'p, 'tcx>],
+) -> Vec<WitnessPat<'tcx>> {
+    let ty = column[0].ty();
+    let pcx = &PatCtxt { cx, ty, span: DUMMY_SP, is_top_level: false };
+
+    let set = ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, column.iter().map(|p| p.ctor()));
+    if set.present.is_empty() {
+        // We can't consistently handle the case where no constructors are present (since this would
+        // require digging deep through any type in case there's a non_exhaustive enum somewhere),
+        // so for consistency we refuse to handle the top-level case, where we could handle it.
+        return vec![];
+    }
+
+    let mut witnesses = Vec::new();
+    if cx.is_foreign_non_exhaustive_enum(ty) {
+        witnesses.extend(
+            set.missing
+                .into_iter()
+                // This will list missing visible variants.
+                .filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
+                .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)),
+        )
+    }
+
+    // Recurse into the fields.
+    for ctor in set.present {
+        let arity = ctor.arity(pcx);
+        if arity == 0 {
+            continue;
+        }
+
+        // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These
+        // columns may have different lengths in the presence of or-patterns (this is why we can't
+        // reuse `Matrix`).
+        let mut specialized_columns: Vec<Vec<_>> = (0..arity).map(|_| Vec::new()).collect();
+        let relevant_patterns = column.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()));
+        for pat in relevant_patterns {
+            let specialized = pat.specialize(pcx, &ctor);
+            for (subpat, sub_column) in specialized.iter().zip(&mut specialized_columns) {
+                if subpat.is_or_pat() {
+                    sub_column.extend(subpat.iter_fields())
+                } else {
+                    sub_column.push(subpat)
+                }
+            }
+        }
+        debug_assert!(
+            !specialized_columns[0].is_empty(),
+            "ctor {ctor:?} was listed as present but isn't"
+        );
+
+        let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor);
+        for (i, col_i) in specialized_columns.iter().enumerate() {
+            // Compute witnesses for each column.
+            let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i.as_slice());
+            // For each witness, we build a new pattern in the shape of `ctor(_, _, wit, _, _)`,
+            // adding enough wildcards to match `arity`.
+            for wit in wits_for_col_i {
+                let mut pat = wild_pat.clone();
+                pat.fields[i] = wit;
+                witnesses.push(pat);
+            }
+        }
+    }
+    witnesses
+}
+
 /// The arm of a match expression.
 #[derive(Clone, Copy, Debug)]
 pub(crate) struct MatchArm<'p, 'tcx> {
@@ -940,7 +975,7 @@ pub(crate) struct UsefulnessReport<'p, 'tcx> {
     pub(crate) arm_usefulness: Vec<(MatchArm<'p, 'tcx>, Reachability)>,
     /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
     /// exhaustiveness.
-    pub(crate) non_exhaustiveness_witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
+    pub(crate) non_exhaustiveness_witnesses: Vec<WitnessPat<'tcx>>,
 }
 
 /// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which
@@ -954,6 +989,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
     arms: &[MatchArm<'p, 'tcx>],
     lint_root: HirId,
     scrut_ty: Ty<'tcx>,
+    scrut_span: Span,
 ) -> UsefulnessReport<'p, 'tcx> {
     let mut matrix = Matrix::empty();
     let arm_usefulness: Vec<_> = arms
@@ -978,9 +1014,39 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
     let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP));
     let v = PatStack::from_pattern(wild_pattern);
     let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, lint_root, false, true);
-    let non_exhaustiveness_witnesses = match usefulness {
+    let non_exhaustiveness_witnesses: Vec<_> = match usefulness {
         WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
         NoWitnesses { .. } => bug!(),
     };
+
+    // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
+    // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
+    if cx.refutable
+        && non_exhaustiveness_witnesses.is_empty()
+        && !matches!(
+            cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0,
+            rustc_session::lint::Level::Allow
+        )
+    {
+        let pat_column = arms.iter().flat_map(|arm| arm.pat.flatten_or_pat()).collect::<Vec<_>>();
+        let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
+
+        if !witnesses.is_empty() {
+            // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+            // is not exhaustive enough.
+            //
+            // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
+            cx.tcx.emit_spanned_lint(
+                NON_EXHAUSTIVE_OMITTED_PATTERNS,
+                lint_root,
+                scrut_span,
+                NonExhaustiveOmittedPattern {
+                    scrut_ty,
+                    uncovered: Uncovered::new(scrut_span, cx, witnesses),
+                },
+            );
+        }
+    }
+
     UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
 }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index c9991e499b3..25ba67a63ec 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -860,13 +860,13 @@ where
         let ty = self.place_ty(self.place);
         match ty.kind() {
             ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()),
-            // Note that `elaborate_drops` only drops the upvars of a generator,
+            // Note that `elaborate_drops` only drops the upvars of a coroutine,
             // and this is ok because `open_drop` here can only be reached
-            // within that own generator's resume function.
+            // within that own coroutine's resume function.
             // This should only happen for the self argument on the resume function.
-            // It effectively only contains upvars until the generator transformation runs.
-            // See librustc_body/transform/generator.rs for more details.
-            ty::Generator(_, args, _) => self.open_drop_for_tuple(&args.as_generator().upvar_tys()),
+            // It effectively only contains upvars until the coroutine transformation runs.
+            // See librustc_body/transform/coroutine.rs for more details.
+            ty::Coroutine(_, args, _) => self.open_drop_for_tuple(&args.as_coroutine().upvar_tys()),
             ty::Tuple(fields) => self.open_drop_for_tuple(fields),
             ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
             ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index bdddaaebca4..c12ccba1e5c 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -267,7 +267,7 @@ where
 
             mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
                 self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
-                    let state_on_generator_drop = this.results.get().clone();
+                    let state_on_coroutine_drop = this.results.get().clone();
                     this.results.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
@@ -283,7 +283,7 @@ where
                         fmt = fmt,
                         diff = diff_pretty(
                             this.results.get(),
-                            &state_on_generator_drop,
+                            &state_on_coroutine_drop,
                             this.results.analysis()
                         ),
                     )
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index ce30c642fcc..b785a999f08 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -114,7 +114,7 @@ pub trait AnalysisDomain<'tcx> {
     //
     // FIXME: For backward dataflow analyses, the initial state should be applied to every basic
     // block where control flow could exit the MIR body (e.g., those terminated with `return` or
-    // `resume`). It's not obvious how to handle `yield` points in generators, however.
+    // `resume`). It's not obvious how to handle `yield` points in coroutines, however.
     fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain);
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 3ad9d3d4264..1e8e09ac333 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -9,7 +9,7 @@ use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
 ///
 /// At present, this is used as a very limited form of alias analysis. For example,
 /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for
-/// immovable generators.
+/// immovable coroutines.
 #[derive(Clone, Copy)]
 pub struct MaybeBorrowedLocals;
 
@@ -136,7 +136,7 @@ where
             | TerminatorKind::Call { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Goto { .. }
             | TerminatorKind::InlineAsm { .. }
             | TerminatorKind::UnwindResume
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index e6d383d626a..182f2590137 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -763,9 +763,9 @@ fn switch_on_enum_discriminant<'mir, 'tcx>(
                     ty::Adt(def, _) => return Some((*discriminated, *def)),
 
                     // `Rvalue::Discriminant` is also used to get the active yield point for a
-                    // generator, but we do not need edge-specific effects in that case. This may
+                    // coroutine, but we do not need edge-specific effects in that case. This may
                     // change in the future.
-                    ty::Generator(..) => return None,
+                    ty::Coroutine(..) => return None,
 
                     t => bug!("`discriminant` called on unexpected type {:?}", t),
                 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 5aa73c7a906..c1152e88cd0 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -98,7 +98,7 @@ where
 {
     fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
         if let PlaceContext::MutatingUse(MutatingUseContext::Yield) = context {
-            // The resume place is evaluated and assigned to only after generator resumes, so its
+            // The resume place is evaluated and assigned to only after coroutine resumes, so its
             // effect is handled separately in `call_resume_effect`.
             return;
         }
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 94d6eb67d49..5a58e3af8be 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -268,7 +268,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
 
             // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
             // that is that a `yield` will return from the function, and `resume_arg` is written
-            // only when the generator is later resumed. Unlike `Call`, this doesn't require the
+            // only when the coroutine is later resumed. Unlike `Call`, this doesn't require the
             // place to have storage *before* the yield, only after.
             TerminatorKind::Yield { .. } => {}
 
@@ -296,7 +296,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Goto { .. }
             | TerminatorKind::UnwindResume
             | TerminatorKind::Return
@@ -333,7 +333,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Goto { .. }
             | TerminatorKind::UnwindResume
             | TerminatorKind::Return
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 7a5b3585d59..91a96593173 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -143,8 +143,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                     | ty::FnPtr(_)
                     | ty::Dynamic(_, _, _)
                     | ty::Closure(_, _)
-                    | ty::Generator(_, _, _)
-                    | ty::GeneratorWitness(..)
+                    | ty::Coroutine(_, _, _)
+                    | ty::CoroutineWitness(..)
                     | ty::Never
                     | ty::Tuple(_)
                     | ty::Alias(_, _)
@@ -168,7 +168,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                             union_path.get_or_insert(base);
                         }
                     }
-                    ty::Closure(_, _) | ty::Generator(_, _, _) | ty::Tuple(_) => (),
+                    ty::Closure(_, _) | ty::Coroutine(_, _, _) | ty::Tuple(_) => (),
                     ty::Bool
                     | ty::Char
                     | ty::Int(_)
@@ -183,7 +183,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                     | ty::FnDef(_, _)
                     | ty::FnPtr(_)
                     | ty::Dynamic(_, _, _)
-                    | ty::GeneratorWitness(..)
+                    | ty::CoroutineWitness(..)
                     | ty::Never
                     | ty::Alias(_, _)
                     | ty::Param(_)
@@ -454,7 +454,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             | TerminatorKind::Return
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. } => {}
 
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 44bbb8374dc..04108aeedf6 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -274,7 +274,7 @@ pub trait ValueAnalysis<'tcx> {
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Assert { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
                 // These terminators have no effect on the analysis.
@@ -915,7 +915,7 @@ impl Map {
     ) {
         for sibling in self.children(parent) {
             let elem = self.places[sibling].proj_elem;
-            // Only invalidate variants and discriminant. Fields (for generators) are not
+            // Only invalidate variants and discriminant. Fields (for coroutines) are not
             // invalidated by assignment to a variant.
             if let Some(TrackElem::Variant(..) | TrackElem::Discriminant) = elem
                 // Only invalidate the other variants, the current one is fine.
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 74243f1f8f2..2b3d423ea61 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -40,7 +40,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
         let body_abi = match body_ty.kind() {
             ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
             ty::Closure(..) => Abi::RustCall,
-            ty::Generator(..) => Abi::Rust,
+            ty::Coroutine(..) => Abi::Rust,
             _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
         };
         let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi);
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 7e4731f5d8a..8872f9a97d7 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -56,7 +56,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | TerminatorKind::Drop { .. }
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Assert { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
@@ -128,7 +128,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
                         ),
                     }
                 }
-                &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
+                &AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _, _) => {
                     let def_id = def_id.expect_local();
                     let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
                         self.tcx.unsafety_check_result(def_id);
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 3450a0f3686..53c0d0dea29 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -82,11 +82,11 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return;
         }
 
-        // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
+        // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles
         // computing their layout.
-        let is_generator = def_kind == DefKind::Generator;
-        if is_generator {
-            trace!("ConstProp skipped for generator {:?}", def_id);
+        let is_coroutine = def_kind == DefKind::Coroutine;
+        if is_coroutine {
+            trace!("ConstProp skipped for coroutine {:?}", def_id);
             return;
         }
 
@@ -512,7 +512,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<Const<'tcx>> {
         // This will return None if the above `const_prop` invocation only "wrote" a
-        // type whose creation requires no write. E.g. a generator whose initial state
+        // type whose creation requires no write. E.g. a coroutine whose initial state
         // consists solely of uninitialized memory (so it doesn't capture any locals).
         let value = self.get_const(place)?;
         if !self.tcx.consider_optimizing(|| format!("ConstantPropagation - {value:?}")) {
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index aad513d7355..a23ba9c4aa9 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -59,10 +59,10 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint {
             return;
         }
 
-        // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
+        // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles
         // computing their layout.
-        if let DefKind::Generator = def_kind {
-            trace!("ConstPropLint skipped for generator {:?}", def_id);
+        if let DefKind::Coroutine = def_kind {
+            trace!("ConstPropLint skipped for coroutine {:?}", def_id);
             return;
         }
 
@@ -648,7 +648,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
             | TerminatorKind::Yield { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Call { .. }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index a6693519e54..fa56d59dd80 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1,53 +1,53 @@
-//! This is the implementation of the pass which transforms generators into state machines.
+//! This is the implementation of the pass which transforms coroutines into state machines.
 //!
-//! MIR generation for generators creates a function which has a self argument which
-//! passes by value. This argument is effectively a generator type which only contains upvars and
-//! is only used for this argument inside the MIR for the generator.
+//! MIR generation for coroutines creates a function which has a self argument which
+//! passes by value. This argument is effectively a coroutine type which only contains upvars and
+//! is only used for this argument inside the MIR for the coroutine.
 //! It is passed by value to enable upvars to be moved out of it. Drop elaboration runs on that
 //! MIR before this pass and creates drop flags for MIR locals.
-//! It will also drop the generator argument (which only consists of upvars) if any of the upvars
-//! are moved out of. This pass elaborates the drops of upvars / generator argument in the case
+//! It will also drop the coroutine argument (which only consists of upvars) if any of the upvars
+//! are moved out of. This pass elaborates the drops of upvars / coroutine argument in the case
 //! that none of the upvars were moved out of. This is because we cannot have any drops of this
-//! generator in the MIR, since it is used to create the drop glue for the generator. We'd get
+//! coroutine in the MIR, since it is used to create the drop glue for the coroutine. We'd get
 //! infinite recursion otherwise.
 //!
-//! This pass creates the implementation for either the `Generator::resume` or `Future::poll`
-//! function and the drop shim for the generator based on the MIR input.
-//! It converts the generator argument from Self to &mut Self adding derefs in the MIR as needed.
-//! It computes the final layout of the generator struct which looks like this:
+//! This pass creates the implementation for either the `Coroutine::resume` or `Future::poll`
+//! function and the drop shim for the coroutine based on the MIR input.
+//! It converts the coroutine argument from Self to &mut Self adding derefs in the MIR as needed.
+//! It computes the final layout of the coroutine struct which looks like this:
 //!     First upvars are stored
-//!     It is followed by the generator state field.
+//!     It is followed by the coroutine state field.
 //!     Then finally the MIR locals which are live across a suspension point are stored.
 //!     ```ignore (illustrative)
-//!     struct Generator {
+//!     struct Coroutine {
 //!         upvars...,
 //!         state: u32,
 //!         mir_locals...,
 //!     }
 //!     ```
 //! This pass computes the meaning of the state field and the MIR locals which are live
-//! across a suspension point. There are however three hardcoded generator states:
-//!     0 - Generator have not been resumed yet
-//!     1 - Generator has returned / is completed
-//!     2 - Generator has been poisoned
+//! across a suspension point. There are however three hardcoded coroutine states:
+//!     0 - Coroutine have not been resumed yet
+//!     1 - Coroutine has returned / is completed
+//!     2 - Coroutine has been poisoned
 //!
-//! It also rewrites `return x` and `yield y` as setting a new generator state and returning
-//! `GeneratorState::Complete(x)` and `GeneratorState::Yielded(y)`,
+//! It also rewrites `return x` and `yield y` as setting a new coroutine state and returning
+//! `CoroutineState::Complete(x)` and `CoroutineState::Yielded(y)`,
 //! or `Poll::Ready(x)` and `Poll::Pending` respectively.
-//! MIR locals which are live across a suspension point are moved to the generator struct
-//! with references to them being updated with references to the generator struct.
+//! MIR locals which are live across a suspension point are moved to the coroutine struct
+//! with references to them being updated with references to the coroutine struct.
 //!
-//! The pass creates two functions which have a switch on the generator state giving
+//! The pass creates two functions which have a switch on the coroutine state giving
 //! the action to take.
 //!
-//! One of them is the implementation of `Generator::resume` / `Future::poll`.
-//! For generators with state 0 (unresumed) it starts the execution of the generator.
-//! For generators with state 1 (returned) and state 2 (poisoned) it panics.
+//! One of them is the implementation of `Coroutine::resume` / `Future::poll`.
+//! For coroutines with state 0 (unresumed) it starts the execution of the coroutine.
+//! For coroutines with state 1 (returned) and state 2 (poisoned) it panics.
 //! Otherwise it continues the execution from the last suspension point.
 //!
-//! The other function is the drop glue for the generator.
-//! For generators with state 0 (unresumed) it drops the upvars of the generator.
-//! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
+//! The other function is the drop glue for the coroutine.
+//! For coroutines with state 0 (unresumed) it drops the upvars of the coroutine.
+//! For coroutines with state 1 (returned) and state 2 (poisoned) it does nothing.
 //! Otherwise it drops all the values in scope at the last suspension point.
 
 use crate::abort_unwinding_calls;
@@ -60,7 +60,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::pluralize;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::GeneratorKind;
+use rustc_hir::CoroutineKind;
 use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
@@ -68,7 +68,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::InstanceDef;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
-use rustc_middle::ty::{GeneratorArgs, GenericArgsRef};
+use rustc_middle::ty::{CoroutineArgs, GenericArgsRef};
 use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
 };
@@ -196,19 +196,19 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
 
 const SELF_ARG: Local = Local::from_u32(1);
 
-/// Generator has not been resumed yet.
-const UNRESUMED: usize = GeneratorArgs::UNRESUMED;
-/// Generator has returned / is completed.
-const RETURNED: usize = GeneratorArgs::RETURNED;
-/// Generator has panicked and is poisoned.
-const POISONED: usize = GeneratorArgs::POISONED;
+/// Coroutine has not been resumed yet.
+const UNRESUMED: usize = CoroutineArgs::UNRESUMED;
+/// Coroutine has returned / is completed.
+const RETURNED: usize = CoroutineArgs::RETURNED;
+/// Coroutine has panicked and is poisoned.
+const POISONED: usize = CoroutineArgs::POISONED;
 
-/// Number of variants to reserve in generator state. Corresponds to
-/// `UNRESUMED` (beginning of a generator) and `RETURNED`/`POISONED`
-/// (end of a generator) states.
+/// Number of variants to reserve in coroutine state. Corresponds to
+/// `UNRESUMED` (beginning of a coroutine) and `RETURNED`/`POISONED`
+/// (end of a coroutine) states.
 const RESERVED_VARIANTS: usize = 3;
 
-/// A `yield` point in the generator.
+/// A `yield` point in the coroutine.
 struct SuspensionPoint<'tcx> {
     /// State discriminant used when suspending or resuming at this point.
     state: usize,
@@ -216,7 +216,7 @@ struct SuspensionPoint<'tcx> {
     resume: BasicBlock,
     /// Where to move the resume argument after resumption.
     resume_arg: Place<'tcx>,
-    /// Which block to jump to if the generator is dropped in this state.
+    /// Which block to jump to if the coroutine is dropped in this state.
     drop: Option<BasicBlock>,
     /// Set of locals that have live storage while at this suspension point.
     storage_liveness: GrowableBitSet<Local>,
@@ -228,10 +228,10 @@ struct TransformVisitor<'tcx> {
     state_adt_ref: AdtDef<'tcx>,
     state_args: GenericArgsRef<'tcx>,
 
-    // The type of the discriminant in the generator struct
+    // The type of the discriminant in the coroutine struct
     discr_ty: Ty<'tcx>,
 
-    // Mapping from Local to (type of local, generator struct index)
+    // Mapping from Local to (type of local, coroutine struct index)
     // FIXME(eddyb) This should use `IndexVec<Local, Option<_>>`.
     remap: FxHashMap<Local, (Ty<'tcx>, VariantIdx, FieldIdx)>,
 
@@ -249,9 +249,9 @@ struct TransformVisitor<'tcx> {
 }
 
 impl<'tcx> TransformVisitor<'tcx> {
-    // Make a `GeneratorState` or `Poll` variant assignment.
+    // Make a `CoroutineState` or `Poll` variant assignment.
     //
-    // `core::ops::GeneratorState` only has single element tuple variants,
+    // `core::ops::CoroutineState` only has single element tuple variants,
     // so we can just write to the downcasted first field and then set the
     // discriminant to the appropriate variant.
     fn make_state(
@@ -262,8 +262,8 @@ impl<'tcx> TransformVisitor<'tcx> {
         statements: &mut Vec<Statement<'tcx>>,
     ) {
         let idx = VariantIdx::new(match (is_return, self.is_async_kind) {
-            (true, false) => 1,  // GeneratorState::Complete
-            (false, false) => 0, // GeneratorState::Yielded
+            (true, false) => 1,  // CoroutineState::Complete
+            (false, false) => 0, // CoroutineState::Yielded
             (true, true) => 0,   // Poll::Ready
             (false, true) => 1,  // Poll::Pending
         });
@@ -285,7 +285,7 @@ impl<'tcx> TransformVisitor<'tcx> {
             return;
         }
 
-        // else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
+        // else: `Poll::Ready(x)`, `CoroutineState::Yielded(x)` or `CoroutineState::Complete(x)`
         assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
 
         statements.push(Statement {
@@ -297,7 +297,7 @@ impl<'tcx> TransformVisitor<'tcx> {
         });
     }
 
-    // Create a Place referencing a generator struct field
+    // Create a Place referencing a coroutine struct field
     fn make_field(&self, variant_index: VariantIdx, idx: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
         let self_place = Place::from(SELF_ARG);
         let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index);
@@ -349,7 +349,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
         _context: PlaceContext,
         _location: Location,
     ) {
-        // Replace an Local in the remap with a generator struct access
+        // Replace an Local in the remap with a coroutine struct access
         if let Some(&(ty, variant_index, idx)) = self.remap.get(&place.local) {
             replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
         }
@@ -413,7 +413,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
     }
 }
 
-fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let gen_ty = body.local_decls.raw[1].ty;
 
     let ref_gen_ty = Ty::new_ref(
@@ -422,14 +422,14 @@ fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo
         ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut },
     );
 
-    // Replace the by value generator argument
+    // Replace the by value coroutine argument
     body.local_decls.raw[1].ty = ref_gen_ty;
 
-    // Add a deref to accesses of the generator state
+    // Add a deref to accesses of the coroutine state
     DerefArgVisitor { tcx }.visit_body(body);
 }
 
-fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let ref_gen_ty = body.local_decls.raw[1].ty;
 
     let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span));
@@ -437,10 +437,10 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
     let args = tcx.mk_args(&[ref_gen_ty.into()]);
     let pin_ref_gen_ty = Ty::new_adt(tcx, pin_adt_ref, args);
 
-    // Replace the by ref generator argument
+    // Replace the by ref coroutine argument
     body.local_decls.raw[1].ty = pin_ref_gen_ty;
 
-    // Add the Pin field access to accesses of the generator state
+    // Add the Pin field access to accesses of the coroutine state
     PinArgVisitor { ref_gen_ty, tcx }.visit_body(body);
 }
 
@@ -465,7 +465,7 @@ fn replace_local<'tcx>(
     new_local
 }
 
-/// Transforms the `body` of the generator applying the following transforms:
+/// Transforms the `body` of the coroutine applying the following transforms:
 ///
 /// - Eliminates all the `get_context` calls that async lowering created.
 /// - Replace all `Local` `ResumeTy` types with `&mut Context<'_>` (`context_mut_ref`).
@@ -485,7 +485,7 @@ fn replace_local<'tcx>(
 ///
 /// The async lowering step and the type / lifetime inference / checking are
 /// still using the `ResumeTy` indirection for the time being, and that indirection
-/// is removed here. After this transform, the generator body only knows about `&mut Context<'_>`.
+/// is removed here. After this transform, the coroutine body only knows about `&mut Context<'_>`.
 fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let context_mut_ref = Ty::new_task_context(tcx);
 
@@ -565,10 +565,10 @@ fn replace_resume_ty_local<'tcx>(
 
 struct LivenessInfo {
     /// Which locals are live across any suspension point.
-    saved_locals: GeneratorSavedLocals,
+    saved_locals: CoroutineSavedLocals,
 
     /// The set of saved locals live at each suspension point.
-    live_locals_at_suspension_points: Vec<BitSet<GeneratorSavedLocal>>,
+    live_locals_at_suspension_points: Vec<BitSet<CoroutineSavedLocal>>,
 
     /// Parallel vec to the above with SourceInfo for each yield terminator.
     source_info_at_suspension_points: Vec<SourceInfo>,
@@ -576,7 +576,7 @@ struct LivenessInfo {
     /// For every saved local, the set of other saved locals that are
     /// storage-live at the same time as this local. We cannot overlap locals in
     /// the layout which have conflicting storage.
-    storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
+    storage_conflicts: BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
 
     /// For every suspending block, the locals which are storage-live across
     /// that suspension point.
@@ -601,7 +601,7 @@ fn locals_live_across_suspend_points<'tcx>(
     // Calculate the MIR locals which have been previously
     // borrowed (even if they are still active).
     let borrowed_locals_results =
-        MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("generator").iterate_to_fixpoint();
+        MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("coroutine").iterate_to_fixpoint();
 
     let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body_ref);
 
@@ -616,7 +616,7 @@ fn locals_live_across_suspend_points<'tcx>(
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness = MaybeLiveLocals
         .into_engine(tcx, body_ref)
-        .pass_name("generator")
+        .pass_name("coroutine")
         .iterate_to_fixpoint()
         .into_results_cursor(body_ref);
 
@@ -635,8 +635,8 @@ fn locals_live_across_suspend_points<'tcx>(
 
             if !movable {
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
-                // This is correct for movable generators since borrows cannot live across
-                // suspension points. However for immovable generators we need to account for
+                // This is correct for movable coroutines since borrows cannot live across
+                // suspension points. However for immovable coroutines we need to account for
                 // borrows, so we conservatively assume that all borrowed locals are live until
                 // we find a StorageDead statement referencing the locals.
                 // To do this we just union our `liveness` result with `borrowed_locals`, which
@@ -659,7 +659,7 @@ fn locals_live_across_suspend_points<'tcx>(
             requires_storage_cursor.seek_before_primary_effect(loc);
             live_locals.intersect(requires_storage_cursor.get());
 
-            // The generator argument is ignored.
+            // The coroutine argument is ignored.
             live_locals.remove(SELF_ARG);
 
             debug!("loc = {:?}, live_locals = {:?}", loc, live_locals);
@@ -674,7 +674,7 @@ fn locals_live_across_suspend_points<'tcx>(
     }
 
     debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point);
-    let saved_locals = GeneratorSavedLocals(live_locals_at_any_suspension_point);
+    let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point);
 
     // Renumber our liveness_map bitsets to include only the locals we are
     // saving.
@@ -701,21 +701,21 @@ fn locals_live_across_suspend_points<'tcx>(
 
 /// The set of `Local`s that must be saved across yield points.
 ///
-/// `GeneratorSavedLocal` is indexed in terms of the elements in this set;
-/// i.e. `GeneratorSavedLocal::new(1)` corresponds to the second local
+/// `CoroutineSavedLocal` is indexed in terms of the elements in this set;
+/// i.e. `CoroutineSavedLocal::new(1)` corresponds to the second local
 /// included in this set.
-struct GeneratorSavedLocals(BitSet<Local>);
+struct CoroutineSavedLocals(BitSet<Local>);
 
-impl GeneratorSavedLocals {
-    /// Returns an iterator over each `GeneratorSavedLocal` along with the `Local` it corresponds
+impl CoroutineSavedLocals {
+    /// Returns an iterator over each `CoroutineSavedLocal` along with the `Local` it corresponds
     /// to.
-    fn iter_enumerated(&self) -> impl '_ + Iterator<Item = (GeneratorSavedLocal, Local)> {
-        self.iter().enumerate().map(|(i, l)| (GeneratorSavedLocal::from(i), l))
+    fn iter_enumerated(&self) -> impl '_ + Iterator<Item = (CoroutineSavedLocal, Local)> {
+        self.iter().enumerate().map(|(i, l)| (CoroutineSavedLocal::from(i), l))
     }
 
     /// Transforms a `BitSet<Local>` that contains only locals saved across yield points to the
-    /// equivalent `BitSet<GeneratorSavedLocal>`.
-    fn renumber_bitset(&self, input: &BitSet<Local>) -> BitSet<GeneratorSavedLocal> {
+    /// equivalent `BitSet<CoroutineSavedLocal>`.
+    fn renumber_bitset(&self, input: &BitSet<Local>) -> BitSet<CoroutineSavedLocal> {
         assert!(self.superset(&input), "{:?} not a superset of {:?}", self.0, input);
         let mut out = BitSet::new_empty(self.count());
         for (saved_local, local) in self.iter_enumerated() {
@@ -726,17 +726,17 @@ impl GeneratorSavedLocals {
         out
     }
 
-    fn get(&self, local: Local) -> Option<GeneratorSavedLocal> {
+    fn get(&self, local: Local) -> Option<CoroutineSavedLocal> {
         if !self.contains(local) {
             return None;
         }
 
         let idx = self.iter().take_while(|&l| l < local).count();
-        Some(GeneratorSavedLocal::new(idx))
+        Some(CoroutineSavedLocal::new(idx))
     }
 }
 
-impl ops::Deref for GeneratorSavedLocals {
+impl ops::Deref for CoroutineSavedLocals {
     type Target = BitSet<Local>;
 
     fn deref(&self) -> &Self::Target {
@@ -747,13 +747,13 @@ impl ops::Deref for GeneratorSavedLocals {
 /// For every saved local, looks for which locals are StorageLive at the same
 /// time. Generates a bitset for every local of all the other locals that may be
 /// StorageLive simultaneously with that local. This is used in the layout
-/// computation; see `GeneratorLayout` for more.
+/// computation; see `CoroutineLayout` for more.
 fn compute_storage_conflicts<'mir, 'tcx>(
     body: &'mir Body<'tcx>,
-    saved_locals: &GeneratorSavedLocals,
+    saved_locals: &CoroutineSavedLocals,
     always_live_locals: BitSet<Local>,
     mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'_, 'mir, 'tcx>>,
-) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
+) -> BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal> {
     assert_eq!(body.local_decls.len(), saved_locals.domain_size());
 
     debug!("compute_storage_conflicts({:?})", body.span);
@@ -775,7 +775,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
 
     let local_conflicts = visitor.local_conflicts;
 
-    // Compress the matrix using only stored locals (Local -> GeneratorSavedLocal).
+    // Compress the matrix using only stored locals (Local -> CoroutineSavedLocal).
     //
     // NOTE: Today we store a full conflict bitset for every local. Technically
     // this is twice as many bits as we need, since the relation is symmetric.
@@ -801,9 +801,9 @@ fn compute_storage_conflicts<'mir, 'tcx>(
 
 struct StorageConflictVisitor<'mir, 'tcx, 's> {
     body: &'mir Body<'tcx>,
-    saved_locals: &'s GeneratorSavedLocals,
+    saved_locals: &'s CoroutineSavedLocals,
     // FIXME(tmandry): Consider using sparse bitsets here once we have good
-    // benchmarks for generators.
+    // benchmarks for coroutines.
     local_conflicts: BitMatrix<Local, Local>,
 }
 
@@ -858,7 +858,7 @@ fn compute_layout<'tcx>(
     body: &Body<'tcx>,
 ) -> (
     FxHashMap<Local, (Ty<'tcx>, VariantIdx, FieldIdx)>,
-    GeneratorLayout<'tcx>,
+    CoroutineLayout<'tcx>,
     IndexVec<BasicBlock, Option<BitSet<Local>>>,
 ) {
     let LivenessInfo {
@@ -870,10 +870,10 @@ fn compute_layout<'tcx>(
     } = liveness;
 
     // Gather live local types and their indices.
-    let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();
-    let mut tys = IndexVec::<GeneratorSavedLocal, _>::new();
+    let mut locals = IndexVec::<CoroutineSavedLocal, _>::new();
+    let mut tys = IndexVec::<CoroutineSavedLocal, _>::new();
     for (saved_local, local) in saved_locals.iter_enumerated() {
-        debug!("generator saved local {:?} => {:?}", saved_local, local);
+        debug!("coroutine saved local {:?} => {:?}", saved_local, local);
 
         locals.push(local);
         let decl = &body.local_decls[local];
@@ -895,7 +895,7 @@ fn compute_layout<'tcx>(
             _ => false,
         };
         let decl =
-            GeneratorSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
+            CoroutineSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
         debug!(?decl);
 
         tys.push(decl);
@@ -914,9 +914,9 @@ fn compute_layout<'tcx>(
     .copied()
     .collect();
 
-    // Build the generator variant field list.
-    // Create a map from local indices to generator struct indices.
-    let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>> =
+    // Build the coroutine variant field list.
+    // Create a map from local indices to coroutine struct indices.
+    let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
         iter::repeat(IndexVec::new()).take(RESERVED_VARIANTS).collect();
     let mut remap = FxHashMap::default();
     for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() {
@@ -926,7 +926,7 @@ fn compute_layout<'tcx>(
             fields.push(saved_local);
             // Note that if a field is included in multiple variants, we will
             // just use the first one here. That's fine; fields do not move
-            // around inside generators, so it doesn't matter which variant
+            // around inside coroutines, so it doesn't matter which variant
             // index we access them by.
             let idx = FieldIdx::from_usize(idx);
             remap.entry(locals[saved_local]).or_insert((tys[saved_local].ty, variant_index, idx));
@@ -934,8 +934,8 @@ fn compute_layout<'tcx>(
         variant_fields.push(fields);
         variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]);
     }
-    debug!("generator variant_fields = {:?}", variant_fields);
-    debug!("generator storage_conflicts = {:#?}", storage_conflicts);
+    debug!("coroutine variant_fields = {:?}", variant_fields);
+    debug!("coroutine storage_conflicts = {:#?}", storage_conflicts);
 
     let mut field_names = IndexVec::from_elem(None, &tys);
     for var in &body.var_debug_info {
@@ -947,7 +947,7 @@ fn compute_layout<'tcx>(
         field_names.get_or_insert_with(saved_local, || var.name);
     }
 
-    let layout = GeneratorLayout {
+    let layout = CoroutineLayout {
         field_tys: tys,
         field_names,
         variant_fields,
@@ -959,7 +959,7 @@ fn compute_layout<'tcx>(
     (remap, layout, storage_liveness)
 }
 
-/// Replaces the entry point of `body` with a block that switches on the generator discriminant and
+/// Replaces the entry point of `body` with a block that switches on the coroutine discriminant and
 /// dispatches to blocks according to `cases`.
 ///
 /// After this function, the former entry point of the function will be bb1.
@@ -992,14 +992,14 @@ fn insert_switch<'tcx>(
     }
 }
 
-fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     use crate::shim::DropShimElaborator;
     use rustc_middle::mir::patch::MirPatch;
     use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, Unwind};
 
-    // Note that `elaborate_drops` only drops the upvars of a generator, and
+    // Note that `elaborate_drops` only drops the upvars of a coroutine, and
     // this is ok because `open_drop` can only be reached within that own
-    // generator's resume function.
+    // coroutine's resume function.
 
     let def_id = body.source.def_id();
     let param_env = tcx.param_env(def_id);
@@ -1047,7 +1047,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     elaborator.patch.apply(body);
 }
 
-fn create_generator_drop_shim<'tcx>(
+fn create_coroutine_drop_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     transform: &TransformVisitor<'tcx>,
     gen_ty: Ty<'tcx>,
@@ -1070,7 +1070,7 @@ fn create_generator_drop_shim<'tcx>(
 
     for block in body.basic_blocks_mut() {
         let kind = &mut block.terminator_mut().kind;
-        if let TerminatorKind::GeneratorDrop = *kind {
+        if let TerminatorKind::CoroutineDrop = *kind {
             *kind = TerminatorKind::Return;
         }
     }
@@ -1078,9 +1078,9 @@ fn create_generator_drop_shim<'tcx>(
     // Replace the return variable
     body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(Ty::new_unit(tcx), source_info);
 
-    make_generator_state_argument_indirect(tcx, &mut body);
+    make_coroutine_state_argument_indirect(tcx, &mut body);
 
-    // Change the generator argument from &mut to *mut
+    // Change the coroutine argument from &mut to *mut
     body.local_decls[SELF_ARG] = LocalDecl::with_source_info(
         Ty::new_ptr(tcx, ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         source_info,
@@ -1104,10 +1104,10 @@ fn create_generator_drop_shim<'tcx>(
         None,
     );
 
-    // Temporary change MirSource to generator's instance so that dump_mir produces more sensible
+    // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible
     // filename.
     body.source.instance = gen_instance;
-    dump_mir(tcx, false, "generator_drop", &0, &body, |_, _| Ok(()));
+    dump_mir(tcx, false, "coroutine_drop", &0, &body, |_, _| Ok(()));
     body.source.instance = drop_instance;
 
     body
@@ -1182,7 +1182,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {}
 
@@ -1191,7 +1191,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             TerminatorKind::UnwindResume => {}
 
             TerminatorKind::Yield { .. } => {
-                unreachable!("`can_unwind` called before generator transform")
+                unreachable!("`can_unwind` called before coroutine transform")
             }
 
             // These may unwind.
@@ -1206,7 +1206,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
     false
 }
 
-fn create_generator_resume_function<'tcx>(
+fn create_coroutine_resume_function<'tcx>(
     tcx: TyCtxt<'tcx>,
     transform: TransformVisitor<'tcx>,
     body: &mut Body<'tcx>,
@@ -1214,7 +1214,7 @@ fn create_generator_resume_function<'tcx>(
 ) {
     let can_unwind = can_unwind(tcx, body);
 
-    // Poison the generator when it unwinds
+    // Poison the coroutine when it unwinds
     if can_unwind {
         let source_info = SourceInfo::outermost(body.span);
         let poison_block = body.basic_blocks_mut().push(BasicBlockData {
@@ -1253,26 +1253,26 @@ fn create_generator_resume_function<'tcx>(
     cases.insert(0, (UNRESUMED, START_BLOCK));
 
     // Panic when resumed on the returned or poisoned state
-    let generator_kind = body.generator_kind().unwrap();
+    let coroutine_kind = body.coroutine_kind().unwrap();
 
     if can_unwind {
         cases.insert(
             1,
-            (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))),
+            (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(coroutine_kind))),
         );
     }
 
     if can_return {
         cases.insert(
             1,
-            (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))),
+            (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(coroutine_kind))),
         );
     }
 
     insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
 
-    make_generator_state_argument_indirect(tcx, body);
-    make_generator_state_argument_pinned(tcx, body);
+    make_coroutine_state_argument_indirect(tcx, body);
+    make_coroutine_state_argument_pinned(tcx, body);
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the drop part of the function
@@ -1280,7 +1280,7 @@ fn create_generator_resume_function<'tcx>(
 
     pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);
 
-    dump_mir(tcx, false, "generator_resume", &0, body, |_, _| Ok(()));
+    dump_mir(tcx, false, "coroutine_resume", &0, body, |_, _| Ok(()));
 }
 
 fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
@@ -1294,7 +1294,7 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
     };
     let source_info = SourceInfo::outermost(body.span);
 
-    // Create a block to destroy an unresumed generators. This can only destroy upvars.
+    // Create a block to destroy an unresumed coroutines. This can only destroy upvars.
     body.basic_blocks_mut().push(BasicBlockData {
         statements: Vec::new(),
         terminator: Some(Terminator { source_info, kind: term }),
@@ -1302,7 +1302,7 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
     })
 }
 
-/// An operation that can be performed on a generator.
+/// An operation that can be performed on a coroutine.
 #[derive(PartialEq, Copy, Clone)]
 enum Operation {
     Resume,
@@ -1381,64 +1381,64 @@ fn create_cases<'tcx>(
 }
 
 #[instrument(level = "debug", skip(tcx), ret)]
-pub(crate) fn mir_generator_witnesses<'tcx>(
+pub(crate) fn mir_coroutine_witnesses<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> Option<GeneratorLayout<'tcx>> {
+) -> Option<CoroutineLayout<'tcx>> {
     let (body, _) = tcx.mir_promoted(def_id);
     let body = body.borrow();
     let body = &*body;
 
-    // The first argument is the generator type passed by value
+    // The first argument is the coroutine type passed by value
     let gen_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
     // Get the interior types and args which typeck computed
     let movable = match *gen_ty.kind() {
-        ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
+        ty::Coroutine(_, _, movability) => movability == hir::Movability::Movable,
         ty::Error(_) => return None,
-        _ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
+        _ => span_bug!(body.span, "unexpected coroutine type {}", gen_ty),
     };
 
-    // When first entering the generator, move the resume argument into its new local.
+    // When first entering the coroutine, move the resume argument into its new local.
     let always_live_locals = always_storage_live_locals(&body);
 
     let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
 
     // Extract locals which are live across suspension point into `layout`
-    // `remap` gives a mapping from local indices onto generator struct indices
+    // `remap` gives a mapping from local indices onto coroutine struct indices
     // `storage_liveness` tells us which locals have live storage at suspension points
-    let (_, generator_layout, _) = compute_layout(liveness_info, body);
+    let (_, coroutine_layout, _) = compute_layout(liveness_info, body);
 
-    check_suspend_tys(tcx, &generator_layout, &body);
+    check_suspend_tys(tcx, &coroutine_layout, &body);
 
-    Some(generator_layout)
+    Some(coroutine_layout)
 }
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let Some(yield_ty) = body.yield_ty() else {
-            // This only applies to generators
+            // This only applies to coroutines
             return;
         };
 
-        assert!(body.generator_drop().is_none());
+        assert!(body.coroutine_drop().is_none());
 
-        // The first argument is the generator type passed by value
+        // The first argument is the coroutine type passed by value
         let gen_ty = body.local_decls.raw[1].ty;
 
         // Get the discriminant type and args which typeck computed
         let (discr_ty, movable) = match *gen_ty.kind() {
-            ty::Generator(_, args, movability) => {
-                let args = args.as_generator();
+            ty::Coroutine(_, args, movability) => {
+                let args = args.as_coroutine();
                 (args.discr_ty(tcx), movability == hir::Movability::Movable)
             }
             _ => {
-                tcx.sess.delay_span_bug(body.span, format!("unexpected generator type {gen_ty}"));
+                tcx.sess.delay_span_bug(body.span, format!("unexpected coroutine type {gen_ty}"));
                 return;
             }
         };
 
-        let is_async_kind = matches!(body.generator_kind(), Some(GeneratorKind::Async(_)));
+        let is_async_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Async(_)));
         let (state_adt_ref, state_args) = if is_async_kind {
             // Compute Poll<return_ty>
             let poll_did = tcx.require_lang_item(LangItem::Poll, None);
@@ -1446,8 +1446,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             let poll_args = tcx.mk_args(&[body.return_ty().into()]);
             (poll_adt_ref, poll_args)
         } else {
-            // Compute GeneratorState<yield_ty, return_ty>
-            let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+            // Compute CoroutineState<yield_ty, return_ty>
+            let state_did = tcx.require_lang_item(LangItem::CoroutineState, None);
             let state_adt_ref = tcx.adt_def(state_did);
             let state_args = tcx.mk_args(&[yield_ty.into(), body.return_ty().into()]);
             (state_adt_ref, state_args)
@@ -1465,8 +1465,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
 
         // We also replace the resume argument and insert an `Assign`.
         // This is needed because the resume argument `_2` might be live across a `yield`, in which
-        // case there is no `Assign` to it that the transform can turn into a store to the generator
-        // state. After the yield the slot in the generator state would then be uninitialized.
+        // case there is no `Assign` to it that the transform can turn into a store to the coroutine
+        // state. After the yield the slot in the coroutine state would then be uninitialized.
         let resume_local = Local::new(2);
         let resume_ty = if is_async_kind {
             Ty::new_task_context(tcx)
@@ -1475,7 +1475,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         };
         let new_resume_local = replace_local(resume_local, resume_ty, body, tcx);
 
-        // When first entering the generator, move the resume argument into its new local.
+        // When first entering the coroutine, move the resume argument into its new local.
         let source_info = SourceInfo::outermost(body.span);
         let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
         stmts.insert(
@@ -1495,7 +1495,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
 
         if tcx.sess.opts.unstable_opts.validate_mir {
-            let mut vis = EnsureGeneratorFieldAssignmentsNeverAlias {
+            let mut vis = EnsureCoroutineFieldAssignmentsNeverAlias {
                 assigned_local: None,
                 saved_locals: &liveness_info.saved_locals,
                 storage_conflicts: &liveness_info.storage_conflicts,
@@ -1505,16 +1505,16 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         }
 
         // Extract locals which are live across suspension point into `layout`
-        // `remap` gives a mapping from local indices onto generator struct indices
+        // `remap` gives a mapping from local indices onto coroutine struct indices
         // `storage_liveness` tells us which locals have live storage at suspension points
         let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
 
         let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
 
-        // Run the transformation which converts Places from Local to generator struct
+        // Run the transformation which converts Places from Local to coroutine struct
         // accesses for locals in `remap`.
-        // It also rewrites `return x` and `yield y` as writing a new generator state and returning
-        // either GeneratorState::Complete(x) and GeneratorState::Yielded(y),
+        // It also rewrites `return x` and `yield y` as writing a new coroutine state and returning
+        // either CoroutineState::Complete(x) and CoroutineState::Yielded(y),
         // or Poll::Ready(x) and Poll::Pending respectively depending on `is_async_kind`.
         let mut transform = TransformVisitor {
             tcx,
@@ -1541,30 +1541,30 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             var.argument_index = None;
         }
 
-        body.generator.as_mut().unwrap().yield_ty = None;
-        body.generator.as_mut().unwrap().generator_layout = Some(layout);
+        body.coroutine.as_mut().unwrap().yield_ty = None;
+        body.coroutine.as_mut().unwrap().coroutine_layout = Some(layout);
 
-        // Insert `drop(generator_struct)` which is used to drop upvars for generators in
+        // Insert `drop(coroutine_struct)` which is used to drop upvars for coroutines in
         // the unresumed state.
-        // This is expanded to a drop ladder in `elaborate_generator_drops`.
+        // This is expanded to a drop ladder in `elaborate_coroutine_drops`.
         let drop_clean = insert_clean_drop(body);
 
-        dump_mir(tcx, false, "generator_pre-elab", &0, body, |_, _| Ok(()));
+        dump_mir(tcx, false, "coroutine_pre-elab", &0, body, |_, _| Ok(()));
 
-        // Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
+        // Expand `drop(coroutine_struct)` to a drop ladder which destroys upvars.
         // If any upvars are moved out of, drop elaboration will handle upvar destruction.
         // However we need to also elaborate the code generated by `insert_clean_drop`.
-        elaborate_generator_drops(tcx, body);
+        elaborate_coroutine_drops(tcx, body);
 
-        dump_mir(tcx, false, "generator_post-transform", &0, body, |_, _| Ok(()));
+        dump_mir(tcx, false, "coroutine_post-transform", &0, body, |_, _| Ok(()));
 
-        // Create a copy of our MIR and use it to create the drop shim for the generator
-        let drop_shim = create_generator_drop_shim(tcx, &transform, gen_ty, body, drop_clean);
+        // Create a copy of our MIR and use it to create the drop shim for the coroutine
+        let drop_shim = create_coroutine_drop_shim(tcx, &transform, gen_ty, body, drop_clean);
 
-        body.generator.as_mut().unwrap().generator_drop = Some(drop_shim);
+        body.coroutine.as_mut().unwrap().coroutine_drop = Some(drop_shim);
 
-        // Create the Generator::resume / Future::poll function
-        create_generator_resume_function(tcx, transform, body, can_return);
+        // Create the Coroutine::resume / Future::poll function
+        create_coroutine_resume_function(tcx, transform, body, can_return);
 
         // Run derefer to fix Derefs that are not in the first place
         deref_finder(tcx, body);
@@ -1572,25 +1572,25 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
 }
 
 /// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields
-/// in the generator state machine but whose storage is not marked as conflicting
+/// in the coroutine state machine but whose storage is not marked as conflicting
 ///
 /// Validation needs to happen immediately *before* `TransformVisitor` is invoked, not after.
 ///
 /// This condition would arise when the assignment is the last use of `_5` but the initial
 /// definition of `_4` if we weren't extra careful to mark all locals used inside a statement as
-/// conflicting. Non-conflicting generator saved locals may be stored at the same location within
-/// the generator state machine, which would result in ill-formed MIR: the left-hand and right-hand
+/// conflicting. Non-conflicting coroutine saved locals may be stored at the same location within
+/// the coroutine state machine, which would result in ill-formed MIR: the left-hand and right-hand
 /// sides of an assignment may not alias. This caused a miscompilation in [#73137].
 ///
 /// [#73137]: https://github.com/rust-lang/rust/issues/73137
-struct EnsureGeneratorFieldAssignmentsNeverAlias<'a> {
-    saved_locals: &'a GeneratorSavedLocals,
-    storage_conflicts: &'a BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
-    assigned_local: Option<GeneratorSavedLocal>,
+struct EnsureCoroutineFieldAssignmentsNeverAlias<'a> {
+    saved_locals: &'a CoroutineSavedLocals,
+    storage_conflicts: &'a BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
+    assigned_local: Option<CoroutineSavedLocal>,
 }
 
-impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
-    fn saved_local_for_direct_place(&self, place: Place<'_>) -> Option<GeneratorSavedLocal> {
+impl EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
+    fn saved_local_for_direct_place(&self, place: Place<'_>) -> Option<CoroutineSavedLocal> {
         if place.is_indirect() {
             return None;
         }
@@ -1609,7 +1609,7 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
     }
 }
 
-impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
+impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
         let Some(lhs) = self.assigned_local else {
             // This visitor only invokes `visit_place` for the right-hand side of an assignment
@@ -1624,7 +1624,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
 
         if !self.storage_conflicts.contains(lhs, rhs) {
             bug!(
-                "Assignment between generator saved locals whose storage is not \
+                "Assignment between coroutine saved locals whose storage is not \
                     marked as conflicting: {:?}: {:?} = {:?}",
                 location,
                 lhs,
@@ -1691,14 +1691,14 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
             | TerminatorKind::Assert { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {}
         }
     }
 }
 
-fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &GeneratorLayout<'tcx>, body: &Body<'tcx>) {
+fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &CoroutineLayout<'tcx>, body: &Body<'tcx>) {
     let mut linted_tys = FxHashSet::default();
 
     // We want a user-facing param-env.
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index a83ccf8fc3c..d07f59bc72a 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -169,22 +169,22 @@ impl CoverageCounters {
         self.bcb_counters[bcb].as_ref()
     }
 
-    pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
-        self.bcb_counters[bcb].take()
-    }
-
-    pub(super) fn drain_bcb_counters(
-        &mut self,
-    ) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ {
+    pub(super) fn bcb_node_counters(
+        &self,
+    ) -> impl Iterator<Item = (BasicCoverageBlock, &BcbCounter)> {
         self.bcb_counters
-            .iter_enumerated_mut()
-            .filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
+            .iter_enumerated()
+            .filter_map(|(bcb, counter_kind)| Some((bcb, counter_kind.as_ref()?)))
     }
 
-    pub(super) fn drain_bcb_edge_counters(
-        &mut self,
-    ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ {
-        self.bcb_edge_counters.drain()
+    /// For each edge in the BCB graph that has an associated counter, yields
+    /// that edge's *from* and *to* nodes, and its counter.
+    pub(super) fn bcb_edge_counters(
+        &self,
+    ) -> impl Iterator<Item = (BasicCoverageBlock, BasicCoverageBlock, &BcbCounter)> {
+        self.bcb_edge_counters
+            .iter()
+            .map(|(&(from_bcb, to_bcb), counter_kind)| (from_bcb, to_bcb, counter_kind))
     }
 
     pub(super) fn take_expressions(&mut self) -> IndexVec<ExpressionId, Expression> {
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 9a7adaada09..6bab62aa854 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -147,7 +147,7 @@ impl CoverageGraph {
                 | TerminatorKind::Unreachable
                 | TerminatorKind::Drop { .. }
                 | TerminatorKind::Call { .. }
-                | TerminatorKind::GeneratorDrop
+                | TerminatorKind::CoroutineDrop
                 | TerminatorKind::Assert { .. }
                 | TerminatorKind::FalseEdge { .. }
                 | TerminatorKind::FalseUnwind { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 6fdaff6b4c0..c9b36ba25ac 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -8,7 +8,7 @@ mod spans;
 mod tests;
 
 use self::counters::{BcbCounter, CoverageCounters};
-use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
+use self::graph::CoverageGraph;
 use self::spans::CoverageSpans;
 
 use crate::MirPass;
@@ -104,7 +104,6 @@ struct Instrumentor<'a, 'tcx> {
     function_source_hash: u64,
     basic_coverage_blocks: CoverageGraph,
     coverage_counters: CoverageCounters,
-    mappings: Vec<Mapping>,
 }
 
 impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
@@ -145,7 +144,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             function_source_hash,
             basic_coverage_blocks,
             coverage_counters,
-            mappings: Vec::new(),
         }
     }
 
@@ -168,148 +166,99 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         // and all `Expression` dependencies (operands) are also generated, for any other
         // `BasicCoverageBlock`s not already associated with a coverage span.
         let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
-        let result = self
-            .coverage_counters
-            .make_bcb_counters(&mut self.basic_coverage_blocks, bcb_has_coverage_spans);
-
-        if let Ok(()) = result {
-            ////////////////////////////////////////////////////
-            // Remove the counter or edge counter from of each coverage cpan's associated
-            // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR.
-            //
-            // `Coverage` statements injected from coverage spans will include the code regions
-            // (source code start and end positions) to be counted by the associated counter.
-            //
-            // These coverage-span-associated counters are removed from their associated
-            // `BasicCoverageBlock`s so that the only remaining counters in the `CoverageGraph`
-            // are indirect counters (to be injected next, without associated code regions).
-            self.inject_coverage_span_counters(&coverage_spans);
-
-            ////////////////////////////////////////////////////
-            // For any remaining `BasicCoverageBlock` counters (that were not associated with
-            // any coverage span), inject `Coverage` statements (_without_ code region spans)
-            // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on
-            // are in fact counted, even though they don't directly contribute to counting
-            // their own independent code region's coverage.
-            self.inject_indirect_counters();
-        };
+        self.coverage_counters
+            .make_bcb_counters(&mut self.basic_coverage_blocks, bcb_has_coverage_spans)
+            .unwrap_or_else(|e| {
+                bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message)
+            });
 
-        if let Err(e) = result {
-            bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message)
-        };
+        let mappings = self.create_mappings_and_inject_coverage_statements(&coverage_spans);
 
         self.mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
             function_source_hash: self.function_source_hash,
             num_counters: self.coverage_counters.num_counters(),
             expressions: self.coverage_counters.take_expressions(),
-            mappings: std::mem::take(&mut self.mappings),
+            mappings,
         }));
     }
 
-    /// Injects a single [`StatementKind::Coverage`] for each BCB that has one
-    /// or more coverage spans.
-    fn inject_coverage_span_counters(&mut self, coverage_spans: &CoverageSpans) {
-        let tcx = self.tcx;
-        let source_map = tcx.sess.source_map();
+    /// For each [`BcbCounter`] associated with a BCB node or BCB edge, create
+    /// any corresponding mappings (for BCB nodes only), and inject any necessary
+    /// coverage statements into MIR.
+    fn create_mappings_and_inject_coverage_statements(
+        &mut self,
+        coverage_spans: &CoverageSpans,
+    ) -> Vec<Mapping> {
+        let source_map = self.tcx.sess.source_map();
         let body_span = self.body_span;
 
         use rustc_session::RemapFileNameExt;
         let file_name =
             Symbol::intern(&self.source_file.name.for_codegen(self.tcx.sess).to_string_lossy());
 
-        for (bcb, spans) in coverage_spans.bcbs_with_coverage_spans() {
-            let counter_kind = self.coverage_counters.take_bcb_counter(bcb).unwrap_or_else(|| {
-                bug!("Every BasicCoverageBlock should have a Counter or Expression");
-            });
-
-            let term = counter_kind.as_term();
-            self.mappings.extend(spans.iter().map(|&span| {
-                let code_region = make_code_region(source_map, file_name, span, body_span);
-                Mapping { code_region, term }
-            }));
-
-            inject_statement(
-                self.mir_body,
-                self.make_mir_coverage_kind(&counter_kind),
-                self.bcb_leader_bb(bcb),
-            );
-        }
-    }
+        let mut mappings = Vec::new();
+
+        // Process the counters and spans associated with BCB nodes.
+        for (bcb, counter_kind) in self.coverage_counters.bcb_node_counters() {
+            let spans = coverage_spans.spans_for_bcb(bcb);
+            let has_mappings = !spans.is_empty();
+
+            // If this BCB has any coverage spans, add corresponding mappings to
+            // the mappings table.
+            if has_mappings {
+                let term = counter_kind.as_term();
+                mappings.extend(spans.iter().map(|&span| {
+                    let code_region = make_code_region(source_map, file_name, span, body_span);
+                    Mapping { code_region, term }
+                }));
+            }
 
-    /// At this point, any BCB with coverage counters has already had its counter injected
-    /// into MIR, and had its counter removed from `coverage_counters` (via `take_counter()`).
-    ///
-    /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not
-    /// associated with a coverage span, should only exist if the counter is an `Expression`
-    /// dependency (one of the expression operands). Collect them, and inject the additional
-    /// counters into the MIR, without a reportable coverage span.
-    fn inject_indirect_counters(&mut self) {
-        let mut bcb_counters_without_direct_coverage_spans = Vec::new();
-        for (target_bcb, counter_kind) in self.coverage_counters.drain_bcb_counters() {
-            bcb_counters_without_direct_coverage_spans.push((None, target_bcb, counter_kind));
-        }
-        for ((from_bcb, target_bcb), counter_kind) in
-            self.coverage_counters.drain_bcb_edge_counters()
-        {
-            bcb_counters_without_direct_coverage_spans.push((
-                Some(from_bcb),
-                target_bcb,
-                counter_kind,
-            ));
+            let do_inject = match counter_kind {
+                // Counter-increment statements always need to be injected.
+                BcbCounter::Counter { .. } => true,
+                // The only purpose of expression-used statements is to detect
+                // when a mapping is unreachable, so we only inject them for
+                // expressions with one or more mappings.
+                BcbCounter::Expression { .. } => has_mappings,
+            };
+            if do_inject {
+                inject_statement(
+                    self.mir_body,
+                    self.make_mir_coverage_kind(counter_kind),
+                    self.basic_coverage_blocks[bcb].leader_bb(),
+                );
+            }
         }
 
-        for (edge_from_bcb, target_bcb, counter_kind) in bcb_counters_without_direct_coverage_spans
-        {
-            match counter_kind {
-                BcbCounter::Counter { .. } => {
-                    let inject_to_bb = if let Some(from_bcb) = edge_from_bcb {
-                        // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
-                        // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
-                        // `target_bcb`; also called the `leader_bb`).
-                        let from_bb = self.bcb_last_bb(from_bcb);
-                        let to_bb = self.bcb_leader_bb(target_bcb);
-
-                        let new_bb = inject_edge_counter_basic_block(self.mir_body, from_bb, to_bb);
-                        debug!(
-                            "Edge {:?} (last {:?}) -> {:?} (leader {:?}) requires a new MIR \
-                            BasicBlock {:?}, for unclaimed edge counter {:?}",
-                            edge_from_bcb, from_bb, target_bcb, to_bb, new_bb, counter_kind,
-                        );
-                        new_bb
-                    } else {
-                        let target_bb = self.bcb_last_bb(target_bcb);
-                        debug!(
-                            "{:?} ({:?}) gets a new Coverage statement for unclaimed counter {:?}",
-                            target_bcb, target_bb, counter_kind,
-                        );
-                        target_bb
-                    };
-
-                    inject_statement(
-                        self.mir_body,
-                        self.make_mir_coverage_kind(&counter_kind),
-                        inject_to_bb,
-                    );
-                }
-                // Experessions with no associated spans don't need to inject a statement.
-                BcbCounter::Expression { .. } => {}
+        // Process the counters associated with BCB edges.
+        for (from_bcb, to_bcb, counter_kind) in self.coverage_counters.bcb_edge_counters() {
+            let do_inject = match counter_kind {
+                // Counter-increment statements always need to be injected.
+                BcbCounter::Counter { .. } => true,
+                // BCB-edge expressions never have mappings, so they never need
+                // a corresponding statement.
+                BcbCounter::Expression { .. } => false,
+            };
+            if !do_inject {
+                continue;
             }
-        }
-    }
 
-    #[inline]
-    fn bcb_leader_bb(&self, bcb: BasicCoverageBlock) -> BasicBlock {
-        self.bcb_data(bcb).leader_bb()
-    }
+            // We need to inject a coverage statement into a new BB between the
+            // last BB of `from_bcb` and the first BB of `to_bcb`.
+            let from_bb = self.basic_coverage_blocks[from_bcb].last_bb();
+            let to_bb = self.basic_coverage_blocks[to_bcb].leader_bb();
 
-    #[inline]
-    fn bcb_last_bb(&self, bcb: BasicCoverageBlock) -> BasicBlock {
-        self.bcb_data(bcb).last_bb()
-    }
+            let new_bb = inject_edge_counter_basic_block(self.mir_body, from_bb, to_bb);
+            debug!(
+                "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \
+                requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}",
+            );
+
+            // Inject a counter into the newly-created BB.
+            inject_statement(self.mir_body, self.make_mir_coverage_kind(&counter_kind), new_bb);
+        }
 
-    #[inline]
-    fn bcb_data(&self, bcb: BasicCoverageBlock) -> &BasicCoverageBlockData {
-        &self.basic_coverage_blocks[bcb]
+        mappings
     }
 
     fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind {
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index f1a0f762041..704eea413e1 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -2,7 +2,7 @@ use std::cell::OnceCell;
 
 use rustc_data_structures::graph::WithNumNodes;
 use rustc_index::IndexVec;
-use rustc_middle::mir::{self, AggregateKind, Rvalue, Statement, StatementKind};
+use rustc_middle::mir;
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol, DUMMY_SP};
 
 use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
@@ -41,13 +41,8 @@ impl CoverageSpans {
         !self.bcb_to_spans[bcb].is_empty()
     }
 
-    pub(super) fn bcbs_with_coverage_spans(
-        &self,
-    ) -> impl Iterator<Item = (BasicCoverageBlock, &[Span])> {
-        self.bcb_to_spans.iter_enumerated().filter_map(|(bcb, spans)| {
-            // Only yield BCBs that have at least one coverage span.
-            (!spans.is_empty()).then_some((bcb, spans.as_slice()))
-        })
+    pub(super) fn spans_for_bcb(&self, bcb: BasicCoverageBlock) -> &[Span] {
+        &self.bcb_to_spans[bcb]
     }
 }
 
@@ -75,29 +70,15 @@ struct CoverageSpan {
 
 impl CoverageSpan {
     pub fn for_fn_sig(fn_sig_span: Span) -> Self {
-        Self {
-            span: fn_sig_span,
-            expn_span: fn_sig_span,
-            current_macro_or_none: Default::default(),
-            bcb: START_BCB,
-            merged_spans: vec![],
-            is_closure: false,
-        }
+        Self::new(fn_sig_span, fn_sig_span, START_BCB, false)
     }
 
-    pub fn for_statement(
-        statement: &Statement<'_>,
+    pub(super) fn new(
         span: Span,
         expn_span: Span,
         bcb: BasicCoverageBlock,
+        is_closure: bool,
     ) -> Self {
-        let is_closure = match statement.kind {
-            StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => {
-                matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _))
-            }
-            _ => false,
-        };
-
         Self {
             span,
             expn_span,
@@ -108,17 +89,6 @@ impl CoverageSpan {
         }
     }
 
-    pub fn for_terminator(span: Span, expn_span: Span, bcb: BasicCoverageBlock) -> Self {
-        Self {
-            span,
-            expn_span,
-            current_macro_or_none: Default::default(),
-            bcb,
-            merged_spans: vec![span],
-            is_closure: false,
-        }
-    }
-
     pub fn merge_from(&mut self, mut other: CoverageSpan) {
         debug_assert!(self.is_mergeable(&other));
         self.span = self.span.to(other.span);
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 4c20997e633..6189e5379ea 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -1,5 +1,7 @@
+use rustc_data_structures::captures::Captures;
 use rustc_middle::mir::{
-    self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
+    self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
+    TerminatorKind,
 };
 use rustc_span::Span;
 
@@ -12,7 +14,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
     body_span: Span,
     basic_coverage_blocks: &CoverageGraph,
 ) -> Vec<CoverageSpan> {
-    let mut initial_spans = Vec::<CoverageSpan>::with_capacity(mir_body.basic_blocks.len() * 2);
+    let mut initial_spans = Vec::with_capacity(mir_body.basic_blocks.len() * 2);
     for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() {
         initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data));
     }
@@ -50,34 +52,41 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
 // for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
 // merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple
 // `Statement`s and/or `Terminator`s.)
-fn bcb_to_initial_coverage_spans(
-    mir_body: &mir::Body<'_>,
+fn bcb_to_initial_coverage_spans<'a, 'tcx>(
+    mir_body: &'a mir::Body<'tcx>,
     body_span: Span,
     bcb: BasicCoverageBlock,
-    bcb_data: &BasicCoverageBlockData,
-) -> Vec<CoverageSpan> {
-    bcb_data
-        .basic_blocks
-        .iter()
-        .flat_map(|&bb| {
-            let data = &mir_body[bb];
-            data.statements
-                .iter()
-                .filter_map(move |statement| {
-                    filtered_statement_span(statement).map(|span| {
-                        CoverageSpan::for_statement(
-                            statement,
-                            function_source_span(span, body_span),
-                            span,
-                            bcb,
-                        )
-                    })
-                })
-                .chain(filtered_terminator_span(data.terminator()).map(|span| {
-                    CoverageSpan::for_terminator(function_source_span(span, body_span), span, bcb)
-                }))
-        })
-        .collect()
+    bcb_data: &'a BasicCoverageBlockData,
+) -> impl Iterator<Item = CoverageSpan> + Captures<'a> + Captures<'tcx> {
+    bcb_data.basic_blocks.iter().flat_map(move |&bb| {
+        let data = &mir_body[bb];
+
+        let statement_spans = data.statements.iter().filter_map(move |statement| {
+            let expn_span = filtered_statement_span(statement)?;
+            let span = function_source_span(expn_span, body_span);
+
+            Some(CoverageSpan::new(span, expn_span, bcb, is_closure(statement)))
+        });
+
+        let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
+            let expn_span = filtered_terminator_span(terminator)?;
+            let span = function_source_span(expn_span, body_span);
+
+            Some(CoverageSpan::new(span, expn_span, bcb, false))
+        });
+
+        statement_spans.chain(terminator_span)
+    })
+}
+
+fn is_closure(statement: &Statement<'_>) -> bool {
+    match statement.kind {
+        StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind {
+            AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _, _) => true,
+            _ => false,
+        },
+        _ => false,
+    }
 }
 
 /// If the MIR `Statement` has a span contributive to computing coverage spans,
@@ -160,7 +169,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
         | TerminatorKind::UnwindTerminate(_)
         | TerminatorKind::Return
         | TerminatorKind::Yield { .. }
-        | TerminatorKind::GeneratorDrop
+        | TerminatorKind::CoroutineDrop
         | TerminatorKind::FalseUnwind { .. }
         | TerminatorKind::InlineAsm { .. } => {
             Some(terminator.source_info.span)
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 99b070c018e..15502adfb5a 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -114,7 +114,7 @@
 //! approach that only works for some classes of CFGs:
 //! - rustc now has a powerful dataflow analysis framework that can handle forwards and backwards
 //!   analyses efficiently.
-//! - Layout optimizations for generators have been added to improve code generation for
+//! - Layout optimizations for coroutines have been added to improve code generation for
 //!   async/await, which are very similar in spirit to what this optimization does.
 //!
 //! Also, rustc now has a simple NRVO pass (see `nrvo.rs`), which handles a subset of the cases that
@@ -655,7 +655,7 @@ impl WriteInfo {
                 // `Drop`s create a `&mut` and so are not considered
             }
             TerminatorKind::Yield { .. }
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
                 bug!("{:?} not found in this MIR phase", terminator)
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index d202860840c..26fcfad8287 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -58,7 +58,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
     let body_abi = match body_ty.kind() {
         ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
         ty::Closure(..) => Abi::RustCall,
-        ty::Generator(..) => Abi::Rust,
+        ty::Coroutine(..) => Abi::Rust,
         _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
     };
     let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi);
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index c710e460dcb..eece7c3e834 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -383,7 +383,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     AggregateKind::Array(..)
                     | AggregateKind::Tuple
                     | AggregateKind::Closure(..)
-                    | AggregateKind::Generator(..) => FIRST_VARIANT,
+                    | AggregateKind::Coroutine(..) => FIRST_VARIANT,
                     AggregateKind::Adt(_, variant_index, _, _, None) => variant_index,
                     // Do not track unions.
                     AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 8f578b69694..757b2aeca7b 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -79,10 +79,10 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
     if body.source.promoted.is_some() {
         return false;
     }
-    // Avoid inlining into generators, since their `optimized_mir` is used for layout computation,
+    // Avoid inlining into coroutines, since their `optimized_mir` is used for layout computation,
     // which can create a cycle, even when no attempt is made to inline the function in the other
     // direction.
-    if body.generator.is_some() {
+    if body.coroutine.is_some() {
         return false;
     }
 
@@ -1014,7 +1014,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
         }
 
         match terminator.kind {
-            TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(),
+            TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => bug!(),
             TerminatorKind::Goto { ref mut target } => {
                 *target = self.map_block(*target);
             }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index d579420ecb8..6c0aa51795b 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -61,6 +61,7 @@ mod const_goto;
 mod const_prop;
 mod const_prop_lint;
 mod copy_prop;
+mod coroutine;
 mod coverage;
 mod cross_crate_inline;
 mod ctfe_limit;
@@ -77,7 +78,6 @@ mod elaborate_drops;
 mod errors;
 mod ffi_unwind_calls;
 mod function_item_references;
-mod generator;
 mod gvn;
 pub mod inline;
 mod instsimplify;
@@ -132,7 +132,7 @@ pub fn provide(providers: &mut Providers) {
         mir_promoted,
         mir_drops_elaborated_and_const_checked,
         mir_for_ctfe,
-        mir_generator_witnesses: generator::mir_generator_witnesses,
+        mir_coroutine_witnesses: coroutine::mir_coroutine_witnesses,
         optimized_mir,
         is_mir_available,
         is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
@@ -375,8 +375,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
 /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
 /// end up missing the source MIR due to stealing happening.
 fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
-    if let DefKind::Generator = tcx.def_kind(def) {
-        tcx.ensure_with_value().mir_generator_witnesses(def);
+    if let DefKind::Coroutine = tcx.def_kind(def) {
+        tcx.ensure_with_value().mir_coroutine_witnesses(def);
     }
     let mir_borrowck = tcx.mir_borrowck(def);
 
@@ -509,7 +509,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // `AddRetag` needs to run after `ElaborateDrops`. Otherwise it should run fairly late,
         // but before optimizations begin.
         &elaborate_box_derefs::ElaborateBoxDerefs,
-        &generator::StateTransform,
+        &coroutine::StateTransform,
         &add_retag::AddRetag,
         &Lint(const_prop_lint::ConstPropLint),
     ];
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 8c48a667786..54892442c87 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -69,7 +69,7 @@ impl RemoveNoopLandingPads {
             | TerminatorKind::FalseUnwind { .. } => {
                 terminator.successors().all(|succ| nop_landing_pads.contains(succ))
             }
-            TerminatorKind::GeneratorDrop
+            TerminatorKind::CoroutineDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Return
             | TerminatorKind::UnwindTerminate(_)
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index b4784b69f7f..5aa3c3cfe4d 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -13,8 +13,8 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // Avoid query cycles (generators require optimized MIR for layout).
-        if tcx.type_of(body.source.def_id()).instantiate_identity().is_generator() {
+        // Avoid query cycles (coroutines require optimized MIR for layout).
+        if tcx.type_of(body.source.def_id()).instantiate_identity().is_coroutine() {
             return;
         }
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index e1e4acccccd..907cfe7581a 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -118,7 +118,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                         | TerminatorKind::Return
                         | TerminatorKind::Unreachable
                         | TerminatorKind::InlineAsm { .. }
-                        | TerminatorKind::GeneratorDrop => {
+                        | TerminatorKind::CoroutineDrop => {
                             continue 'predec_iter;
                         }
                     }
@@ -169,7 +169,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
-            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::CoroutineDrop
             | TerminatorKind::Assert { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index e9895d97dfe..2400cfa21fb 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -4,7 +4,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, EarlyBinder, GeneratorArgs, Ty, TyCtxt};
+use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
 use rustc_index::{Idx, IndexVec};
@@ -67,10 +67,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
         }
 
         ty::InstanceDef::DropGlue(def_id, ty) => {
-            // FIXME(#91576): Drop shims for generators aren't subject to the MIR passes at the end
+            // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
             // of this function. Is this intentional?
-            if let Some(ty::Generator(gen_def_id, args, _)) = ty.map(Ty::kind) {
-                let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
+            if let Some(ty::Coroutine(gen_def_id, args, _)) = ty.map(Ty::kind) {
+                let body = tcx.optimized_mir(*gen_def_id).coroutine_drop().unwrap();
                 let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
                 debug!("make_shim({:?}) = {:?}", instance, body);
 
@@ -171,7 +171,7 @@ fn local_decls_for_sig<'tcx>(
 fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
-    assert!(!matches!(ty, Some(ty) if ty.is_generator()));
+    assert!(!matches!(ty, Some(ty) if ty.is_coroutine()));
 
     let args = if let Some(ty) = ty {
         tcx.mk_args(&[ty.into()])
@@ -392,8 +392,8 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
         _ if is_copy => builder.copy_shim(),
         ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
         ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
-        ty::Generator(gen_def_id, args, hir::Movability::Movable) => {
-            builder.generator_shim(dest, src, *gen_def_id, args.as_generator())
+        ty::Coroutine(gen_def_id, args, hir::Movability::Movable) => {
+            builder.coroutine_shim(dest, src, *gen_def_id, args.as_coroutine())
         }
         _ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),
     };
@@ -593,12 +593,12 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
     }
 
-    fn generator_shim(
+    fn coroutine_shim(
         &mut self,
         dest: Place<'tcx>,
         src: Place<'tcx>,
         gen_def_id: DefId,
-        args: GeneratorArgs<'tcx>,
+        args: CoroutineArgs<'tcx>,
     ) {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
         let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index c21b1724cbb..427cc1e1924 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -20,8 +20,8 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
 
-        // Avoid query cycles (generators require optimized MIR for layout).
-        if tcx.type_of(body.source.def_id()).instantiate_identity().is_generator() {
+        // Avoid query cycles (coroutines require optimized MIR for layout).
+        if tcx.type_of(body.source.def_id()).instantiate_identity().is_coroutine() {
             return;
         }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index eb1c7db026e..82fee7c8dfe 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -855,7 +855,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             | mir::TerminatorKind::UnwindResume
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::Unreachable => {}
-            mir::TerminatorKind::GeneratorDrop
+            mir::TerminatorKind::CoroutineDrop
             | mir::TerminatorKind::Yield { .. }
             | mir::TerminatorKind::FalseEdge { .. }
             | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 1d8cbe0e21b..4009e289240 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -105,7 +105,6 @@ use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathDataName;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
-use rustc_middle::mir;
 use rustc_middle::mir::mono::{
     CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
     Visibility,
@@ -1279,38 +1278,8 @@ fn dump_mono_items_stats<'tcx>(
     Ok(())
 }
 
-fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
-    let (items, cgus) = tcx.collect_and_partition_mono_items(());
-    let mut visited = DefIdSet::default();
-    let mut result = items.clone();
-
-    for cgu in cgus {
-        for item in cgu.items().keys() {
-            if let MonoItem::Fn(ref instance) = item {
-                let did = instance.def_id();
-                if !visited.insert(did) {
-                    continue;
-                }
-                let body = tcx.instance_mir(instance.def);
-                for block in body.basic_blocks.iter() {
-                    for statement in &block.statements {
-                        let mir::StatementKind::Coverage(_) = statement.kind else { continue };
-                        let scope = statement.source_info.scope;
-                        if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
-                            result.insert(inlined.def_id());
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    tcx.arena.alloc(result)
-}
-
 pub fn provide(providers: &mut Providers) {
     providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
-    providers.codegened_and_inlined_items = codegened_and_inlined_items;
 
     providers.is_codegened_item = |tcx, def_id| {
         let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 6c206a6bac8..a3b35eab465 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -131,7 +131,7 @@ fn mark_used_by_default_parameters<'tcx>(
     unused_parameters: &mut UnusedGenericParams,
 ) {
     match tcx.def_kind(def_id) {
-        DefKind::Closure | DefKind::Generator => {
+        DefKind::Closure | DefKind::Coroutine => {
             for param in &generics.params {
                 debug!(?param, "(closure/gen)");
                 unused_parameters.mark_used(param.index);
@@ -227,7 +227,7 @@ struct MarkUsedGenericParams<'a, 'tcx> {
 
 impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
     /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
-    /// a closure, generator or constant).
+    /// a closure, coroutine or constant).
     #[instrument(level = "debug", skip(self, def_id, args))]
     fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
         let instance = ty::InstanceDef::Item(def_id);
@@ -248,8 +248,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
         if local == Local::from_usize(1) {
             let def_kind = self.tcx.def_kind(self.def_id);
-            if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
-                // Skip visiting the closure/generator that is currently being processed. This only
+            if matches!(def_kind, DefKind::Closure | DefKind::Coroutine) {
+                // Skip visiting the closure/coroutine that is currently being processed. This only
                 // happens because the first argument to the closure is a reference to itself and
                 // that will call `visit_args`, resulting in each generic parameter captured being
                 // considered used by default.
@@ -319,14 +319,14 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
         }
 
         match *ty.kind() {
-            ty::Closure(def_id, args) | ty::Generator(def_id, args, ..) => {
+            ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
                 debug!(?def_id);
-                // Avoid cycle errors with generators.
+                // Avoid cycle errors with coroutines.
                 if def_id == self.def_id {
                     return ControlFlow::Continue(());
                 }
 
-                // Consider any generic parameters used by any closures/generators as used in the
+                // Consider any generic parameters used by any closures/coroutines as used in the
                 // parent.
                 self.visit_child_body(def_id, args);
                 ControlFlow::Continue(())
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 44cb90227e7..5157106f4e2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1848,7 +1848,7 @@ impl<'a> Parser<'a> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Yield(self.parse_expr_opt()?);
         let span = lo.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::generators, span);
+        self.sess.gated_spans.gate(sym::coroutines, span);
         let expr = self.mk_expr(span, kind);
         self.maybe_recover_from_bad_qpath(expr)
     }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 7e837243918..2aec4ea7ef1 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -149,7 +149,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
         // Now check whether the lang_item has the expected number of generic
         // arguments. Generally speaking, binary and indexing operations have
         // one (for the RHS/index), unary operations have none, the closure
-        // traits have one for the argument list, generators have one for the
+        // traits have one for the argument list, coroutines have one for the
         // resume argument, and ordering/equality relations have one for the RHS
         // Some other types like Box and various functions like drop_in_place
         // have minimum requirements.
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 1fe44b2b877..d068fe62473 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -706,7 +706,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         //
         // When computing the liveness for captured variables we take into
         // account how variable is captured (ByRef vs ByValue) and what is the
-        // closure kind (Generator / FnOnce vs Fn / FnMut).
+        // closure kind (Coroutine / FnOnce vs Fn / FnMut).
         //
         // Variables captured by reference are assumed to be used on the exit
         // from the closure.
@@ -752,7 +752,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 ty::ClosureKind::FnMut => {}
                 ty::ClosureKind::FnOnce => return succ,
             },
-            ty::Generator(..) => return succ,
+            ty::Coroutine(..) => return succ,
             _ => {
                 span_bug!(
                     body.value.span,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 5599c6100a5..f2d6a0dff9c 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -188,7 +188,7 @@ where
             | ty::Foreign(def_id)
             | ty::FnDef(def_id, ..)
             | ty::Closure(def_id, ..)
-            | ty::Generator(def_id, ..) => {
+            | ty::Coroutine(def_id, ..) => {
                 self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
                 if V::SHALLOW {
                     return ControlFlow::Continue(());
@@ -294,7 +294,7 @@ where
             | ty::Param(..)
             | ty::Bound(..)
             | ty::Error(_)
-            | ty::GeneratorWitness(..) => {}
+            | ty::CoroutineWitness(..) => {}
             ty::Placeholder(..) | ty::Infer(..) => {
                 bug!("unexpected type: {:?}", ty)
             }
@@ -666,7 +666,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             | DefKind::GlobalAsm
             | DefKind::Impl { .. }
             | DefKind::Closure
-            | DefKind::Generator => (),
+            | DefKind::Coroutine => (),
         }
     }
 }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a18109574fe..0407db528af 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -981,7 +981,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 | DefKind::GlobalAsm
                 | DefKind::Closure
                 | DefKind::Impl { .. }
-                | DefKind::Generator,
+                | DefKind::Coroutine,
                 _,
             )
             | Res::Local(..)
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 925ee615b09..4ad838e5aed 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1511,9 +1511,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 ),
             );
         }
+
+        let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
+            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+            && let Some(span) = suggestion.span
+            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix("_")
+            && snippet == candidate
+        {
+            // When the suggested binding change would be from `x` to `_x`, suggest changing the
+            // original binding definition instead. (#60164)
+            (span, snippet, ", consider changing it")
+        } else {
+            (span, suggestion.candidate.to_string(), "")
+        };
         let msg = match suggestion.target {
             SuggestionTarget::SimilarlyNamed => format!(
-                "{} {} with a similar name exists",
+                "{} {} with a similar name exists{post}",
                 suggestion.res.article(),
                 suggestion.res.descr()
             ),
@@ -1521,7 +1534,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 format!("maybe you meant this {}", suggestion.res.descr())
             }
         };
-        err.span_suggestion(span, msg, suggestion.candidate, Applicability::MaybeIncorrect);
+        err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
         true
     }
 
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index df81e1f8305..f792b8f2cdd 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -24,7 +24,7 @@ pub enum SizeKind {
 pub enum FieldKind {
     AdtField,
     Upvar,
-    GeneratorLocal,
+    CoroutineLocal,
 }
 
 impl std::fmt::Display for FieldKind {
@@ -32,7 +32,7 @@ impl std::fmt::Display for FieldKind {
         match self {
             FieldKind::AdtField => write!(w, "field"),
             FieldKind::Upvar => write!(w, "upvar"),
-            FieldKind::GeneratorLocal => write!(w, "local"),
+            FieldKind::CoroutineLocal => write!(w, "local"),
         }
     }
 }
@@ -52,7 +52,7 @@ pub enum DataTypeKind {
     Union,
     Enum,
     Closure,
-    Generator,
+    Coroutine,
 }
 
 #[derive(PartialEq, Eq, Hash, Debug)]
@@ -105,9 +105,9 @@ impl CodeStats {
         // Sort variants so the largest ones are shown first. A stable sort is
         // used here so that source code order is preserved for all variants
         // that have the same size.
-        // Except for Generators, whose variants are already sorted according to
-        // their yield points in `variant_info_for_generator`.
-        if kind != DataTypeKind::Generator {
+        // Except for Coroutines, whose variants are already sorted according to
+        // their yield points in `variant_info_for_coroutine`.
+        if kind != DataTypeKind::Coroutine {
             variants.sort_by_key(|info| cmp::Reverse(info.size));
         }
         let info = TypeSizeInfo {
@@ -160,7 +160,7 @@ impl CodeStats {
 
             let struct_like = match kind {
                 DataTypeKind::Struct | DataTypeKind::Closure => true,
-                DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Generator => false,
+                DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Coroutine => false,
             };
             for (i, variant_info) in variants.into_iter().enumerate() {
                 let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
new file mode 100644
index 00000000000..f42a9739320
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -0,0 +1,61 @@
+//! Module containing the translation from stable mir constructs to the rustc counterpart.
+//!
+//! This module will only include a few constructs to allow users to invoke internal rustc APIs
+//! due to incomplete stable coverage.
+
+// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
+use crate::rustc_smir::{MaybeStable, Tables};
+use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
+use stable_mir::ty::{Const, GenericArgKind, GenericArgs, Region, Ty};
+use stable_mir::DefId;
+
+use super::RustcInternal;
+
+impl<'tcx> RustcInternal<'tcx> for DefId {
+    type T = rustc_span::def_id::DefId;
+    fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        tables.def_ids[*self]
+    }
+}
+
+impl<'tcx> RustcInternal<'tcx> for GenericArgs {
+    type T = rustc_ty::GenericArgsRef<'tcx>;
+    fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        tables.tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables)))
+    }
+}
+
+impl<'tcx> RustcInternal<'tcx> for GenericArgKind {
+    type T = rustc_ty::GenericArg<'tcx>;
+    fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self {
+            GenericArgKind::Lifetime(reg) => reg.internal(tables).into(),
+            GenericArgKind::Type(ty) => ty.internal(tables).into(),
+            GenericArgKind::Const(cnst) => cnst.internal(tables).into(),
+        }
+    }
+}
+
+impl<'tcx> RustcInternal<'tcx> for Region {
+    type T = rustc_ty::Region<'tcx>;
+    fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+        todo!()
+    }
+}
+
+impl<'tcx> RustcInternal<'tcx> for Ty {
+    type T = InternalTy<'tcx>;
+    fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match tables.types[self.0] {
+            MaybeStable::Stable(_) => todo!(),
+            MaybeStable::Rustc(ty) => ty,
+        }
+    }
+}
+
+impl<'tcx> RustcInternal<'tcx> for Const {
+    type T = rustc_ty::Const<'tcx>;
+    fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+        todo!()
+    }
+}
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 5ea805e5739..b1ea5e898b8 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -20,6 +20,8 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::{ControlFlow, Index};
 
+mod internal;
+
 impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
     type Output = DefId;
 
@@ -59,8 +61,8 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::ClosureDef(self.create_def_id(did))
     }
 
-    pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
-        stable_mir::ty::GeneratorDef(self.create_def_id(did))
+    pub fn coroutine_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineDef {
+        stable_mir::ty::CoroutineDef(self.create_def_id(did))
     }
 
     pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
@@ -231,3 +233,11 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
         k
     }
 }
+
+/// Trait used to translate a stable construct to its rustc counterpart.
+///
+/// This is basically a mirror of [crate::rustc_smir::Stable].
+pub(crate) trait RustcInternal<'tcx> {
+    type T;
+    fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T;
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
new file mode 100644
index 00000000000..8ff3958da7b
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -0,0 +1,55 @@
+//! Logic required to produce a monomorphic stable body.
+//!
+//! We first retrieve and monomorphize the rustc body representation, i.e., we generate a
+//! monomorphic body using internal representation.
+//! After that, we convert the internal representation into a stable one.
+use crate::rustc_smir::{Stable, Tables};
+use rustc_middle::mir;
+use rustc_middle::mir::visit::MutVisitor;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+/// Builds a monomorphic body for a given instance.
+pub struct BodyBuilder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    instance: ty::Instance<'tcx>,
+}
+
+impl<'tcx> BodyBuilder<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
+        BodyBuilder { tcx, instance }
+    }
+
+    pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
+        let mut body = self.tcx.instance_mir(self.instance.def).clone();
+        let generics = self.tcx.generics_of(self.instance.def_id());
+        if generics.requires_monomorphization(self.tcx) {
+            self.visit_body(&mut body);
+        }
+        body.stable(tables)
+    }
+
+    fn monomorphize<T>(&self, value: T) -> T
+    where
+        T: ty::TypeFoldable<TyCtxt<'tcx>>,
+    {
+        self.instance.instantiate_mir_and_normalize_erasing_regions(
+            self.tcx,
+            ty::ParamEnv::reveal_all(),
+            ty::EarlyBinder::bind(value),
+        )
+    }
+}
+
+impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
+    fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, _location: mir::Location) {
+        *ct = self.monomorphize(*ct);
+    }
+
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: mir::visit::TyContext) {
+        *ty = self.monomorphize(*ty);
+    }
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 94dc15b4767..d5379797f1c 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,7 +7,7 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
-use crate::rustc_internal::IndexMap;
+use crate::rustc_internal::{IndexMap, RustcInternal};
 use crate::rustc_smir::hir::def::DefKind;
 use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
 use rustc_hir as hir;
@@ -26,6 +26,7 @@ use stable_mir::{self, opaque, Context, Filename};
 use tracing::debug;
 
 mod alloc;
+mod builder;
 
 impl<'tcx> Context for Tables<'tcx> {
     fn local_crate(&self) -> stable_mir::Crate {
@@ -171,8 +172,9 @@ impl<'tcx> Context for Tables<'tcx> {
         }
     }
 
-    fn instance_body(&mut self, _def: InstanceDef) -> Body {
-        todo!("Monomorphize the body")
+    fn instance_body(&mut self, def: InstanceDef) -> Body {
+        let instance = self.instances[def];
+        builder::BodyBuilder::new(self.tcx, instance).build(self)
     }
 
     fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty {
@@ -195,9 +197,21 @@ impl<'tcx> Context for Tables<'tcx> {
         let def_id = self[def_id];
         let generics = self.tcx.generics_of(def_id);
         let result = generics.requires_monomorphization(self.tcx);
-        println!("req {result}: {def_id:?}");
         result
     }
+
+    fn resolve_instance(
+        &mut self,
+        def: stable_mir::ty::FnDef,
+        args: &stable_mir::ty::GenericArgs,
+    ) -> Option<stable_mir::mir::mono::Instance> {
+        let def_id = def.0.internal(self);
+        let args_ref = args.internal(self);
+        match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
+            Ok(Some(instance)) => Some(instance.stable(self)),
+            Ok(None) | Err(_) => None,
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -768,11 +782,11 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
             AssertKind::RemainderByZero(op) => {
                 stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
             }
-            AssertKind::ResumedAfterReturn(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable(tables))
+            AssertKind::ResumedAfterReturn(coroutine) => {
+                stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
             }
-            AssertKind::ResumedAfterPanic(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable(tables))
+            AssertKind::ResumedAfterPanic(coroutine) => {
+                stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
             }
             AssertKind::MisalignedPointerDereference { required, found } => {
                 stable_mir::mir::AssertMessage::MisalignedPointerDereference {
@@ -849,9 +863,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
                     generic_arg.stable(tables),
                 )
             }
-            mir::AggregateKind::Generator(def_id, generic_arg, movability) => {
-                stable_mir::mir::AggregateKind::Generator(
-                    tables.generator_def(*def_id),
+            mir::AggregateKind::Coroutine(def_id, generic_arg, movability) => {
+                stable_mir::mir::AggregateKind::Coroutine(
+                    tables.coroutine_def(*def_id),
                     generic_arg.stable(tables),
                     movability.stable(tables),
                 )
@@ -860,20 +874,20 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind {
-    type T = stable_mir::mir::GeneratorKind;
+impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
+    type T = stable_mir::mir::CoroutineKind;
     fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
-        use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
+        use rustc_hir::{AsyncCoroutineKind, CoroutineKind};
         match self {
-            GeneratorKind::Async(async_gen) => {
+            CoroutineKind::Async(async_gen) => {
                 let async_gen = match async_gen {
-                    AsyncGeneratorKind::Block => stable_mir::mir::AsyncGeneratorKind::Block,
-                    AsyncGeneratorKind::Closure => stable_mir::mir::AsyncGeneratorKind::Closure,
-                    AsyncGeneratorKind::Fn => stable_mir::mir::AsyncGeneratorKind::Fn,
+                    AsyncCoroutineKind::Block => stable_mir::mir::AsyncCoroutineKind::Block,
+                    AsyncCoroutineKind::Closure => stable_mir::mir::AsyncCoroutineKind::Closure,
+                    AsyncCoroutineKind::Fn => stable_mir::mir::AsyncCoroutineKind::Fn,
                 };
-                stable_mir::mir::GeneratorKind::Async(async_gen)
+                stable_mir::mir::CoroutineKind::Async(async_gen)
             }
-            GeneratorKind::Gen => stable_mir::mir::GeneratorKind::Gen,
+            CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine,
         }
     }
 }
@@ -976,7 +990,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 unwind: unwind.stable(tables),
             },
             mir::TerminatorKind::Yield { .. }
-            | mir::TerminatorKind::GeneratorDrop
+            | mir::TerminatorKind::CoroutineDrop
             | mir::TerminatorKind::FalseEdge { .. }
             | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
         }
@@ -1231,8 +1245,8 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
                 tables.closure_def(*def_id),
                 generic_args.stable(tables),
             )),
-            ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
-                tables.generator_def(*def_id),
+            ty::Coroutine(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Coroutine(
+                tables.coroutine_def(*def_id),
                 generic_args.stable(tables),
                 movability.stable(tables),
             )),
@@ -1247,7 +1261,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
             ty::Bound(debruijn_idx, bound_ty) => {
                 TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
             }
-            ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => {
+            ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
                 unreachable!();
             }
         }
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index ee93f74e750..31c2a56faa5 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -13,7 +13,6 @@ rustc_index = { path = "../rustc_index" }
 rustc_arena = { path = "../rustc_arena" }
 scoped-tls = "1.0"
 unicode-width = "0.1.4"
-cfg-if = "1.0"
 tracing = "0.1"
 sha1 = "0.10.0"
 sha2 = "0.10.1"
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index 450d5455ff9..7da7dc610ec 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -33,8 +33,8 @@ pub fn analyze_source_file(
     (lines, multi_byte_chars, non_narrow_chars)
 }
 
-cfg_if::cfg_if! {
-    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
+cfg_match! {
+    cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
         fn analyze_source_file_dispatch(src: &str,
                                     lines: &mut Vec<RelativeBytePos>,
                                     multi_byte_chars: &mut Vec<MultiByteChar>,
@@ -172,8 +172,8 @@ cfg_if::cfg_if! {
                                         non_narrow_chars);
             }
         }
-    } else {
-
+    }
+    _ => {
         // The target (or compiler version) does not support SSE2 ...
         fn analyze_source_file_dispatch(src: &str,
                                     lines: &mut Vec<RelativeBytePos>,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 49b4042d148..8bb64aa5f12 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -13,21 +13,24 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+// tidy-alphabetical-start
+#![allow(internal_features)]
 #![cfg_attr(not(bootstrap), doc(rust_logo))]
 #![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![deny(rustc::diagnostic_outside_of_impl)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
+#![feature(cfg_match)]
 #![feature(if_let_guard)]
-#![feature(negative_impls)]
-#![feature(min_specialization)]
-#![feature(rustc_attrs)]
 #![feature(let_chains)]
-#![feature(round_char_boundary)]
-#![feature(read_buf)]
+#![feature(min_specialization)]
+#![feature(negative_impls)]
 #![feature(new_uninit)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-#![allow(internal_features)]
+#![feature(read_buf)]
+#![feature(round_char_boundary)]
+#![feature(rustc_attrs)]
+// tidy-alphabetical-end
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index be8c65862dc..5b58cf8b6d6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -591,6 +591,10 @@ symbols! {
         core_panic_2015_macro,
         core_panic_2021_macro,
         core_panic_macro,
+        coroutine,
+        coroutine_clone,
+        coroutine_state,
+        coroutines,
         cosf32,
         cosf64,
         count,
@@ -815,9 +819,7 @@ symbols! {
         ge,
         gen_future,
         gen_kill,
-        generator,
         generator_clone,
-        generator_state,
         generators,
         generic_arg_infer,
         generic_assert,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 5290da9a25b..5f22b89ea49 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -214,7 +214,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
             ty::FnDef(def_id, args)
             | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
             | ty::Closure(def_id, args)
-            | ty::Generator(def_id, args, _) => self.print_def_path(def_id, args),
+            | ty::Coroutine(def_id, args, _) => self.print_def_path(def_id, args),
 
             // The `pretty_print_type` formatting of array size depends on
             // -Zverbose flag, so we cannot reuse it here.
@@ -284,7 +284,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
-            ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Generator(..)
+            ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Coroutine(..)
                 if trait_ref.is_none() =>
             {
                 self.print_type(self_ty)
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 6ade2d777c7..7b4ab67a24d 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -238,7 +238,7 @@ fn compute_symbol_name<'tcx>(
     // and we want to be sure to avoid any symbol conflicts here.
     let is_globally_shared_function = matches!(
         tcx.def_kind(instance.def_id()),
-        DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator | DefKind::Ctor(..)
+        DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Coroutine | DefKind::Ctor(..)
     ) && matches!(
         MonoItem::Fn(instance).instantiation_mode(tcx),
         InstantiationMode::GloballyShared { may_conflict: true }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 6ad3e7155e8..5ce188488ce 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -639,7 +639,7 @@ fn encode_ty<'tcx>(
             typeid.push_str(&s);
         }
 
-        ty::Generator(def_id, args, ..) => {
+        ty::Coroutine(def_id, args, ..) => {
             // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
             // as vendor extended type.
             let mut s = String::new();
@@ -648,7 +648,7 @@ fn encode_ty<'tcx>(
             // Encode parent args only
             s.push_str(&encode_args(
                 tcx,
-                tcx.mk_args(args.as_generator().parent_args()),
+                tcx.mk_args(args.as_coroutine().parent_args()),
                 dict,
                 options,
             ));
@@ -719,7 +719,7 @@ fn encode_ty<'tcx>(
         ty::Alias(..)
         | ty::Bound(..)
         | ty::Error(..)
-        | ty::GeneratorWitness(..)
+        | ty::CoroutineWitness(..)
         | ty::Infer(..)
         | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
@@ -778,7 +778,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         | ty::Str
         | ty::Never
         | ty::Foreign(..)
-        | ty::GeneratorWitness(..) => {}
+        | ty::CoroutineWitness(..) => {}
 
         ty::Bool => {
             if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
@@ -892,8 +892,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
             ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options));
         }
 
-        ty::Generator(def_id, args, movability) => {
-            ty = Ty::new_generator(tcx, *def_id, transform_args(tcx, args, options), *movability);
+        ty::Coroutine(def_id, args, movability) => {
+            ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options), *movability);
         }
 
         ty::Ref(region, ty0, ..) => {
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 99c5d016439..89b8b1518b0 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -427,7 +427,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             | ty::FnDef(def_id, args)
             | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
             | ty::Closure(def_id, args)
-            | ty::Generator(def_id, args, _) => {
+            | ty::Coroutine(def_id, args, _) => {
                 self = self.print_def_path(def_id, args)?;
             }
             ty::Foreign(def_id) => {
@@ -476,7 +476,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
             ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
             ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"),
-            ty::GeneratorWitness(..) => bug!("symbol_names: unexpected `GeneratorWitness`"),
+            ty::CoroutineWitness(..) => bug!("symbol_names: unexpected `CoroutineWitness`"),
         }
 
         // Only cache types that do not refer to an enclosing
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 23d2c0c4ea0..0c214ca8753 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -191,18 +191,18 @@ pub(super) trait GoalKind<'tcx>:
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    /// A generator (that comes from an `async` desugaring) is known to implement
-    /// `Future<Output = O>`, where `O` is given by the generator's return type
+    /// A coroutine (that comes from an `async` desugaring) is known to implement
+    /// `Future<Output = O>`, where `O` is given by the coroutine's return type
     /// that was computed during type-checking.
     fn consider_builtin_future_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
-    /// A generator (that doesn't come from an `async` desugaring) is known to
-    /// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
-    /// and return types of the generator computed during type-checking.
-    fn consider_builtin_generator_candidate(
+    /// A coroutine (that doesn't come from an `async` desugaring) is known to
+    /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
+    /// and return types of the coroutine computed during type-checking.
+    fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
@@ -410,7 +410,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::FnPtr(_)
             | ty::Dynamic(_, _, _)
             | ty::Closure(_, _)
-            | ty::Generator(_, _, _)
+            | ty::Coroutine(_, _, _)
             | ty::Never
             | ty::Tuple(_) => {
                 let simp =
@@ -467,9 +467,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),
 
             // FIXME: These should ideally not exist as a self type. It would be nice for
-            // the builtin auto trait impls of generators to instead directly recurse
+            // the builtin auto trait impls of coroutines to instead directly recurse
             // into the witness.
-            ty::GeneratorWitness(..) => (),
+            ty::CoroutineWitness(..) => (),
 
             // These variants should not exist as a self type.
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
@@ -553,7 +553,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         } else if lang_items.future_trait() == Some(trait_def_id) {
             G::consider_builtin_future_candidate(self, goal)
         } else if lang_items.gen_trait() == Some(trait_def_id) {
-            G::consider_builtin_generator_candidate(self, goal)
+            G::consider_builtin_coroutine_candidate(self, goal)
         } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
             G::consider_builtin_discriminant_kind_candidate(self, goal)
         } else if lang_items.destruct_trait() == Some(trait_def_id) {
@@ -620,8 +620,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::FnPtr(_)
             | ty::Dynamic(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Param(_)
@@ -776,8 +776,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::FnPtr(_)
             | ty::Alias(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Param(_)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 26c68acddff..d655a4106b8 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -12,7 +12,7 @@ use crate::solve::EvalCtxt;
 
 // Calculates the constituent types of a type for `auto trait` purposes.
 //
-// For types with an "existential" binder, i.e. generator witnesses, we also
+// For types with an "existential" binder, i.e. coroutine witnesses, we also
 // instantiate the binder with placeholders eagerly.
 pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
     ecx: &EvalCtxt<'_, 'tcx>,
@@ -56,14 +56,14 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
 
         ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
 
-        ty::Generator(_, ref args, _) => {
-            let generator_args = args.as_generator();
-            Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()])
+        ty::Coroutine(_, ref args, _) => {
+            let coroutine_args = args.as_coroutine();
+            Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
         }
 
-        ty::GeneratorWitness(def_id, args) => Ok(ecx
+        ty::CoroutineWitness(def_id, args) => Ok(ecx
             .tcx()
-            .generator_hidden_types(def_id)
+            .coroutine_hidden_types(def_id)
             .map(|bty| {
                 ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
                     tcx,
@@ -122,8 +122,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
         | ty::RawPtr(..)
         | ty::Char
         | ty::Ref(..)
-        | ty::Generator(..)
-        | ty::GeneratorWitness(..)
+        | ty::Coroutine(..)
+        | ty::CoroutineWitness(..)
         | ty::Array(..)
         | ty::Closure(..)
         | ty::Never
@@ -174,7 +174,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
         ty::Dynamic(..)
         | ty::Str
         | ty::Slice(_)
-        | ty::Generator(_, _, Movability::Static)
+        | ty::Coroutine(_, _, Movability::Static)
         | ty::Foreign(..)
         | ty::Ref(_, _, Mutability::Mut)
         | ty::Adt(_, _)
@@ -191,18 +191,18 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
 
         ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
 
-        ty::Generator(_, args, Movability::Movable) => {
-            if ecx.tcx().features().generator_clone {
-                let generator = args.as_generator();
-                Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
+        ty::Coroutine(_, args, Movability::Movable) => {
+            if ecx.tcx().features().coroutine_clone {
+                let coroutine = args.as_coroutine();
+                Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])
             } else {
                 Err(NoSolution)
             }
         }
 
-        ty::GeneratorWitness(def_id, args) => Ok(ecx
+        ty::CoroutineWitness(def_id, args) => Ok(ecx
             .tcx()
-            .generator_hidden_types(def_id)
+            .coroutine_hidden_types(def_id)
             .map(|bty| {
                 ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
                     ecx.tcx(),
@@ -275,8 +275,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         | ty::RawPtr(_)
         | ty::Ref(_, _, _)
         | ty::Dynamic(_, _, _)
-        | ty::Generator(_, _, _)
-        | ty::GeneratorWitness(..)
+        | ty::Coroutine(_, _, _)
+        | ty::CoroutineWitness(..)
         | ty::Never
         | ty::Tuple(_)
         | ty::Alias(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index aa92b924ef2..19f0c9fe826 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -329,8 +329,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
             | ty::FnPtr(_)
             | ty::Dynamic(_, _, _)
             | ty::Closure(_, _)
-            | ty::Generator(_, _, _)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(_, _, _)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Alias(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs
index 73c8d0c85dd..4950a444ffb 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs
@@ -392,8 +392,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 | ty::FnPtr(..)
                 | ty::Closure(..)
                 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
-                | ty::Generator(..)
-                | ty::GeneratorWitness(..)
+                | ty::Coroutine(..)
+                | ty::CoroutineWitness(..)
                 | ty::Never
                 | ty::Foreign(..) => tcx.types.unit,
 
@@ -459,17 +459,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+        let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
-        // Generators are not futures unless they come from `async` desugaring
+        // Coroutines are not futures unless they come from `async` desugaring
         let tcx = ecx.tcx();
-        if !tcx.generator_is_async(def_id) {
+        if !tcx.coroutine_is_async(def_id) {
             return Err(NoSolution);
         }
 
-        let term = args.as_generator().return_ty().into();
+        let term = args.as_coroutine().return_ty().into();
 
         Self::consider_implied_clause(
             ecx,
@@ -480,35 +480,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             }
             .to_predicate(tcx),
             // Technically, we need to check that the future type is Sized,
-            // but that's already proven by the generator being WF.
+            // but that's already proven by the coroutine being WF.
             [],
         )
     }
 
-    fn consider_builtin_generator_candidate(
+    fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+        let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
-        // `async`-desugared generators do not implement the generator trait
+        // `async`-desugared coroutines do not implement the coroutine trait
         let tcx = ecx.tcx();
-        if tcx.generator_is_async(def_id) {
+        if tcx.coroutine_is_async(def_id) {
             return Err(NoSolution);
         }
 
-        let generator = args.as_generator();
+        let coroutine = args.as_coroutine();
 
         let name = tcx.associated_item(goal.predicate.def_id()).name;
         let term = if name == sym::Return {
-            generator.return_ty().into()
+            coroutine.return_ty().into()
         } else if name == sym::Yield {
-            generator.yield_ty().into()
+            coroutine.yield_ty().into()
         } else {
-            bug!("unexpected associated item `<{self_ty} as Generator>::{name}`")
+            bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`")
         };
 
         Self::consider_implied_clause(
@@ -518,13 +518,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 projection_ty: ty::AliasTy::new(
                     ecx.tcx(),
                     goal.predicate.def_id(),
-                    [self_ty, generator.resume_ty()],
+                    [self_ty, coroutine.resume_ty()],
                 ),
                 term,
             }
             .to_predicate(tcx),
             // Technically, we need to check that the future type is Sized,
-            // but that's already proven by the generator being WF.
+            // but that's already proven by the coroutine being WF.
             [],
         )
     }
@@ -561,8 +561,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             | ty::FnPtr(..)
             | ty::Closure(..)
             | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Foreign(..)
             | ty::Adt(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index d87e05ad02f..fa91a125b6a 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -319,23 +319,23 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else {
+        let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else {
             return Err(NoSolution);
         };
 
-        // Generators are not futures unless they come from `async` desugaring
+        // Coroutines are not futures unless they come from `async` desugaring
         let tcx = ecx.tcx();
-        if !tcx.generator_is_async(def_id) {
+        if !tcx.coroutine_is_async(def_id) {
             return Err(NoSolution);
         }
 
-        // Async generator unconditionally implement `Future`
+        // Async coroutine unconditionally implement `Future`
         // Technically, we need to check that the future output type is Sized,
-        // but that's already proven by the generator being WF.
+        // but that's already proven by the coroutine being WF.
         ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 
-    fn consider_builtin_generator_candidate(
+    fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
@@ -344,24 +344,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         }
 
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+        let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
-        // `async`-desugared generators do not implement the generator trait
+        // `async`-desugared coroutines do not implement the coroutine trait
         let tcx = ecx.tcx();
-        if tcx.generator_is_async(def_id) {
+        if tcx.coroutine_is_async(def_id) {
             return Err(NoSolution);
         }
 
-        let generator = args.as_generator();
+        let coroutine = args.as_coroutine();
         Self::consider_implied_clause(
             ecx,
             goal,
-            ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, generator.resume_ty()])
+            ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
                 .to_predicate(tcx),
-            // Technically, we need to check that the generator types are Sized,
-            // but that's already proven by the generator being WF.
+            // Technically, we need to check that the coroutine types are Sized,
+            // but that's already proven by the coroutine being WF.
             [],
         )
     }
@@ -844,10 +844,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
             ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
 
-            // Generators have one special built-in candidate, `Unpin`, which
+            // Coroutines have one special built-in candidate, `Unpin`, which
             // takes precedence over the structural auto trait candidate being
             // assembled.
-            ty::Generator(_, _, movability)
+            ty::Coroutine(_, _, movability)
                 if Some(goal.predicate.def_id()) == self.tcx().lang_items().unpin_trait() =>
             {
                 match movability {
@@ -879,8 +879,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::FnDef(_, _)
             | ty::FnPtr(_)
             | ty::Closure(_, _)
-            | ty::Generator(_, _, _)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(_, _, _)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(_)
             | ty::Adt(_, _)
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index acab4498a09..29b0c7189f9 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -817,7 +817,7 @@ where
                 }
             }
             ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
-            ty::Closure(did, ..) | ty::Generator(did, ..) => {
+            ty::Closure(did, ..) | ty::Coroutine(did, ..) => {
                 if self.def_id_is_local(did) {
                     ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
                 } else {
@@ -827,7 +827,7 @@ where
             // This should only be created when checking whether we have to check whether some
             // auto trait impl applies. There will never be multiple impls, so we can just
             // act as if it were a local type here.
-            ty::GeneratorWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
+            ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
             ty::Alias(ty::Opaque, ..) => {
                 // This merits some explanation.
                 // Normally, opaque types are not involved when performing
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 9c9b78f4152..016c44c20f6 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -102,7 +102,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let node = hir.find(hir_id)?;
         match &node {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
-                self.describe_generator(*body_id).or_else(|| {
+                self.describe_coroutine(*body_id).or_else(|| {
                     Some(match sig.header {
                         hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => {
                             "an async function"
@@ -114,11 +114,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
                 ..
-            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
+            }) => self.describe_coroutine(*body_id).or_else(|| Some("a trait method")),
             hir::Node::ImplItem(hir::ImplItem {
                 kind: hir::ImplItemKind::Fn(sig, body_id),
                 ..
-            }) => self.describe_generator(*body_id).or_else(|| {
+            }) => self.describe_coroutine(*body_id).or_else(|| {
                 Some(match sig.header {
                     hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method",
                     _ => "a method",
@@ -127,7 +127,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             hir::Node::Expr(hir::Expr {
                 kind: hir::ExprKind::Closure(hir::Closure { body, movability, .. }),
                 ..
-            }) => self.describe_generator(*body).or_else(|| {
+            }) => self.describe_coroutine(*body).or_else(|| {
                 Some(if movability.is_some() { "an async closure" } else { "a closure" })
             }),
             hir::Node::Expr(hir::Expr { .. }) => {
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 66529b67c17..78b466907b3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -22,7 +22,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::is_range_literal;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_hir::{AsyncCoroutineKind, CoroutineKind, Node};
 use rustc_hir::{Expr, HirId};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -47,37 +47,37 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 
 #[derive(Debug)]
-pub enum GeneratorInteriorOrUpvar {
+pub enum CoroutineInteriorOrUpvar {
     // span of interior type
     Interior(Span, Option<(Span, Option<Span>)>),
     // span of upvar
     Upvar(Span),
 }
 
-// This type provides a uniform interface to retrieve data on generators, whether it originated from
+// This type provides a uniform interface to retrieve data on coroutines, whether it originated from
 // the local crate being compiled or from a foreign crate.
 #[derive(Debug)]
-struct GeneratorData<'tcx, 'a>(&'a TypeckResults<'tcx>);
+struct CoroutineData<'tcx, 'a>(&'a TypeckResults<'tcx>);
 
-impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
-    /// Try to get information about variables captured by the generator that matches a type we are
+impl<'tcx, 'a> CoroutineData<'tcx, 'a> {
+    /// Try to get information about variables captured by the coroutine that matches a type we are
     /// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
     /// meet an obligation
     fn try_get_upvar_span<F>(
         &self,
         infer_context: &InferCtxt<'tcx>,
-        generator_did: DefId,
+        coroutine_did: DefId,
         ty_matches: F,
-    ) -> Option<GeneratorInteriorOrUpvar>
+    ) -> Option<CoroutineInteriorOrUpvar>
     where
         F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
     {
-        infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
+        infer_context.tcx.upvars_mentioned(coroutine_did).and_then(|upvars| {
             upvars.iter().find_map(|(upvar_id, upvar)| {
                 let upvar_ty = self.0.node_type(*upvar_id);
                 let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
                 ty_matches(ty::Binder::dummy(upvar_ty))
-                    .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
+                    .then(|| CoroutineInteriorOrUpvar::Upvar(upvar.span))
             })
         })
     }
@@ -244,9 +244,9 @@ pub trait TypeErrCtxtExt<'tcx> {
     fn note_obligation_cause_for_async_await(
         &self,
         err: &mut Diagnostic,
-        interior_or_upvar_span: GeneratorInteriorOrUpvar,
+        interior_or_upvar_span: CoroutineInteriorOrUpvar,
         is_async: bool,
-        outer_generator: Option<DefId>,
+        outer_coroutine: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
         obligation: &PredicateObligation<'tcx>,
@@ -1644,7 +1644,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
             // use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
             if let Some((_, hir::Node::Expr(await_expr))) = hir.parent_iter(*hir_id).nth(1)
-                && let Some(expr_span) = expr.span.find_ancestor_inside(await_expr.span)
+                && let Some(expr_span) = expr.span.find_ancestor_inside_same_ctxt(await_expr.span)
             {
                 let removal_span = self
                     .tcx
@@ -1982,7 +1982,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let argument_kind = match expected.skip_binder().self_ty().kind() {
             ty::Closure(..) => "closure",
-            ty::Generator(..) => "generator",
+            ty::Coroutine(..) => "coroutine",
             _ => "function",
         };
         let mut err = struct_span_err!(
@@ -2144,33 +2144,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let hir = self.tcx.hir();
 
         // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator to be present.
+        // for a coroutine to be present.
         //
         // When a future does not implement a trait because of a captured type in one of the
-        // generators somewhere in the call stack, then the result is a chain of obligations.
+        // coroutines somewhere in the call stack, then the result is a chain of obligations.
         //
         // Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
         // future is passed as an argument to a function C which requires a `Send` type, then the
         // chain looks something like this:
         //
-        // - `BuiltinDerivedObligation` with a generator witness (B)
-        // - `BuiltinDerivedObligation` with a generator (B)
+        // - `BuiltinDerivedObligation` with a coroutine witness (B)
+        // - `BuiltinDerivedObligation` with a coroutine (B)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with a generator witness (A)
-        // - `BuiltinDerivedObligation` with a generator (A)
+        // - `BuiltinDerivedObligation` with a coroutine witness (A)
+        // - `BuiltinDerivedObligation` with a coroutine (A)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BindingObligation` with `impl_send` (Send requirement)
         //
-        // The first obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator (`outer_generator` below) has information about where the
-        // bound was introduced. At least one generator should be present for this diagnostic to be
+        // The first obligation in the chain is the most useful and has the coroutine that captured
+        // the type. The last coroutine (`outer_coroutine` below) has information about where the
+        // bound was introduced. At least one coroutine should be present for this diagnostic to be
         // modified.
         let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) => (Some(p), Some(p.self_ty())),
             _ => (None, None),
         };
-        let mut generator = None;
-        let mut outer_generator = None;
+        let mut coroutine = None;
+        let mut outer_coroutine = None;
         let mut next_code = Some(obligation.cause.code());
 
         let mut seen_upvar_tys_infer_tuple = false;
@@ -2190,18 +2190,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     );
 
                     match *ty.kind() {
-                        ty::Generator(did, ..) | ty::GeneratorWitness(did, _) => {
-                            generator = generator.or(Some(did));
-                            outer_generator = Some(did);
+                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
+                            coroutine = coroutine.or(Some(did));
+                            outer_coroutine = Some(did);
                         }
                         ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
                             // By introducing a tuple of upvar types into the chain of obligations
-                            // of a generator, the first non-generator item is now the tuple itself,
+                            // of a coroutine, the first non-coroutine item is now the tuple itself,
                             // we shall ignore this.
 
                             seen_upvar_tys_infer_tuple = true;
                         }
-                        _ if generator.is_none() => {
+                        _ if coroutine.is_none() => {
                             trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
                             target_ty = Some(ty);
                         }
@@ -2219,18 +2219,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     );
 
                     match *ty.kind() {
-                        ty::Generator(did, ..) | ty::GeneratorWitness(did, ..) => {
-                            generator = generator.or(Some(did));
-                            outer_generator = Some(did);
+                        ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
+                            coroutine = coroutine.or(Some(did));
+                            outer_coroutine = Some(did);
                         }
                         ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
                             // By introducing a tuple of upvar types into the chain of obligations
-                            // of a generator, the first non-generator item is now the tuple itself,
+                            // of a coroutine, the first non-coroutine item is now the tuple itself,
                             // we shall ignore this.
 
                             seen_upvar_tys_infer_tuple = true;
                         }
-                        _ if generator.is_none() => {
+                        _ if coroutine.is_none() => {
                             trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
                             target_ty = Some(ty);
                         }
@@ -2243,48 +2243,48 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         }
 
-        // Only continue if a generator was found.
-        debug!(?generator, ?trait_ref, ?target_ty);
-        let (Some(generator_did), Some(trait_ref), Some(target_ty)) =
-            (generator, trait_ref, target_ty)
+        // Only continue if a coroutine was found.
+        debug!(?coroutine, ?trait_ref, ?target_ty);
+        let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
+            (coroutine, trait_ref, target_ty)
         else {
             return false;
         };
 
-        let span = self.tcx.def_span(generator_did);
+        let span = self.tcx.def_span(coroutine_did);
 
-        let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
+        let coroutine_did_root = self.tcx.typeck_root_def_id(coroutine_did);
         debug!(
-            ?generator_did,
-            ?generator_did_root,
+            ?coroutine_did,
+            ?coroutine_did_root,
             typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
             ?span,
         );
 
-        let generator_body = generator_did
+        let coroutine_body = coroutine_did
             .as_local()
             .and_then(|def_id| hir.maybe_body_owned_by(def_id))
             .map(|body_id| hir.body(body_id));
         let mut visitor = AwaitsVisitor::default();
-        if let Some(body) = generator_body {
+        if let Some(body) = coroutine_body {
             visitor.visit_body(body);
         }
         debug!(awaits = ?visitor.awaits);
 
-        // Look for a type inside the generator interior that matches the target type to get
+        // Look for a type inside the coroutine interior that matches the target type to get
         // a span.
         let target_ty_erased = self.tcx.erase_regions(target_ty);
         let ty_matches = |ty| -> bool {
             // Careful: the regions for types that appear in the
-            // generator interior are not generally known, so we
+            // coroutine interior are not generally known, so we
             // want to erase them when comparing (and anyway,
             // `Send` and other bounds are generally unaffected by
             // the choice of region). When erasing regions, we
             // also have to erase late-bound regions. This is
-            // because the types that appear in the generator
+            // because the types that appear in the coroutine
             // interior generally contain "bound regions" to
             // represent regions that are part of the suspended
-            // generator frame. Bound regions are preserved by
+            // coroutine frame. Bound regions are preserved by
             // `erase_regions` and so we must also call
             // `erase_late_bound_regions`.
             let ty_erased = self.tcx.erase_late_bound_regions(ty);
@@ -2294,44 +2294,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             eq
         };
 
-        // Get the typeck results from the infcx if the generator is the function we are currently
+        // Get the typeck results from the infcx if the coroutine is the function we are currently
         // type-checking; otherwise, get them by performing a query. This is needed to avoid
-        // cycles. If we can't use resolved types because the generator comes from another crate,
+        // cycles. If we can't use resolved types because the coroutine comes from another crate,
         // we still provide a targeted error but without all the relevant spans.
-        let generator_data = match &self.typeck_results {
-            Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData(&t),
-            _ if generator_did.is_local() => {
-                GeneratorData(self.tcx.typeck(generator_did.expect_local()))
+        let coroutine_data = match &self.typeck_results {
+            Some(t) if t.hir_owner.to_def_id() == coroutine_did_root => CoroutineData(&t),
+            _ if coroutine_did.is_local() => {
+                CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
             }
             _ => return false,
         };
 
-        let generator_within_in_progress_typeck = match &self.typeck_results {
-            Some(t) => t.hir_owner.to_def_id() == generator_did_root,
+        let coroutine_within_in_progress_typeck = match &self.typeck_results {
+            Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
             _ => false,
         };
 
         let mut interior_or_upvar_span = None;
 
-        let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
+        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, hir, ty_matches);
         debug!(?from_awaited_ty);
 
         // Avoid disclosing internal information to downstream crates.
-        if generator_did.is_local()
+        if coroutine_did.is_local()
             // Try to avoid cycles.
-            && !generator_within_in_progress_typeck
-            && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
+            && !coroutine_within_in_progress_typeck
+            && let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
         {
-            debug!(?generator_info);
+            debug!(?coroutine_info);
             'find_source: for (variant, source_info) in
-                generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
+                coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
             {
                 debug!(?variant);
                 for &local in variant {
-                    let decl = &generator_info.field_tys[local];
+                    let decl = &coroutine_info.field_tys[local];
                     debug!(?decl);
                     if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
-                        interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
+                        interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
                             decl.source_info.span,
                             Some((source_info.span, from_awaited_ty)),
                         ));
@@ -2343,21 +2343,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         if interior_or_upvar_span.is_none() {
             interior_or_upvar_span =
-                generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
+                coroutine_data.try_get_upvar_span(&self, coroutine_did, ty_matches);
         }
 
-        if interior_or_upvar_span.is_none() && !generator_did.is_local() {
-            interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None));
+        if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
+            interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(span, None));
         }
 
         debug!(?interior_or_upvar_span);
         if let Some(interior_or_upvar_span) = interior_or_upvar_span {
-            let is_async = self.tcx.generator_is_async(generator_did);
+            let is_async = self.tcx.coroutine_is_async(coroutine_did);
             self.note_obligation_cause_for_async_await(
                 err,
                 interior_or_upvar_span,
                 is_async,
-                outer_generator,
+                outer_coroutine,
                 trait_ref,
                 target_ty,
                 obligation,
@@ -2375,9 +2375,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn note_obligation_cause_for_async_await(
         &self,
         err: &mut Diagnostic,
-        interior_or_upvar_span: GeneratorInteriorOrUpvar,
+        interior_or_upvar_span: CoroutineInteriorOrUpvar,
         is_async: bool,
-        outer_generator: Option<DefId>,
+        outer_coroutine: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
         obligation: &PredicateObligation<'tcx>,
@@ -2387,7 +2387,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let (await_or_yield, an_await_or_yield) =
             if is_async { ("await", "an await") } else { ("yield", "a yield") };
-        let future_or_generator = if is_async { "future" } else { "generator" };
+        let future_or_coroutine = if is_async { "future" } else { "coroutine" };
 
         // Special case the primary error message when send or sync is the trait that was
         // not implemented.
@@ -2400,34 +2400,34 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
             err.clear_code();
             err.set_primary_message(format!(
-                "{future_or_generator} cannot be {trait_verb} between threads safely"
+                "{future_or_coroutine} cannot be {trait_verb} between threads safely"
             ));
 
             let original_span = err.span.primary_span().unwrap();
             let mut span = MultiSpan::from_span(original_span);
 
-            let message = outer_generator
-                .and_then(|generator_did| {
-                    Some(match self.tcx.generator_kind(generator_did).unwrap() {
-                        GeneratorKind::Gen => format!("generator is not {trait_name}"),
-                        GeneratorKind::Async(AsyncGeneratorKind::Fn) => self
+            let message = outer_coroutine
+                .and_then(|coroutine_did| {
+                    Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
+                        CoroutineKind::Coroutine => format!("coroutine is not {trait_name}"),
+                        CoroutineKind::Async(AsyncCoroutineKind::Fn) => self
                             .tcx
-                            .parent(generator_did)
+                            .parent(coroutine_did)
                             .as_local()
                             .map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
                             .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("future returned by `{name}` is not {trait_name}")
                             })?,
-                        GeneratorKind::Async(AsyncGeneratorKind::Block) => {
+                        CoroutineKind::Async(AsyncCoroutineKind::Block) => {
                             format!("future created by async block is not {trait_name}")
                         }
-                        GeneratorKind::Async(AsyncGeneratorKind::Closure) => {
+                        CoroutineKind::Async(AsyncCoroutineKind::Closure) => {
                             format!("future created by async closure is not {trait_name}")
                         }
                     })
                 })
-                .unwrap_or_else(|| format!("{future_or_generator} is not {trait_name}"));
+                .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
 
             span.push_span_label(original_span, message);
             err.set_span(span);
@@ -2471,11 +2471,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             );
             err.span_note(
                 span,
-                format!("{future_or_generator} {trait_explanation} as this value is used across {an_await_or_yield}"),
+                format!("{future_or_coroutine} {trait_explanation} as this value is used across {an_await_or_yield}"),
             );
         };
         match interior_or_upvar_span {
-            GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
+            CoroutineInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
                 if let Some((yield_span, from_awaited_ty)) = interior_extra_info {
                     if let Some(await_span) = from_awaited_ty {
                         // The type causing this obligation is one being awaited at await_span.
@@ -2498,7 +2498,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
             }
-            GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
+            CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
                 // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
                 let non_send = match target_ty.kind() {
                     ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(&obligation) {
@@ -2665,6 +2665,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // Check for foreign traits being reachable.
                             self.tcx.visible_parent_map(()).get(&def_id).is_some()
                         };
+                        if Some(def_id) == self.tcx.lang_items().sized_trait()
+                            && let Some(hir::Node::TraitItem(hir::TraitItem {
+                                ident,
+                                kind: hir::TraitItemKind::Type(bounds, None),
+                                ..
+                            })) = tcx.hir().get_if_local(item_def_id)
+                            // Do not suggest relaxing if there is an explicit `Sized` obligation.
+                            && !bounds.iter()
+                                .filter_map(|bound| bound.trait_ref())
+                                .any(|tr| tr.trait_def_id() == self.tcx.lang_items().sized_trait())
+                        {
+                            let (span, separator) = if let [.., last] = bounds {
+                                (last.span().shrink_to_hi(), " +")
+                            } else {
+                                (ident.span.shrink_to_hi(), ":")
+                            };
+                            err.span_suggestion_verbose(
+                                span,
+                                "consider relaxing the implicit `Sized` restriction",
+                                format!("{separator} ?Sized"),
+                                Applicability::MachineApplicable,
+                            );
+                        }
                         if let DefKind::Trait = tcx.def_kind(item_def_id)
                             && !visible_item
                         {
@@ -2810,7 +2833,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 err.note("the return type of a function must have a statically known size");
             }
             ObligationCauseCode::SizedYieldType => {
-                err.note("the yield type of a generator must have a statically known size");
+                err.note("the yield type of a coroutine must have a statically known size");
             }
             ObligationCauseCode::AssignmentLhsSized => {
                 err.note("the left-hand-side of an assignment must have a statically known size");
@@ -2880,10 +2903,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     err.span_label(span, "this closure captures all values by move");
                 }
             }
-            ObligationCauseCode::SizedGeneratorInterior(generator_def_id) => {
-                let what = match self.tcx.generator_kind(generator_def_id) {
-                    None | Some(hir::GeneratorKind::Gen) => "yield",
-                    Some(hir::GeneratorKind::Async(..)) => "await",
+            ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => {
+                let what = match self.tcx.coroutine_kind(coroutine_def_id) {
+                    None | Some(hir::CoroutineKind::Coroutine) => "yield",
+                    Some(hir::CoroutineKind::Async(..)) => "await",
                 };
                 err.note(format!(
                     "all values live across `{what}` must have a statically known size"
@@ -2905,7 +2928,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     return;
                 }
 
-                // If the obligation for a tuple is set directly by a Generator or Closure,
+                // If the obligation for a tuple is set directly by a Coroutine or Closure,
                 // then the tuple must be the one containing capture types.
                 let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
                     false
@@ -2915,7 +2938,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let parent_trait_ref =
                             self.resolve_vars_if_possible(data.parent_trait_pred);
                         let nested_ty = parent_trait_ref.skip_binder().self_ty();
-                        matches!(nested_ty.kind(), ty::Generator(..))
+                        matches!(nested_ty.kind(), ty::Coroutine(..))
                             || matches!(nested_ty.kind(), ty::Closure(..))
                     } else {
                         false
@@ -2935,7 +2958,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             },
                             ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                                 // If the previous type is async fn, this is the future generated by the body of an async function.
-                                // Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
+                                // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below).
                                 let is_future = tcx.ty_is_opaque_future(ty);
                                 debug!(
                                     ?obligated_types,
@@ -2944,8 +2967,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 );
                                 if is_future
                                     && obligated_types.last().is_some_and(|ty| match ty.kind() {
-                                        ty::Generator(last_def_id, ..) => {
-                                            tcx.generator_is_async(*last_def_id)
+                                        ty::Coroutine(last_def_id, ..) => {
+                                            tcx.coroutine_is_async(*last_def_id)
                                         }
                                         _ => false,
                                     })
@@ -2954,7 +2977,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 }
                                 err.span_note(self.tcx.def_span(def_id), msg)
                             }
-                            ty::GeneratorWitness(def_id, args) => {
+                            ty::CoroutineWitness(def_id, args) => {
                                 use std::fmt::Write;
 
                                 // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
@@ -2962,17 +2985,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 // FIXME: only print types which don't meet the trait requirement
                                 let mut msg =
                                     "required because it captures the following types: ".to_owned();
-                                for bty in tcx.generator_hidden_types(*def_id) {
+                                for bty in tcx.coroutine_hidden_types(*def_id) {
                                     let ty = bty.instantiate(tcx, args);
                                     write!(msg, "`{ty}`, ").unwrap();
                                 }
                                 err.note(msg.trim_end_matches(", ").to_string())
                             }
-                            ty::Generator(def_id, _, _) => {
+                            ty::Coroutine(def_id, _, _) => {
                                 let sp = self.tcx.def_span(def_id);
 
-                                // Special-case this to say "async block" instead of `[static generator]`.
-                                let kind = tcx.generator_kind(def_id).unwrap().descr();
+                                // Special-case this to say "async block" instead of `[static coroutine]`.
+                                let kind = tcx.coroutine_kind(def_id).unwrap().descr();
                                 err.span_note(
                                     sp,
                                     with_forced_trimmed_paths!(format!(
@@ -3271,7 +3294,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) {
         if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
             let body = self.tcx.hir().body(body_id);
-            if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
+            if let Some(hir::CoroutineKind::Async(_)) = body.coroutine_kind {
                 let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
 
                 let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
@@ -4332,7 +4355,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
 
     fn visit_body(&mut self, body: &'v hir::Body<'v>) {
         assert!(!self.in_block_tail);
-        if body.generator_kind().is_none() {
+        if body.coroutine_kind().is_none() {
             if let hir::ExprKind::Block(block, None) = body.value.kind {
                 if block.expr.is_some() {
                     self.in_block_tail = true;
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 640bd3fad7c..b382474213e 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
@@ -1036,7 +1036,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         ignoring_lifetimes: bool,
     ) -> Option<CandidateSimilarity>;
 
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
+    fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str>;
 
     fn find_similar_impl_candidates(
         &self,
@@ -1564,9 +1564,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ty::Alias(ty::Weak, ..) => Some(15),
                 ty::Never => Some(16),
                 ty::Adt(..) => Some(17),
-                ty::Generator(..) => Some(18),
+                ty::Coroutine(..) => Some(18),
                 ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
+                ty::CoroutineWitness(..) => Some(20),
                 ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
             }
         }
@@ -1613,12 +1613,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+    fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).coroutine_kind.map(|gen_kind| match gen_kind {
+            hir::CoroutineKind::Coroutine => "a coroutine",
+            hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) => "an async block",
+            hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Fn) => "an async function",
+            hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Closure) => "an async closure",
         })
     }
 
@@ -3098,7 +3098,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         };
 
         let found_did = match *found_trait_ty.kind() {
-            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Generator(did, ..) => {
+            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => {
                 Some(did)
             }
             ty::Adt(def, _) => Some(def.did()),
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index b923926d28d..c3f56ae2756 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1811,8 +1811,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::FnPtr(..)
                         | ty::Dynamic(..)
                         | ty::Closure(..)
-                        | ty::Generator(..)
-                        | ty::GeneratorWitness(..)
+                        | ty::Coroutine(..)
+                        | ty::CoroutineWitness(..)
                         | ty::Never
                         | ty::Tuple(..)
                         // Integers and floats always have `u8` as their discriminant.
@@ -1860,8 +1860,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::FnPtr(..)
                         | ty::Dynamic(..)
                         | ty::Closure(..)
-                        | ty::Generator(..)
-                        | ty::GeneratorWitness(..)
+                        | ty::Coroutine(..)
+                        | ty::CoroutineWitness(..)
                         | ty::Never
                         // Extern types have unit metadata, according to RFC 2850
                         | ty::Foreign(_)
@@ -2003,7 +2003,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
             let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
             let lang_items = selcx.tcx().lang_items();
             if lang_items.gen_trait() == Some(trait_def_id) {
-                confirm_generator_candidate(selcx, obligation, data)
+                confirm_coroutine_candidate(selcx, obligation, data)
             } else if lang_items.future_trait() == Some(trait_def_id) {
                 confirm_future_candidate(selcx, obligation, data)
             } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
@@ -2030,17 +2030,17 @@ fn confirm_select_candidate<'cx, 'tcx>(
     }
 }
 
-fn confirm_generator_candidate<'cx, 'tcx>(
+fn confirm_coroutine_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Generator(_, args, _) =
+    let ty::Coroutine(_, args, _) =
         selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
-    let gen_sig = args.as_generator().poly_sig();
+    let gen_sig = args.as_coroutine().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2049,13 +2049,13 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         gen_sig,
     );
 
-    debug!(?obligation, ?gen_sig, ?obligations, "confirm_generator_candidate");
+    debug!(?obligation, ?gen_sig, ?obligations, "confirm_coroutine_candidate");
 
     let tcx = selcx.tcx();
 
-    let gen_def_id = tcx.require_lang_item(LangItem::Generator, None);
+    let gen_def_id = tcx.require_lang_item(LangItem::Coroutine, None);
 
-    let predicate = super::util::generator_trait_ref_and_outputs(
+    let predicate = super::util::coroutine_trait_ref_and_outputs(
         tcx,
         gen_def_id,
         obligation.predicate.self_ty(),
@@ -2087,12 +2087,12 @@ fn confirm_future_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Generator(_, args, _) =
+    let ty::Coroutine(_, args, _) =
         selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
-    let gen_sig = args.as_generator().poly_sig();
+    let gen_sig = args.as_coroutine().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 86ea7a2bf83..0783eec6fe8 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -35,7 +35,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         | ty::FnDef(..)
         | ty::FnPtr(_)
         | ty::Char
-        | ty::GeneratorWitness(..)
+        | ty::CoroutineWitness(..)
         | ty::RawPtr(_)
         | ty::Ref(..)
         | ty::Str
@@ -72,7 +72,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Bound(..)
-        | ty::Generator(..) => false,
+        | ty::Coroutine(..) => false,
     }
 }
 
@@ -217,7 +217,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
         | ty::Ref(..)
         | ty::FnDef(..)
         | ty::FnPtr(_)
-        | ty::GeneratorWitness(..) => {
+        | ty::CoroutineWitness(..) => {
             // these types never have a destructor
         }
 
@@ -255,22 +255,22 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             })?
         }
 
-        ty::Generator(_, args, _movability) => {
+        ty::Coroutine(_, args, _movability) => {
             // rust-lang/rust#49918: types can be constructed, stored
-            // in the interior, and sit idle when generator yields
+            // in the interior, and sit idle when coroutine yields
             // (and is subsequently dropped).
             //
             // It would be nice to descend into interior of a
-            // generator to determine what effects dropping it might
+            // coroutine to determine what effects dropping it might
             // have (by looking at any drop effects associated with
             // its interior).
             //
             // However, the interior's representation uses things like
-            // GeneratorWitness that explicitly assume they are not
+            // CoroutineWitness that explicitly assume they are not
             // traversed in such a manner. So instead, we will
-            // simplify things for now by treating all generators as
+            // simplify things for now by treating all coroutines as
             // if they were like trait objects, where its upvars must
-            // all be alive for the generator's (potential)
+            // all be alive for the coroutine's (potential)
             // destructor.
             //
             // In particular, skipping over `_interior` is safe
@@ -279,20 +279,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // derived from lifetimes attached to the upvars and resume
             // argument, and we *do* incorporate those here.
 
-            if !args.as_generator().is_valid() {
+            if !args.as_coroutine().is_valid() {
                 // By the time this code runs, all type variables ought to
                 // be fully resolved.
                 tcx.sess.delay_span_bug(
                     span,
-                    format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
+                    format!("upvar_tys for coroutine not found. Expected capture information for coroutine {ty}",),
                 );
                 return Err(NoSolution);
             }
 
             constraints
                 .outlives
-                .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from));
-            constraints.outlives.push(args.as_generator().resume_ty().into());
+                .extend(args.as_coroutine().upvar_tys().iter().map(ty::GenericArg::from));
+            constraints.outlives.push(args.as_coroutine().resume_ty().into());
         }
 
         ty::Adt(def, args) => {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index f785211c548..349741a698c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -231,7 +231,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                         let args = data.args.try_fold_with(self)?;
                         let recursion_limit = self.interner().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
-                            // A closure or generator may have itself as in its upvars.
+                            // A closure or coroutine may have itself as in its upvars.
                             // This should be checked handled by the recursion check for opaque
                             // types, but we may end up here before that check can happen.
                             // In that case, we delay a bug to mark the trip, and continue without
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a8001577bcd..ee50a36be55 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -111,7 +111,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
 
                 if lang_items.gen_trait() == Some(def_id) {
-                    self.assemble_generator_candidates(obligation, &mut candidates);
+                    self.assemble_coroutine_candidates(obligation, &mut candidates);
                 } else if lang_items.future_trait() == Some(def_id) {
                     self.assemble_future_candidates(obligation, &mut candidates);
                 }
@@ -201,25 +201,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(())
     }
 
-    fn assemble_generator_candidates(
+    fn assemble_coroutine_candidates(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        // Okay to skip binder because the args on generator types never
+        // Okay to skip binder because the args on coroutine types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = obligation.self_ty().skip_binder();
         match self_ty.kind() {
-            // async constructs get lowered to a special kind of generator that
-            // should *not* `impl Generator`.
-            ty::Generator(did, ..) if !self.tcx().generator_is_async(*did) => {
-                debug!(?self_ty, ?obligation, "assemble_generator_candidates",);
+            // async constructs get lowered to a special kind of coroutine that
+            // should *not* `impl Coroutine`.
+            ty::Coroutine(did, ..) if !self.tcx().coroutine_is_async(*did) => {
+                debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
 
-                candidates.vec.push(GeneratorCandidate);
+                candidates.vec.push(CoroutineCandidate);
             }
             ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_generator_candidates: ambiguous self-type");
+                debug!("assemble_coroutine_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
             }
             _ => {}
@@ -232,10 +232,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let self_ty = obligation.self_ty().skip_binder();
-        if let ty::Generator(did, ..) = self_ty.kind() {
-            // async constructs get lowered to a special kind of generator that
+        if let ty::Coroutine(did, ..) = self_ty.kind() {
+            // async constructs get lowered to a special kind of coroutine that
             // should directly `impl Future`.
-            if self.tcx().generator_is_async(*did) {
+            if self.tcx().coroutine_is_async(*did) {
                 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
 
                 candidates.vec.push(FutureCandidate);
@@ -435,8 +435,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::RawPtr(_)
                 | ty::Ref(_, _, _)
                 | ty::Closure(_, _)
-                | ty::Generator(_, _, _)
-                | ty::GeneratorWitness(..)
+                | ty::Coroutine(_, _, _)
+                | ty::CoroutineWitness(..)
                 | ty::Never
                 | ty::Tuple(_)
                 | ty::Error(_) => return true,
@@ -513,16 +513,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // The auto impl might apply; we don't know.
                     candidates.ambiguous = true;
                 }
-                ty::Generator(_, _, movability)
+                ty::Coroutine(_, _, movability)
                     if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
                 {
                     match movability {
                         hir::Movability::Static => {
-                            // Immovable generators are never `Unpin`, so
+                            // Immovable coroutines are never `Unpin`, so
                             // suppress the normal auto-impl candidate for it.
                         }
                         hir::Movability::Movable => {
-                            // Movable generators are always `Unpin`, so add an
+                            // Movable coroutines are always `Unpin`, so add an
                             // unconditional builtin candidate.
                             candidates.vec.push(BuiltinCandidate { has_nested: false });
                         }
@@ -570,10 +570,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::FnDef(..)
                 | ty::FnPtr(_)
                 | ty::Closure(_, _)
-                | ty::Generator(..)
+                | ty::Coroutine(..)
                 | ty::Never
                 | ty::Tuple(_)
-                | ty::GeneratorWitness(..) => {
+                | ty::CoroutineWitness(..) => {
                     // Only consider auto impls if there are no manual impls for the root of `self_ty`.
                     //
                     // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
@@ -947,9 +947,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Array(..)
             | ty::Slice(_)
             | ty::Closure(..)
-            | ty::Generator(..)
+            | ty::Coroutine(..)
             | ty::Tuple(_)
-            | ty::GeneratorWitness(..) => {
+            | ty::CoroutineWitness(..) => {
                 // These are built-in, and cannot have a custom `impl const Destruct`.
                 candidates.vec.push(ConstDestructCandidate(None));
             }
@@ -1021,8 +1021,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::FnPtr(_)
             | ty::Dynamic(_, _, _)
             | ty::Closure(_, _)
-            | ty::Generator(_, _, _)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(_, _, _)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Alias(..)
             | ty::Param(_)
@@ -1082,8 +1082,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Placeholder(..)
             | ty::Dynamic(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Never
             | ty::Tuple(..)
             | ty::Alias(..)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 08ee9c73bf8..fce439f21fa 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -83,9 +83,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
             }
 
-            GeneratorCandidate => {
-                let vtable_generator = self.confirm_generator_candidate(obligation)?;
-                ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator)
+            CoroutineCandidate => {
+                let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?;
+                ImplSource::Builtin(BuiltinImplSource::Misc, vtable_coroutine)
             }
 
             FutureCandidate => {
@@ -711,23 +711,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         trait_obligations
     }
 
-    fn confirm_generator_candidate(
+    fn confirm_coroutine_candidate(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on generator types never
+        // Okay to skip binder because the args on coroutine types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
+        let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
 
-        debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
+        debug!(?obligation, ?coroutine_def_id, ?args, "confirm_coroutine_candidate");
 
-        let gen_sig = args.as_generator().poly_sig();
+        let gen_sig = args.as_coroutine().poly_sig();
 
-        // NOTE: The self-type is a generator type and hence is
+        // NOTE: The self-type is a coroutine type and hence is
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation).
         let self_ty = obligation
@@ -736,7 +736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .no_bound_vars()
             .expect("unboxed closure type should not capture bound vars from the predicate");
 
-        let trait_ref = super::util::generator_trait_ref_and_outputs(
+        let trait_ref = super::util::coroutine_trait_ref_and_outputs(
             self.tcx(),
             obligation.predicate.def_id(),
             self_ty,
@@ -745,7 +745,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         .map_bound(|(trait_ref, ..)| trait_ref);
 
         let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
-        debug!(?trait_ref, ?nested, "generator candidate obligations");
+        debug!(?trait_ref, ?nested, "coroutine candidate obligations");
 
         Ok(nested)
     }
@@ -754,17 +754,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on generator types never
+        // Okay to skip binder because the args on coroutine types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
+        let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
 
-        debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
+        debug!(?obligation, ?coroutine_def_id, ?args, "confirm_future_candidate");
 
-        let gen_sig = args.as_generator().poly_sig();
+        let gen_sig = args.as_coroutine().poly_sig();
 
         let trait_ref = super::util::future_trait_ref_and_outputs(
             self.tcx(),
@@ -1234,13 +1234,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::Closure(_, args) => {
                     stack.push(args.as_closure().tupled_upvars_ty());
                 }
-                ty::Generator(_, args, _) => {
-                    let generator = args.as_generator();
-                    stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
+                ty::Coroutine(_, args, _) => {
+                    let coroutine = args.as_coroutine();
+                    stack.extend([coroutine.tupled_upvars_ty(), coroutine.witness()]);
                 }
-                ty::GeneratorWitness(def_id, args) => {
+                ty::CoroutineWitness(def_id, args) => {
                     let tcx = self.tcx();
-                    stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
+                    stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| {
                         let ty = bty.instantiate(tcx, args);
                         debug_assert!(!ty.has_late_bound_regions());
                         ty
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 940ceca50d2..67cb39bc004 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1886,7 +1886,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 ImplCandidate(..)
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -1914,7 +1914,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 ImplCandidate(_)
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -1948,7 +1948,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 ImplCandidate(..)
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -1962,7 +1962,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 ImplCandidate(..)
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -2068,7 +2068,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             (
                 ImplCandidate(_)
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -2078,7 +2078,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 | TraitAliasCandidate,
                 ImplCandidate(_)
                 | ClosureCandidate { .. }
-                | GeneratorCandidate
+                | CoroutineCandidate
                 | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
@@ -2112,8 +2112,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             | ty::RawPtr(..)
             | ty::Char
             | ty::Ref(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Array(..)
             | ty::Closure(..)
             | ty::Never
@@ -2180,7 +2180,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             ty::Dynamic(..)
             | ty::Str
             | ty::Slice(..)
-            | ty::Generator(_, _, hir::Movability::Static)
+            | ty::Coroutine(_, _, hir::Movability::Static)
             | ty::Foreign(..)
             | ty::Ref(_, _, hir::Mutability::Mut) => None,
 
@@ -2189,21 +2189,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 Where(obligation.predicate.rebind(tys.iter().collect()))
             }
 
-            ty::Generator(_, args, hir::Movability::Movable) => {
-                if self.tcx().features().generator_clone {
+            ty::Coroutine(_, args, hir::Movability::Movable) => {
+                if self.tcx().features().coroutine_clone {
                     let resolved_upvars =
-                        self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
+                        self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
                     let resolved_witness =
-                        self.infcx.shallow_resolve(args.as_generator().witness());
+                        self.infcx.shallow_resolve(args.as_coroutine().witness());
                     if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
                         // Not yet resolved.
                         Ambiguous
                     } else {
                         let all = args
-                            .as_generator()
+                            .as_coroutine()
                             .upvar_tys()
                             .iter()
-                            .chain([args.as_generator().witness()])
+                            .chain([args.as_coroutine().witness()])
                             .collect::<Vec<_>>();
                         Where(obligation.predicate.rebind(all))
                     }
@@ -2212,8 +2212,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 }
             }
 
-            ty::GeneratorWitness(def_id, ref args) => {
-                let hidden_types = bind_generator_hidden_types_above(
+            ty::CoroutineWitness(def_id, ref args) => {
+                let hidden_types = bind_coroutine_hidden_types_above(
                     self.infcx,
                     def_id,
                     args,
@@ -2311,14 +2311,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 t.rebind(vec![ty])
             }
 
-            ty::Generator(_, ref args, _) => {
-                let ty = self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
-                let witness = args.as_generator().witness();
+            ty::Coroutine(_, ref args, _) => {
+                let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
+                let witness = args.as_coroutine().witness();
                 t.rebind([ty].into_iter().chain(iter::once(witness)).collect())
             }
 
-            ty::GeneratorWitness(def_id, ref args) => {
-                bind_generator_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
+            ty::CoroutineWitness(def_id, ref args) => {
+                bind_coroutine_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
             }
 
             // For `PhantomData<T>`, we pass `T`.
@@ -3054,12 +3054,12 @@ pub enum ProjectionMatchesProjection {
     No,
 }
 
-/// Replace all regions inside the generator interior with late bound regions.
+/// Replace all regions inside the coroutine interior with late bound regions.
 /// Note that each region slot in the types gets a new fresh late bound region, which means that
 /// none of the regions inside relate to any other, even if typeck had previously found constraints
 /// that would cause them to be related.
 #[instrument(level = "trace", skip(infcx), ret)]
-fn bind_generator_hidden_types_above<'tcx>(
+fn bind_coroutine_hidden_types_above<'tcx>(
     infcx: &InferCtxt<'tcx>,
     def_id: DefId,
     args: ty::GenericArgsRef<'tcx>,
@@ -3074,7 +3074,7 @@ fn bind_generator_hidden_types_above<'tcx>(
     let mut counter = num_bound_variables;
 
     let hidden_types: Vec<_> = tcx
-        .generator_hidden_types(def_id)
+        .coroutine_hidden_types(def_id)
         // Deduplicate tys to avoid repeated work.
         .filter(|bty| seen_tys.insert(*bty))
         .map(|mut bty| {
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index fc9b424369a..5960415a88d 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -79,7 +79,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
             ty::Closure(..) => {
                 return ControlFlow::Break(ty);
             }
-            ty::Generator(..) | ty::GeneratorWitness(..) => {
+            ty::Coroutine(..) | ty::CoroutineWitness(..) => {
                 return ControlFlow::Break(ty);
             }
             ty::FnDef(..) => {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 4ef2027d7e8..47ed4e20edc 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -275,7 +275,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
     sig.map_bound(|sig| (trait_ref, sig.output()))
 }
 
-pub fn generator_trait_ref_and_outputs<'tcx>(
+pub fn coroutine_trait_ref_and_outputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_trait_def_id: DefId,
     self_ty: Ty<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e7e4ee983fb..fe5b625e483 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -600,7 +600,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 | ty::Float(..)
                 | ty::Error(_)
                 | ty::Str
-                | ty::GeneratorWitness(..)
+                | ty::CoroutineWitness(..)
                 | ty::Never
                 | ty::Param(_)
                 | ty::Bound(..)
@@ -672,14 +672,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     }
                 }
 
-                ty::Generator(did, args, ..) => {
-                    // Walk ALL the types in the generator: this will
+                ty::Coroutine(did, args, ..) => {
+                    // Walk ALL the types in the coroutine: this will
                     // include the upvar types as well as the yield
                     // type. Note that this is mildly distinct from
                     // the closure case, where we have to be careful
                     // about the signature of the closure. We don't
                     // have the problem of implied bounds here since
-                    // generators don't take arguments.
+                    // coroutines don't take arguments.
                     let obligations = self.nominal_obligations(did, args);
                     self.out.extend(obligations);
                 }
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index c416aa52a24..ae795ef2214 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -60,6 +60,6 @@ ty_utils_tuple_not_supported = tuple construction is not supported in generic co
 
 ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
 
-ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+ty_utils_yield_not_supported = coroutine control flow is not allowed in generic constants
 
 ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index b118ddaab2b..fcf6626bbf0 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -97,8 +97,8 @@ fn fn_sig_for_fn_abi<'tcx>(
                 bound_vars,
             )
         }
-        ty::Generator(did, args, _) => {
-            let sig = args.as_generator().poly_sig();
+        ty::Coroutine(did, args, _) => {
+            let sig = args.as_coroutine().poly_sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
                 sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
@@ -116,11 +116,11 @@ fn fn_sig_for_fn_abi<'tcx>(
             let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_args);
 
             let sig = sig.skip_binder();
-            // The `FnSig` and the `ret_ty` here is for a generators main
-            // `Generator::resume(...) -> GeneratorState` function in case we
-            // have an ordinary generator, or the `Future::poll(...) -> Poll`
-            // function in case this is a special generator backing an async construct.
-            let (resume_ty, ret_ty) = if tcx.generator_is_async(did) {
+            // The `FnSig` and the `ret_ty` here is for a coroutines main
+            // `Coroutine::resume(...) -> CoroutineState` function in case we
+            // have an ordinary coroutine, or the `Future::poll(...) -> Poll`
+            // function in case this is a special coroutine backing an async construct.
+            let (resume_ty, ret_ty) = if tcx.coroutine_is_async(did) {
                 // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
                 let poll_did = tcx.require_lang_item(LangItem::Poll, None);
                 let poll_adt_ref = tcx.adt_def(poll_did);
@@ -143,8 +143,8 @@ fn fn_sig_for_fn_abi<'tcx>(
 
                 (context_mut_ref, ret_ty)
             } else {
-                // The signature should be `Generator::resume(_, Resume) -> GeneratorState<Yield, Return>`
-                let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+                // The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
+                let state_did = tcx.require_lang_item(LangItem::CoroutineState, None);
                 let state_adt_ref = tcx.adt_def(state_did);
                 let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
                 let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 0ca7d43f6d5..5c34df1ed50 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -157,7 +157,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::Generator => ty::List::empty(),
+        | DefKind::Coroutine => ty::List::empty(),
     }
 }
 
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 2fbf87800bb..0e9d79c15c3 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -38,7 +38,7 @@ fn resolve_instance<'tcx>(
                 debug!(" => nontrivial drop glue");
                 match *ty.kind() {
                     ty::Closure(..)
-                    | ty::Generator(..)
+                    | ty::Coroutine(..)
                     | ty::Tuple(..)
                     | ty::Adt(..)
                     | ty::Dynamic(..)
@@ -212,8 +212,8 @@ fn resolve_associated_item<'tcx>(
                     let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
                     match self_ty.kind() {
                         _ if is_copy => (),
-                        ty::Generator(..)
-                        | ty::GeneratorWitness(..)
+                        ty::Coroutine(..)
+                        | ty::CoroutineWitness(..)
                         | ty::Closure(..)
                         | ty::Tuple(..) => {}
                         _ => return Ok(None),
@@ -246,12 +246,12 @@ fn resolve_associated_item<'tcx>(
                     })
                 }
             } else if Some(trait_ref.def_id) == lang_items.future_trait() {
-                let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
+                let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
                     bug!()
                 };
                 if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
                     // `Future::poll` is generated by the compiler.
-                    Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args: args })
+                    Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
                 } else {
                     // All other methods are default methods of the `Future` trait.
                     // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
@@ -259,21 +259,21 @@ fn resolve_associated_item<'tcx>(
                     Some(Instance::new(trait_item_id, rcvr_args))
                 }
             } else if Some(trait_ref.def_id) == lang_items.gen_trait() {
-                let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
+                let ty::Coroutine(coroutine_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
                     bug!()
                 };
                 if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
-                    // For compiler developers who'd like to add new items to `Generator`,
+                    // For compiler developers who'd like to add new items to `Coroutine`,
                     // you either need to generate a shim body, or perhaps return
                     // `InstanceDef::Item` pointing to a trait default method body if
                     // it is given a default implementation by the trait.
                     span_bug!(
-                        tcx.def_span(generator_def_id),
-                        "no definition for `{trait_ref}::{}` for built-in generator type",
+                        tcx.def_span(coroutine_def_id),
+                        "no definition for `{trait_ref}::{}` for built-in coroutine type",
                         tcx.item_name(trait_item_id)
                     )
                 }
-                Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args })
+                Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
             } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
                 // FIXME: This doesn't check for malformed libcore that defines, e.g.,
                 // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index cc6c8478785..283862b5e1c 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -2,7 +2,7 @@ use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
+use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
@@ -314,7 +314,7 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(unit)
         }
 
-        ty::Generator(def_id, args, _) => generator_layout(cx, ty, def_id, args)?,
+        ty::Coroutine(def_id, args, _) => coroutine_layout(cx, ty, def_id, args)?,
 
         ty::Closure(_, ref args) => {
             let tys = args.as_closure().upvar_tys();
@@ -575,7 +575,7 @@ fn layout_of_uncached<'tcx>(
             return Err(error(cx, LayoutError::Unknown(ty)));
         }
 
-        ty::Bound(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => {
+        ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
             bug!("Layout::compute: unexpected type `{}`", ty)
         }
 
@@ -585,7 +585,7 @@ fn layout_of_uncached<'tcx>(
     })
 }
 
-/// Overlap eligibility and variant assignment for each GeneratorSavedLocal.
+/// Overlap eligibility and variant assignment for each CoroutineSavedLocal.
 #[derive(Clone, Debug, PartialEq)]
 enum SavedLocalEligibility {
     Unassigned,
@@ -593,7 +593,7 @@ enum SavedLocalEligibility {
     Ineligible(Option<FieldIdx>),
 }
 
-// When laying out generators, we divide our saved local fields into two
+// When laying out coroutines, we divide our saved local fields into two
 // categories: overlap-eligible and overlap-ineligible.
 //
 // Those fields which are ineligible for overlap go in a "prefix" at the
@@ -613,16 +613,16 @@ enum SavedLocalEligibility {
 // of any variant.
 
 /// Compute the eligibility and assignment of each local.
-fn generator_saved_local_eligibility(
-    info: &GeneratorLayout<'_>,
-) -> (BitSet<GeneratorSavedLocal>, IndexVec<GeneratorSavedLocal, SavedLocalEligibility>) {
+fn coroutine_saved_local_eligibility(
+    info: &CoroutineLayout<'_>,
+) -> (BitSet<CoroutineSavedLocal>, IndexVec<CoroutineSavedLocal, SavedLocalEligibility>) {
     use SavedLocalEligibility::*;
 
-    let mut assignments: IndexVec<GeneratorSavedLocal, SavedLocalEligibility> =
+    let mut assignments: IndexVec<CoroutineSavedLocal, SavedLocalEligibility> =
         IndexVec::from_elem(Unassigned, &info.field_tys);
 
     // The saved locals not eligible for overlap. These will get
-    // "promoted" to the prefix of our generator.
+    // "promoted" to the prefix of our coroutine.
     let mut ineligible_locals = BitSet::new_empty(info.field_tys.len());
 
     // Figure out which of our saved locals are fields in only
@@ -660,7 +660,7 @@ fn generator_saved_local_eligibility(
 
         for local_b in info.storage_conflicts.iter(local_a) {
             // local_a and local_b are storage live at the same time, therefore they
-            // cannot overlap in the generator layout. The only way to guarantee
+            // cannot overlap in the coroutine layout. The only way to guarantee
             // this is if they are in the same variant, or one is ineligible
             // (which means it is stored in every variant).
             if ineligible_locals.contains(local_b) || assignments[local_a] == assignments[local_b] {
@@ -705,13 +705,13 @@ fn generator_saved_local_eligibility(
             assignments[local] = Ineligible(Some(FieldIdx::from_usize(idx)));
         }
     }
-    debug!("generator saved local assignments: {:?}", assignments);
+    debug!("coroutine saved local assignments: {:?}", assignments);
 
     (ineligible_locals, assignments)
 }
 
-/// Compute the full generator layout.
-fn generator_layout<'tcx>(
+/// Compute the full coroutine layout.
+fn coroutine_layout<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     ty: Ty<'tcx>,
     def_id: hir::def_id::DefId,
@@ -721,15 +721,15 @@ fn generator_layout<'tcx>(
     let tcx = cx.tcx;
     let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).instantiate(tcx, args);
 
-    let Some(info) = tcx.generator_layout(def_id) else {
+    let Some(info) = tcx.coroutine_layout(def_id) else {
         return Err(error(cx, LayoutError::Unknown(ty)));
     };
-    let (ineligible_locals, assignments) = generator_saved_local_eligibility(&info);
+    let (ineligible_locals, assignments) = coroutine_saved_local_eligibility(&info);
 
     // Build a prefix layout, including "promoting" all ineligible
     // locals as part of the prefix. We compute the layout of all of
     // these fields at once to get optimal packing.
-    let tag_index = args.as_generator().prefix_tys().len();
+    let tag_index = args.as_coroutine().prefix_tys().len();
 
     // `info.variant_fields` already accounts for the reserved variants, so no need to add them.
     let max_discr = (info.variant_fields.len() - 1) as u128;
@@ -746,7 +746,7 @@ fn generator_layout<'tcx>(
         .map(|ty| Ty::new_maybe_uninit(tcx, ty))
         .map(|ty| Ok(cx.layout_of(ty)?.layout));
     let prefix_layouts = args
-        .as_generator()
+        .as_coroutine()
         .prefix_tys()
         .iter()
         .map(|ty| Ok(cx.layout_of(ty)?.layout))
@@ -766,7 +766,7 @@ fn generator_layout<'tcx>(
     // Split the prefix layout into the "outer" fields (upvars and
     // discriminant) and the "promoted" fields. Promoted fields will
     // get included in each variant that requested them in
-    // GeneratorLayout.
+    // CoroutineLayout.
     debug!("prefix = {:#?}", prefix);
     let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
         FieldsShape::Arbitrary { mut offsets, memory_index } => {
@@ -833,7 +833,7 @@ fn generator_layout<'tcx>(
             };
 
             // Now, stitch the promoted and variant-only fields back together in
-            // the order they are mentioned by our GeneratorLayout.
+            // the order they are mentioned by our CoroutineLayout.
             // Because we only use some subset (that can differ between variants)
             // of the promoted fields, we can't just pick those elements of the
             // `promoted_memory_index` (as we'd end up with gaps).
@@ -907,7 +907,7 @@ fn generator_layout<'tcx>(
         max_repr_align: None,
         unadjusted_abi_align: align.abi,
     });
-    debug!("generator layout ({:?}): {:#?}", ty, layout);
+    debug!("coroutine layout ({:?}): {:#?}", ty, layout);
     Ok(layout)
 }
 
@@ -956,12 +956,12 @@ fn record_layout_for_printing_outlined<'tcx>(
             record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
         }
 
-        ty::Generator(def_id, args, _) => {
-            debug!("print-type-size t: `{:?}` record generator", layout.ty);
-            // Generators always have a begin/poisoned/end state with additional suspend points
+        ty::Coroutine(def_id, args, _) => {
+            debug!("print-type-size t: `{:?}` record coroutine", layout.ty);
+            // Coroutines always have a begin/poisoned/end state with additional suspend points
             let (variant_infos, opt_discr_size) =
-                variant_info_for_generator(cx, layout, def_id, args);
-            record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
+                variant_info_for_coroutine(cx, layout, def_id, args);
+            record(DataTypeKind::Coroutine, false, opt_discr_size, variant_infos);
         }
 
         ty::Closure(..) => {
@@ -1046,7 +1046,7 @@ fn variant_info_for_adt<'tcx>(
     }
 }
 
-fn variant_info_for_generator<'tcx>(
+fn variant_info_for_coroutine<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     layout: TyAndLayout<'tcx>,
     def_id: DefId,
@@ -1056,12 +1056,12 @@ fn variant_info_for_generator<'tcx>(
         return (vec![], None);
     };
 
-    let generator = cx.tcx.optimized_mir(def_id).generator_layout().unwrap();
+    let coroutine = cx.tcx.optimized_mir(def_id).coroutine_layout().unwrap();
     let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
 
     let mut upvars_size = Size::ZERO;
     let upvar_fields: Vec<_> = args
-        .as_generator()
+        .as_coroutine()
         .upvar_tys()
         .iter()
         .zip(upvar_names)
@@ -1080,7 +1080,7 @@ fn variant_info_for_generator<'tcx>(
         })
         .collect();
 
-    let mut variant_infos: Vec<_> = generator
+    let mut variant_infos: Vec<_> = coroutine
         .variant_fields
         .iter_enumerated()
         .map(|(variant_idx, variant_def)| {
@@ -1095,9 +1095,9 @@ fn variant_info_for_generator<'tcx>(
                     // The struct is as large as the last field's end
                     variant_size = variant_size.max(offset + field_layout.size);
                     FieldInfo {
-                        kind: FieldKind::GeneratorLocal,
-                        name: generator.field_names[*local].unwrap_or(Symbol::intern(&format!(
-                            ".generator_field{}",
+                        kind: FieldKind::CoroutineLocal,
+                        name: coroutine.field_names[*local].unwrap_or(Symbol::intern(&format!(
+                            ".coroutine_field{}",
                             local.as_usize()
                         ))),
                         offset: offset.bytes(),
@@ -1115,8 +1115,8 @@ fn variant_info_for_generator<'tcx>(
 
             // This `if` deserves some explanation.
             //
-            // The layout code has a choice of where to place the discriminant of this generator.
-            // If the discriminant of the generator is placed early in the layout (before the
+            // The layout code has a choice of where to place the discriminant of this coroutine.
+            // If the discriminant of the coroutine is placed early in the layout (before the
             // variant's own fields), then it'll implicitly be counted towards the size of the
             // variant, since we use the maximum offset to calculate size.
             //    (side-note: I know this is a bit problematic given upvars placement, etc).
@@ -1136,7 +1136,7 @@ fn variant_info_for_generator<'tcx>(
             }
 
             VariantInfo {
-                name: Some(Symbol::intern(&ty::GeneratorArgs::variant_name(variant_idx))),
+                name: Some(Symbol::intern(&ty::CoroutineArgs::variant_name(variant_idx))),
                 kind: SizeKind::Exact,
                 size: variant_size.bytes(),
                 align: variant_layout.align.abi.bytes(),
@@ -1147,7 +1147,7 @@ fn variant_info_for_generator<'tcx>(
 
     // The first three variants are hardcoded to be `UNRESUMED`, `RETURNED` and `POISONED`.
     // We will move the `RETURNED` and `POISONED` elements to the end so we
-    // are left with a sorting order according to the generators yield points:
+    // are left with a sorting order according to the coroutines yield points:
     // First `Unresumed`, then the `SuspendN` followed by `Returned` and `Panicked` (POISONED).
     let end_states = variant_infos.drain(1..=2);
     let end_states: Vec<_> = end_states.collect();
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 6dcbc4470e6..08127304741 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -130,10 +130,10 @@ where
 
             for component in components {
                 match *component.kind() {
-                    // The information required to determine whether a generator has drop is
+                    // The information required to determine whether a coroutine has drop is
                     // computed on MIR, while this very method is used to build MIR.
-                    // To avoid cycles, we consider that generators always require drop.
-                    ty::Generator(..) => {
+                    // To avoid cycles, we consider that coroutines always require drop.
+                    ty::Coroutine(..) => {
                         return Some(Err(AlwaysRequiresDrop));
                     }
 
@@ -191,7 +191,7 @@ where
                     | ty::FnPtr(..)
                     | ty::Tuple(_)
                     | ty::Bound(..)
-                    | ty::GeneratorWitness(..)
+                    | ty::CoroutineWitness(..)
                     | ty::Never
                     | ty::Infer(_)
                     | ty::Error(_) => {
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 06a30677d20..0010570e7b3 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -322,8 +322,8 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Impl { .. } => {}
-        // Closures and generators are type checked with their parent, so there is no difference here.
-        DefKind::Closure | DefKind::Generator | DefKind::InlineConst => {
+        // Closures and coroutines are type checked with their parent, so there is no difference here.
+        DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst => {
             return tcx.opaque_types_defined_by(tcx.local_parent(item));
         }
     }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index e1ec159921e..abf3e108ed4 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -14,13 +14,13 @@ fn sized_constraint_for_ty<'tcx>(
     adtdef: ty::AdtDef<'tcx>,
     ty: Ty<'tcx>,
 ) -> Vec<Ty<'tcx>> {
-    use rustc_type_ir::sty::TyKind::*;
+    use rustc_type_ir::TyKind::*;
 
     let result = match ty.kind() {
         Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
-        | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
+        | FnPtr(_) | Array(..) | Closure(..) | Coroutine(..) | Never => vec![],
 
-        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => {
+        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | CoroutineWitness(..) => {
             // these are never sized - return the target type
             vec![ty]
         }
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
new file mode 100644
index 00000000000..f84841c9f64
--- /dev/null
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -0,0 +1,258 @@
+use rustc_data_structures::stable_hasher::HashStable;
+use rustc_serialize::{Decodable, Decoder, Encodable};
+use std::cmp::Ordering;
+use std::fmt;
+use std::hash;
+
+use crate::{
+    DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx,
+    TyDecoder, TyEncoder,
+};
+
+use self::ConstKind::*;
+
+/// Represents a constant in Rust.
+// #[derive(derive_more::From)]
+pub enum ConstKind<I: Interner> {
+    /// A const generic parameter.
+    Param(I::ParamConst),
+
+    /// Infer the value of the const.
+    Infer(I::InferConst),
+
+    /// Bound const variable, used only when preparing a trait query.
+    Bound(DebruijnIndex, I::BoundConst),
+
+    /// A placeholder const - universally quantified higher-ranked const.
+    Placeholder(I::PlaceholderConst),
+
+    /// An unnormalized const item such as an anon const or assoc const or free const item.
+    /// Right now anything other than anon consts does not actually work properly but this
+    /// should
+    Unevaluated(I::AliasConst),
+
+    /// Used to hold computed value.
+    Value(I::ValueConst),
+
+    /// A placeholder for a const which could not be computed; this is
+    /// propagated to avoid useless error messages.
+    Error(I::ErrorGuaranteed),
+
+    /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
+    /// const arguments such as `N + 1` or `foo(N)`
+    Expr(I::ExprConst),
+}
+
+const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
+    match value {
+        Param(_) => 0,
+        Infer(_) => 1,
+        Bound(_, _) => 2,
+        Placeholder(_) => 3,
+        Unevaluated(_) => 4,
+        Value(_) => 5,
+        Error(_) => 6,
+        Expr(_) => 7,
+    }
+}
+
+impl<I: Interner> hash::Hash for ConstKind<I> {
+    fn hash<H: hash::Hasher>(&self, state: &mut H) {
+        const_kind_discriminant(self).hash(state);
+        match self {
+            Param(p) => p.hash(state),
+            Infer(i) => i.hash(state),
+            Bound(d, b) => {
+                d.hash(state);
+                b.hash(state);
+            }
+            Placeholder(p) => p.hash(state),
+            Unevaluated(u) => u.hash(state),
+            Value(v) => v.hash(state),
+            Error(e) => e.hash(state),
+            Expr(e) => e.hash(state),
+        }
+    }
+}
+
+impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
+where
+    I::ParamConst: HashStable<CTX>,
+    I::InferConst: HashStable<CTX>,
+    I::BoundConst: HashStable<CTX>,
+    I::PlaceholderConst: HashStable<CTX>,
+    I::AliasConst: HashStable<CTX>,
+    I::ValueConst: HashStable<CTX>,
+    I::ErrorGuaranteed: HashStable<CTX>,
+    I::ExprConst: HashStable<CTX>,
+{
+    fn hash_stable(
+        &self,
+        hcx: &mut CTX,
+        hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
+    ) {
+        const_kind_discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Param(p) => p.hash_stable(hcx, hasher),
+            Infer(i) => i.hash_stable(hcx, hasher),
+            Bound(d, b) => {
+                d.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            Placeholder(p) => p.hash_stable(hcx, hasher),
+            Unevaluated(u) => u.hash_stable(hcx, hasher),
+            Value(v) => v.hash_stable(hcx, hasher),
+            Error(e) => e.hash_stable(hcx, hasher),
+            Expr(e) => e.hash_stable(hcx, hasher),
+        }
+    }
+}
+
+impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
+where
+    I::ParamConst: Decodable<D>,
+    I::InferConst: Decodable<D>,
+    I::BoundConst: Decodable<D>,
+    I::PlaceholderConst: Decodable<D>,
+    I::AliasConst: Decodable<D>,
+    I::ValueConst: Decodable<D>,
+    I::ErrorGuaranteed: Decodable<D>,
+    I::ExprConst: Decodable<D>,
+{
+    fn decode(d: &mut D) -> Self {
+        match Decoder::read_usize(d) {
+            0 => Param(Decodable::decode(d)),
+            1 => Infer(Decodable::decode(d)),
+            2 => Bound(Decodable::decode(d), Decodable::decode(d)),
+            3 => Placeholder(Decodable::decode(d)),
+            4 => Unevaluated(Decodable::decode(d)),
+            5 => Value(Decodable::decode(d)),
+            6 => Error(Decodable::decode(d)),
+            7 => Expr(Decodable::decode(d)),
+            _ => panic!(
+                "{}",
+                format!(
+                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                    "ConstKind", 8,
+                )
+            ),
+        }
+    }
+}
+
+impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
+where
+    I::ParamConst: Encodable<E>,
+    I::InferConst: Encodable<E>,
+    I::BoundConst: Encodable<E>,
+    I::PlaceholderConst: Encodable<E>,
+    I::AliasConst: Encodable<E>,
+    I::ValueConst: Encodable<E>,
+    I::ErrorGuaranteed: Encodable<E>,
+    I::ExprConst: Encodable<E>,
+{
+    fn encode(&self, e: &mut E) {
+        let disc = const_kind_discriminant(self);
+        match self {
+            Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
+            Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
+            Bound(d, b) => e.emit_enum_variant(disc, |e| {
+                d.encode(e);
+                b.encode(e);
+            }),
+            Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
+            Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
+            Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
+            Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
+            Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
+        }
+    }
+}
+
+impl<I: Interner> PartialOrd for ConstKind<I> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<I: Interner> Ord for ConstKind<I> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        const_kind_discriminant(self)
+            .cmp(&const_kind_discriminant(other))
+            .then_with(|| match (self, other) {
+                (Param(p1), Param(p2)) => p1.cmp(p2),
+                (Infer(i1), Infer(i2)) => i1.cmp(i2),
+                (Bound(d1, b1), Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
+                (Placeholder(p1), Placeholder(p2)) => p1.cmp(p2),
+                (Unevaluated(u1), Unevaluated(u2)) => u1.cmp(u2),
+                (Value(v1), Value(v2)) => v1.cmp(v2),
+                (Error(e1), Error(e2)) => e1.cmp(e2),
+                (Expr(e1), Expr(e2)) => e1.cmp(e2),
+                _ => {
+                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
+                    Ordering::Equal
+                }
+            })
+    }
+}
+
+impl<I: Interner> PartialEq for ConstKind<I> {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Param(l0), Param(r0)) => l0 == r0,
+            (Infer(l0), Infer(r0)) => l0 == r0,
+            (Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
+            (Placeholder(l0), Placeholder(r0)) => l0 == r0,
+            (Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
+            (Value(l0), Value(r0)) => l0 == r0,
+            (Error(l0), Error(r0)) => l0 == r0,
+            (Expr(l0), Expr(r0)) => l0 == r0,
+            _ => false,
+        }
+    }
+}
+
+impl<I: Interner> Eq for ConstKind<I> {}
+
+impl<I: Interner> Clone for ConstKind<I> {
+    fn clone(&self) -> Self {
+        match self {
+            Param(arg0) => Param(arg0.clone()),
+            Infer(arg0) => Infer(arg0.clone()),
+            Bound(arg0, arg1) => Bound(arg0.clone(), arg1.clone()),
+            Placeholder(arg0) => Placeholder(arg0.clone()),
+            Unevaluated(arg0) => Unevaluated(arg0.clone()),
+            Value(arg0) => Value(arg0.clone()),
+            Error(arg0) => Error(arg0.clone()),
+            Expr(arg0) => Expr(arg0.clone()),
+        }
+    }
+}
+
+impl<I: Interner> fmt::Debug for ConstKind<I> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+
+impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        use ConstKind::*;
+
+        match this.data {
+            Param(param) => write!(f, "{param:?}"),
+            Infer(var) => write!(f, "{:?}", &this.wrap(var)),
+            Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
+            Placeholder(placeholder) => write!(f, "{placeholder:?}"),
+            Unevaluated(uv) => {
+                write!(f, "{:?}", &this.wrap(uv))
+            }
+            Value(valtree) => write!(f, "{valtree:?}"),
+            Error(_) => write!(f, "{{const error}}"),
+            Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
+        }
+    }
+}
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
new file mode 100644
index 00000000000..7c6a7846900
--- /dev/null
+++ b/compiler/rustc_type_ir/src/debug.rs
@@ -0,0 +1,117 @@
+use crate::{Interner, UniverseIndex};
+
+use core::fmt;
+use std::marker::PhantomData;
+
+pub trait InferCtxtLike<I: Interner> {
+    fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;
+
+    fn universe_of_lt(&self, lt: I::InferRegion) -> Option<UniverseIndex>;
+
+    fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
+}
+
+impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
+    fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
+        match *self {}
+    }
+
+    fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
+        match *self {}
+    }
+
+    fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
+        match *self {}
+    }
+}
+
+pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result;
+}
+
+impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        <T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
+    }
+}
+
+impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        match f.alternate() {
+            true => {
+                write!(f, "[\n")?;
+                for element in this.data.iter() {
+                    write!(f, "{:?},\n", &this.wrap(element))?;
+                }
+                write!(f, "]")
+            }
+            false => {
+                write!(f, "[")?;
+                if this.data.len() > 0 {
+                    for element in &this.data[..(this.data.len() - 1)] {
+                        write!(f, "{:?}, ", &this.wrap(element))?;
+                    }
+                    if let Some(element) = this.data.last() {
+                        write!(f, "{:?}", &this.wrap(element))?;
+                    }
+                }
+                write!(f, "]")
+            }
+        }
+    }
+}
+
+pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
+    pub data: T,
+    pub infcx: Option<&'a InfCtx>,
+    _interner: PhantomData<I>,
+}
+
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}
+
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
+    fn clone(&self) -> Self {
+        Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
+    }
+}
+
+impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
+    pub fn new_no_ctx(data: T) -> Self {
+        Self { data, infcx: None, _interner: PhantomData }
+    }
+}
+
+impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
+    pub fn new(data: T, infcx: &'a InfCtx) -> Self {
+        Self { data, infcx: Some(infcx), _interner: PhantomData }
+    }
+
+    pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
+        OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
+    }
+
+    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
+        OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
+    }
+
+    pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
+        OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
+    }
+}
+
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
+    for OptWithInfcx<'_, I, InfCtx, T>
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        DebugWithInfcx::fmt(self.as_ref(), f)
+    }
+}
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
new file mode 100644
index 00000000000..2acb903c217
--- /dev/null
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -0,0 +1,119 @@
+bitflags! {
+    /// Flags that we track on types. These flags are propagated upwards
+    /// through the type during type construction, so that we can quickly check
+    /// whether the type has various kinds of types in it without recursing
+    /// over the type itself.
+    pub struct TypeFlags: u32 {
+        // Does this have parameters? Used to determine whether substitution is
+        // required.
+        /// Does this have `Param`?
+        const HAS_TY_PARAM                = 1 << 0;
+        /// Does this have `ReEarlyBound`?
+        const HAS_RE_PARAM                = 1 << 1;
+        /// Does this have `ConstKind::Param`?
+        const HAS_CT_PARAM                = 1 << 2;
+
+        const HAS_PARAM                 = TypeFlags::HAS_TY_PARAM.bits
+                                          | TypeFlags::HAS_RE_PARAM.bits
+                                          | TypeFlags::HAS_CT_PARAM.bits;
+
+        /// Does this have `Infer`?
+        const HAS_TY_INFER                = 1 << 3;
+        /// Does this have `ReVar`?
+        const HAS_RE_INFER                = 1 << 4;
+        /// Does this have `ConstKind::Infer`?
+        const HAS_CT_INFER                = 1 << 5;
+
+        /// Does this have inference variables? Used to determine whether
+        /// inference is required.
+        const HAS_INFER                 = TypeFlags::HAS_TY_INFER.bits
+                                          | TypeFlags::HAS_RE_INFER.bits
+                                          | TypeFlags::HAS_CT_INFER.bits;
+
+        /// Does this have `Placeholder`?
+        const HAS_TY_PLACEHOLDER          = 1 << 6;
+        /// Does this have `RePlaceholder`?
+        const HAS_RE_PLACEHOLDER          = 1 << 7;
+        /// Does this have `ConstKind::Placeholder`?
+        const HAS_CT_PLACEHOLDER          = 1 << 8;
+
+        /// Does this have placeholders?
+        const HAS_PLACEHOLDER           = TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_RE_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits;
+
+        /// `true` if there are "names" of regions and so forth
+        /// that are local to a particular fn/inferctxt
+        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;
+
+        /// `true` if there are "names" of types and regions and so forth
+        /// that are local to a particular fn
+        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
+                                          | TypeFlags::HAS_CT_PARAM.bits
+                                          | TypeFlags::HAS_TY_INFER.bits
+                                          | TypeFlags::HAS_CT_INFER.bits
+                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                          // We consider 'freshened' types and constants
+                                          // to depend on a particular fn.
+                                          // The freshening process throws away information,
+                                          // which can make things unsuitable for use in a global
+                                          // cache. Note that there is no 'fresh lifetime' flag -
+                                          // freshening replaces all lifetimes with `ReErased`,
+                                          // which is different from how types/const are freshened.
+                                          | TypeFlags::HAS_TY_FRESH.bits
+                                          | TypeFlags::HAS_CT_FRESH.bits
+                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
+                                          | TypeFlags::HAS_RE_ERASED.bits;
+
+        /// Does this have `Projection`?
+        const HAS_TY_PROJECTION           = 1 << 10;
+        /// Does this have `Inherent`?
+        const HAS_TY_INHERENT             = 1 << 11;
+        /// Does this have `Opaque`?
+        const HAS_TY_OPAQUE               = 1 << 12;
+        /// Does this have `ConstKind::Unevaluated`?
+        const HAS_CT_PROJECTION           = 1 << 13;
+
+        /// Could this type be normalized further?
+        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
+                                          | TypeFlags::HAS_TY_OPAQUE.bits
+                                          | TypeFlags::HAS_TY_INHERENT.bits
+                                          | TypeFlags::HAS_CT_PROJECTION.bits;
+
+        /// Is an error type/const reachable?
+        const HAS_ERROR                   = 1 << 14;
+
+        /// Does this have any region that "appears free" in the type?
+        /// Basically anything but `ReLateBound` and `ReErased`.
+        const HAS_FREE_REGIONS            = 1 << 15;
+
+        /// Does this have any `ReLateBound` regions?
+        const HAS_RE_LATE_BOUND           = 1 << 16;
+        /// Does this have any `Bound` types?
+        const HAS_TY_LATE_BOUND           = 1 << 17;
+        /// Does this have any `ConstKind::Bound` consts?
+        const HAS_CT_LATE_BOUND           = 1 << 18;
+        /// Does this have any bound variables?
+        /// Used to check if a global bound is safe to evaluate.
+        const HAS_LATE_BOUND              = TypeFlags::HAS_RE_LATE_BOUND.bits
+                                          | TypeFlags::HAS_TY_LATE_BOUND.bits
+                                          | TypeFlags::HAS_CT_LATE_BOUND.bits;
+
+        /// Does this have any `ReErased` regions?
+        const HAS_RE_ERASED               = 1 << 19;
+
+        /// Does this value have parameters/placeholders/inference variables which could be
+        /// replaced later, in a way that would change the results of `impl` specialization?
+        const STILL_FURTHER_SPECIALIZABLE = 1 << 20;
+
+        /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
+        const HAS_TY_FRESH                = 1 << 21;
+
+        /// Does this value have `InferConst::Fresh`?
+        const HAS_CT_FRESH                = 1 << 22;
+
+        /// Does this have `Generator` or `GeneratorWitness`?
+        const HAS_TY_GENERATOR            = 1 << 23;
+    }
+}
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index e7a6831f5ee..fc56400df16 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -44,6 +44,11 @@
 //!     - ty.super_fold_with(folder)
 //! - u.fold_with(folder)
 //! ```
+
+use rustc_data_structures::sync::Lrc;
+use rustc_index::{Idx, IndexVec};
+use std::mem;
+
 use crate::{visit::TypeVisitable, Interner};
 
 /// This trait is implemented for every type that can be folded,
@@ -242,3 +247,101 @@ where
         Ok(self.fold_predicate(p))
     }
 }
+
+///////////////////////////////////////////////////////////////////////////
+// Traversal implementations.
+
+impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
+        Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
+    }
+}
+
+impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
+    for (A, B, C)
+{
+    fn try_fold_with<F: FallibleTypeFolder<I>>(
+        self,
+        folder: &mut F,
+    ) -> Result<(A, B, C), F::Error> {
+        Ok((
+            self.0.try_fold_with(folder)?,
+            self.1.try_fold_with(folder)?,
+            self.2.try_fold_with(folder)?,
+        ))
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            Some(v) => Some(v.try_fold_with(folder)?),
+            None => None,
+        })
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            Ok(v) => Ok(v.try_fold_with(folder)?),
+            Err(e) => Err(e.try_fold_with(folder)?),
+        })
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
+        // We merely want to replace the contained `T`, if at all possible,
+        // so that we don't needlessly allocate a new `Lrc` or indeed clone
+        // the contained type.
+        unsafe {
+            // First step is to ensure that we have a unique reference to
+            // the contained type, which `Lrc::make_mut` will accomplish (by
+            // allocating a new `Lrc` and cloning the `T` only if required).
+            // This is done *before* casting to `Lrc<ManuallyDrop<T>>` so that
+            // panicking during `make_mut` does not leak the `T`.
+            Lrc::make_mut(&mut self);
+
+            // Casting to `Lrc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
+            // is `repr(transparent)`.
+            let ptr = Lrc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
+            let mut unique = Lrc::from_raw(ptr);
+
+            // Call to `Lrc::make_mut` above guarantees that `unique` is the
+            // sole reference to the contained value, so we can avoid doing
+            // a checked `get_mut` here.
+            let slot = Lrc::get_mut_unchecked(&mut unique);
+
+            // Semantically move the contained type out from `unique`, fold
+            // it, then move the folded value back into `unique`. Should
+            // folding fail, `ManuallyDrop` ensures that the "moved-out"
+            // value is not re-dropped.
+            let owned = mem::ManuallyDrop::take(slot);
+            let folded = owned.try_fold_with(folder)?;
+            *slot = mem::ManuallyDrop::new(folded);
+
+            // Cast back to `Lrc<T>`.
+            Ok(Lrc::from_raw(Lrc::into_raw(unique).cast()))
+        }
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
+        *self = (*self).try_fold_with(folder)?;
+        Ok(self)
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.into_iter().map(|t| t.try_fold_with(folder)).collect()
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.raw.try_fold_with(folder).map(IndexVec::from_raw)
+    }
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
new file mode 100644
index 00000000000..60e4c587993
--- /dev/null
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -0,0 +1,155 @@
+use smallvec::SmallVec;
+use std::fmt::Debug;
+use std::hash::Hash;
+
+use crate::{DebugWithInfcx, Mutability};
+
+pub trait Interner: Sized {
+    type DefId: Clone + Debug + Hash + Ord;
+    type AdtDef: Clone + Debug + Hash + Ord;
+
+    type GenericArgs: Clone
+        + DebugWithInfcx<Self>
+        + Hash
+        + Ord
+        + IntoIterator<Item = Self::GenericArg>;
+    type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord;
+
+    type Binder<T>;
+
+    // Predicates
+    type Predicate;
+    type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
+
+    type TypeAndMut: Clone + Debug + Hash + Ord;
+
+    // Kinds of tys
+    type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
+    type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type ParamTy: Clone + Debug + Hash + Ord;
+    type BoundTy: Clone + Debug + Hash + Ord;
+    type PlaceholderTy: Clone + Debug + Hash + Ord;
+    type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
+
+    // Things stored inside of tys
+    type ErrorGuaranteed: Clone + Debug + Hash + Ord;
+    type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type AllocId: Clone + Debug + Hash + Ord;
+
+    // Kinds of consts
+    type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type PlaceholderConst: Clone + Debug + Hash + Ord;
+    type ParamConst: Clone + Debug + Hash + Ord;
+    type BoundConst: Clone + Debug + Hash + Ord;
+    type ValueConst: Clone + Debug + Hash + Ord;
+    type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
+
+    // Kinds of regions
+    type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type EarlyBoundRegion: Clone + Debug + Hash + Ord;
+    type BoundRegion: Clone + Debug + Hash + Ord;
+    type FreeRegion: Clone + Debug + Hash + Ord;
+    type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type PlaceholderRegion: Clone + Debug + Hash + Ord;
+
+    fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
+}
+
+/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
+/// that produces `T` items. You could combine them with
+/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
+/// `Vec`.
+///
+/// This trait allows for faster implementations, intended for cases where the
+/// number of items produced by the iterator is small. There is a blanket impl
+/// for `T` items, but there is also a fallible impl for `Result<T, E>` items.
+pub trait CollectAndApply<T, R>: Sized {
+    type Output;
+
+    /// Produce a result of type `Self::Output` from `iter`. The result will
+    /// typically be produced by applying `f` on the elements produced by
+    /// `iter`, though this may not happen in some impls, e.g. if an error
+    /// occurred during iteration.
+    fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
+    where
+        I: Iterator<Item = Self>,
+        F: FnOnce(&[T]) -> R;
+}
+
+/// The blanket impl that always collects all elements and applies `f`.
+impl<T, R> CollectAndApply<T, R> for T {
+    type Output = R;
+
+    /// Equivalent to `f(&iter.collect::<Vec<_>>())`.
+    fn collect_and_apply<I, F>(mut iter: I, f: F) -> R
+    where
+        I: Iterator<Item = T>,
+        F: FnOnce(&[T]) -> R,
+    {
+        // This code is hot enough that it's worth specializing for the most
+        // common length lists, to avoid the overhead of `SmallVec` creation.
+        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
+        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
+        // `assert`.
+        match iter.size_hint() {
+            (0, Some(0)) => {
+                assert!(iter.next().is_none());
+                f(&[])
+            }
+            (1, Some(1)) => {
+                let t0 = iter.next().unwrap();
+                assert!(iter.next().is_none());
+                f(&[t0])
+            }
+            (2, Some(2)) => {
+                let t0 = iter.next().unwrap();
+                let t1 = iter.next().unwrap();
+                assert!(iter.next().is_none());
+                f(&[t0, t1])
+            }
+            _ => f(&iter.collect::<SmallVec<[_; 8]>>()),
+        }
+    }
+}
+
+/// A fallible impl that will fail, without calling `f`, if there are any
+/// errors during collection.
+impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
+    type Output = Result<R, E>;
+
+    /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`.
+    fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E>
+    where
+        I: Iterator<Item = Result<T, E>>,
+        F: FnOnce(&[T]) -> R,
+    {
+        // This code is hot enough that it's worth specializing for the most
+        // common length lists, to avoid the overhead of `SmallVec` creation.
+        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
+        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
+        // `assert`, unless a failure happens first, in which case the result
+        // will be an error anyway.
+        Ok(match iter.size_hint() {
+            (0, Some(0)) => {
+                assert!(iter.next().is_none());
+                f(&[])
+            }
+            (1, Some(1)) => {
+                let t0 = iter.next().unwrap()?;
+                assert!(iter.next().is_none());
+                f(&[t0])
+            }
+            (2, Some(2)) => {
+                let t0 = iter.next().unwrap()?;
+                let t1 = iter.next().unwrap()?;
+                assert!(iter.next().is_none());
+                f(&[t0, t1])
+            }
+            _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
+        })
+    }
+}
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 0a35e8d3a90..d4ca9da96e4 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -15,302 +15,35 @@ extern crate bitflags;
 #[macro_use]
 extern crate rustc_macros;
 
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
-use smallvec::SmallVec;
 use std::fmt;
-use std::fmt::Debug;
 use std::hash::Hash;
-use std::mem::discriminant;
 
 pub mod codec;
 pub mod fold;
-pub mod sty;
 pub mod ty_info;
+pub mod ty_kind;
 pub mod visit;
 
 #[macro_use]
 mod macros;
-mod structural_impls;
+mod const_kind;
+mod debug;
+mod flags;
+mod interner;
+mod region_kind;
 
 pub use codec::*;
-pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
-pub use sty::*;
+pub use const_kind::*;
+pub use debug::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
+pub use flags::*;
+pub use interner::*;
+pub use region_kind::*;
 pub use ty_info::*;
+pub use ty_kind::*;
 
 /// Needed so we can use #[derive(HashStable_Generic)]
 pub trait HashStableContext {}
 
-pub trait Interner: Sized {
-    type DefId: Clone + Debug + Hash + Ord;
-    type AdtDef: Clone + Debug + Hash + Ord;
-
-    type GenericArgs: Clone
-        + DebugWithInfcx<Self>
-        + Hash
-        + Ord
-        + IntoIterator<Item = Self::GenericArg>;
-    type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord;
-
-    type Binder<T>;
-
-    // Predicates
-    type Predicate;
-    type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
-
-    type TypeAndMut: Clone + Debug + Hash + Ord;
-
-    // Kinds of tys
-    type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
-    type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type ParamTy: Clone + Debug + Hash + Ord;
-    type BoundTy: Clone + Debug + Hash + Ord;
-    type PlaceholderTy: Clone + Debug + Hash + Ord;
-    type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
-
-    // Things stored inside of tys
-    type ErrorGuaranteed: Clone + Debug + Hash + Ord;
-    type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type AllocId: Clone + Debug + Hash + Ord;
-
-    // Kinds of consts
-    type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderConst: Clone + Debug + Hash + Ord;
-    type ParamConst: Clone + Debug + Hash + Ord;
-    type BoundConst: Clone + Debug + Hash + Ord;
-    type ValueConst: Clone + Debug + Hash + Ord;
-    type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
-
-    // Kinds of regions
-    type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type EarlyBoundRegion: Clone + Debug + Hash + Ord;
-    type BoundRegion: Clone + Debug + Hash + Ord;
-    type FreeRegion: Clone + Debug + Hash + Ord;
-    type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderRegion: Clone + Debug + Hash + Ord;
-
-    fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
-}
-
-/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
-/// that produces `T` items. You could combine them with
-/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
-/// `Vec`.
-///
-/// This trait allows for faster implementations, intended for cases where the
-/// number of items produced by the iterator is small. There is a blanket impl
-/// for `T` items, but there is also a fallible impl for `Result<T, E>` items.
-pub trait CollectAndApply<T, R>: Sized {
-    type Output;
-
-    /// Produce a result of type `Self::Output` from `iter`. The result will
-    /// typically be produced by applying `f` on the elements produced by
-    /// `iter`, though this may not happen in some impls, e.g. if an error
-    /// occurred during iteration.
-    fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
-    where
-        I: Iterator<Item = Self>,
-        F: FnOnce(&[T]) -> R;
-}
-
-/// The blanket impl that always collects all elements and applies `f`.
-impl<T, R> CollectAndApply<T, R> for T {
-    type Output = R;
-
-    /// Equivalent to `f(&iter.collect::<Vec<_>>())`.
-    fn collect_and_apply<I, F>(mut iter: I, f: F) -> R
-    where
-        I: Iterator<Item = T>,
-        F: FnOnce(&[T]) -> R,
-    {
-        // This code is hot enough that it's worth specializing for the most
-        // common length lists, to avoid the overhead of `SmallVec` creation.
-        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
-        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
-        // `assert`.
-        match iter.size_hint() {
-            (0, Some(0)) => {
-                assert!(iter.next().is_none());
-                f(&[])
-            }
-            (1, Some(1)) => {
-                let t0 = iter.next().unwrap();
-                assert!(iter.next().is_none());
-                f(&[t0])
-            }
-            (2, Some(2)) => {
-                let t0 = iter.next().unwrap();
-                let t1 = iter.next().unwrap();
-                assert!(iter.next().is_none());
-                f(&[t0, t1])
-            }
-            _ => f(&iter.collect::<SmallVec<[_; 8]>>()),
-        }
-    }
-}
-
-/// A fallible impl that will fail, without calling `f`, if there are any
-/// errors during collection.
-impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
-    type Output = Result<R, E>;
-
-    /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`.
-    fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E>
-    where
-        I: Iterator<Item = Result<T, E>>,
-        F: FnOnce(&[T]) -> R,
-    {
-        // This code is hot enough that it's worth specializing for the most
-        // common length lists, to avoid the overhead of `SmallVec` creation.
-        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
-        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
-        // `assert`, unless a failure happens first, in which case the result
-        // will be an error anyway.
-        Ok(match iter.size_hint() {
-            (0, Some(0)) => {
-                assert!(iter.next().is_none());
-                f(&[])
-            }
-            (1, Some(1)) => {
-                let t0 = iter.next().unwrap()?;
-                assert!(iter.next().is_none());
-                f(&[t0])
-            }
-            (2, Some(2)) => {
-                let t0 = iter.next().unwrap()?;
-                let t1 = iter.next().unwrap()?;
-                assert!(iter.next().is_none());
-                f(&[t0, t1])
-            }
-            _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
-        })
-    }
-}
-
-bitflags! {
-    /// Flags that we track on types. These flags are propagated upwards
-    /// through the type during type construction, so that we can quickly check
-    /// whether the type has various kinds of types in it without recursing
-    /// over the type itself.
-    pub struct TypeFlags: u32 {
-        // Does this have parameters? Used to determine whether substitution is
-        // required.
-        /// Does this have `Param`?
-        const HAS_TY_PARAM                = 1 << 0;
-        /// Does this have `ReEarlyBound`?
-        const HAS_RE_PARAM                = 1 << 1;
-        /// Does this have `ConstKind::Param`?
-        const HAS_CT_PARAM                = 1 << 2;
-
-        const HAS_PARAM                 = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_RE_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits;
-
-        /// Does this have `Infer`?
-        const HAS_TY_INFER                = 1 << 3;
-        /// Does this have `ReVar`?
-        const HAS_RE_INFER                = 1 << 4;
-        /// Does this have `ConstKind::Infer`?
-        const HAS_CT_INFER                = 1 << 5;
-
-        /// Does this have inference variables? Used to determine whether
-        /// inference is required.
-        const HAS_INFER                 = TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_RE_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits;
-
-        /// Does this have `Placeholder`?
-        const HAS_TY_PLACEHOLDER          = 1 << 6;
-        /// Does this have `RePlaceholder`?
-        const HAS_RE_PLACEHOLDER          = 1 << 7;
-        /// Does this have `ConstKind::Placeholder`?
-        const HAS_CT_PLACEHOLDER          = 1 << 8;
-
-        /// Does this have placeholders?
-        const HAS_PLACEHOLDER           = TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                          | TypeFlags::HAS_RE_PLACEHOLDER.bits
-                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits;
-
-        /// `true` if there are "names" of regions and so forth
-        /// that are local to a particular fn/inferctxt
-        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;
-
-        /// `true` if there are "names" of types and regions and so forth
-        /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits
-                                          | TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits
-                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                          // We consider 'freshened' types and constants
-                                          // to depend on a particular fn.
-                                          // The freshening process throws away information,
-                                          // which can make things unsuitable for use in a global
-                                          // cache. Note that there is no 'fresh lifetime' flag -
-                                          // freshening replaces all lifetimes with `ReErased`,
-                                          // which is different from how types/const are freshened.
-                                          | TypeFlags::HAS_TY_FRESH.bits
-                                          | TypeFlags::HAS_CT_FRESH.bits
-                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
-                                          | TypeFlags::HAS_RE_ERASED.bits;
-
-        /// Does this have `Projection`?
-        const HAS_TY_PROJECTION           = 1 << 10;
-        /// Does this have `Inherent`?
-        const HAS_TY_INHERENT             = 1 << 11;
-        /// Does this have `Opaque`?
-        const HAS_TY_OPAQUE               = 1 << 12;
-        /// Does this have `ConstKind::Unevaluated`?
-        const HAS_CT_PROJECTION           = 1 << 13;
-
-        /// Could this type be normalized further?
-        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
-                                          | TypeFlags::HAS_TY_OPAQUE.bits
-                                          | TypeFlags::HAS_TY_INHERENT.bits
-                                          | TypeFlags::HAS_CT_PROJECTION.bits;
-
-        /// Is an error type/const reachable?
-        const HAS_ERROR                   = 1 << 14;
-
-        /// Does this have any region that "appears free" in the type?
-        /// Basically anything but `ReLateBound` and `ReErased`.
-        const HAS_FREE_REGIONS            = 1 << 15;
-
-        /// Does this have any `ReLateBound` regions?
-        const HAS_RE_LATE_BOUND           = 1 << 16;
-        /// Does this have any `Bound` types?
-        const HAS_TY_LATE_BOUND           = 1 << 17;
-        /// Does this have any `ConstKind::Bound` consts?
-        const HAS_CT_LATE_BOUND           = 1 << 18;
-        /// Does this have any bound variables?
-        /// Used to check if a global bound is safe to evaluate.
-        const HAS_LATE_BOUND              = TypeFlags::HAS_RE_LATE_BOUND.bits
-                                          | TypeFlags::HAS_TY_LATE_BOUND.bits
-                                          | TypeFlags::HAS_CT_LATE_BOUND.bits;
-
-        /// Does this have any `ReErased` regions?
-        const HAS_RE_ERASED               = 1 << 19;
-
-        /// Does this value have parameters/placeholders/inference variables which could be
-        /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 20;
-
-        /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 21;
-
-        /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 22;
-
-        /// Does this have `Generator` or `GeneratorWitness`?
-        const HAS_TY_GENERATOR            = 1 << 23;
-    }
-}
-
 rustc_index::newtype_index! {
     /// A [De Bruijn index][dbi] is a standard means of representing
     /// regions (and perhaps later types) in a higher-ranked setting. In
@@ -434,259 +167,6 @@ pub fn debug_bound_var<T: std::fmt::Write>(
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
-pub enum IntTy {
-    Isize,
-    I8,
-    I16,
-    I32,
-    I64,
-    I128,
-}
-
-impl IntTy {
-    pub fn name_str(&self) -> &'static str {
-        match *self {
-            IntTy::Isize => "isize",
-            IntTy::I8 => "i8",
-            IntTy::I16 => "i16",
-            IntTy::I32 => "i32",
-            IntTy::I64 => "i64",
-            IntTy::I128 => "i128",
-        }
-    }
-
-    pub fn bit_width(&self) -> Option<u64> {
-        Some(match *self {
-            IntTy::Isize => return None,
-            IntTy::I8 => 8,
-            IntTy::I16 => 16,
-            IntTy::I32 => 32,
-            IntTy::I64 => 64,
-            IntTy::I128 => 128,
-        })
-    }
-
-    pub fn normalize(&self, target_width: u32) -> Self {
-        match self {
-            IntTy::Isize => match target_width {
-                16 => IntTy::I16,
-                32 => IntTy::I32,
-                64 => IntTy::I64,
-                _ => unreachable!(),
-            },
-            _ => *self,
-        }
-    }
-
-    pub fn to_unsigned(self) -> UintTy {
-        match self {
-            IntTy::Isize => UintTy::Usize,
-            IntTy::I8 => UintTy::U8,
-            IntTy::I16 => UintTy::U16,
-            IntTy::I32 => UintTy::U32,
-            IntTy::I64 => UintTy::U64,
-            IntTy::I128 => UintTy::U128,
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
-pub enum UintTy {
-    Usize,
-    U8,
-    U16,
-    U32,
-    U64,
-    U128,
-}
-
-impl UintTy {
-    pub fn name_str(&self) -> &'static str {
-        match *self {
-            UintTy::Usize => "usize",
-            UintTy::U8 => "u8",
-            UintTy::U16 => "u16",
-            UintTy::U32 => "u32",
-            UintTy::U64 => "u64",
-            UintTy::U128 => "u128",
-        }
-    }
-
-    pub fn bit_width(&self) -> Option<u64> {
-        Some(match *self {
-            UintTy::Usize => return None,
-            UintTy::U8 => 8,
-            UintTy::U16 => 16,
-            UintTy::U32 => 32,
-            UintTy::U64 => 64,
-            UintTy::U128 => 128,
-        })
-    }
-
-    pub fn normalize(&self, target_width: u32) -> Self {
-        match self {
-            UintTy::Usize => match target_width {
-                16 => UintTy::U16,
-                32 => UintTy::U32,
-                64 => UintTy::U64,
-                _ => unreachable!(),
-            },
-            _ => *self,
-        }
-    }
-
-    pub fn to_signed(self) -> IntTy {
-        match self {
-            UintTy::Usize => IntTy::Isize,
-            UintTy::U8 => IntTy::I8,
-            UintTy::U16 => IntTy::I16,
-            UintTy::U32 => IntTy::I32,
-            UintTy::U64 => IntTy::I64,
-            UintTy::U128 => IntTy::I128,
-        }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
-pub enum FloatTy {
-    F32,
-    F64,
-}
-
-impl FloatTy {
-    pub fn name_str(self) -> &'static str {
-        match self {
-            FloatTy::F32 => "f32",
-            FloatTy::F64 => "f64",
-        }
-    }
-
-    pub fn bit_width(self) -> u64 {
-        match self {
-            FloatTy::F32 => 32,
-            FloatTy::F64 => 64,
-        }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub enum IntVarValue {
-    IntType(IntTy),
-    UintType(UintTy),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct FloatVarValue(pub FloatTy);
-
-rustc_index::newtype_index! {
-    /// A **ty**pe **v**ariable **ID**.
-    #[debug_format = "?{}t"]
-    pub struct TyVid {}
-}
-
-rustc_index::newtype_index! {
-    /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
-    #[debug_format = "?{}i"]
-    pub struct IntVid {}
-}
-
-rustc_index::newtype_index! {
-    /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
-    #[debug_format = "?{}f"]
-    pub struct FloatVid {}
-}
-
-/// A placeholder for a type that hasn't been inferred yet.
-///
-/// E.g., if we have an empty array (`[]`), then we create a fresh
-/// type variable for the element type since we won't know until it's
-/// used what the element type is supposed to be.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-pub enum InferTy {
-    /// A type variable.
-    TyVar(TyVid),
-    /// An integral type variable (`{integer}`).
-    ///
-    /// These are created when the compiler sees an integer literal like
-    /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.).
-    /// We don't know until it's used what type it's supposed to be, so
-    /// we create a fresh type variable.
-    IntVar(IntVid),
-    /// A floating-point type variable (`{float}`).
-    ///
-    /// These are created when the compiler sees an float literal like
-    /// `1.0` that could be either an `f32` or an `f64`.
-    /// We don't know until it's used what type it's supposed to be, so
-    /// we create a fresh type variable.
-    FloatVar(FloatVid),
-
-    /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement
-    /// for an unbound type variable. This is convenient for caching etc. See
-    /// `rustc_infer::infer::freshen` for more details.
-    ///
-    /// Compare with [`TyVar`][Self::TyVar].
-    FreshTy(u32),
-    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar].
-    FreshIntTy(u32),
-    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar].
-    FreshFloatTy(u32),
-}
-
-/// Raw `TyVid` are used as the unification key for `sub_relations`;
-/// they carry no values.
-impl UnifyKey for TyVid {
-    type Value = ();
-    #[inline]
-    fn index(&self) -> u32 {
-        self.as_u32()
-    }
-    #[inline]
-    fn from_index(i: u32) -> TyVid {
-        TyVid::from_u32(i)
-    }
-    fn tag() -> &'static str {
-        "TyVid"
-    }
-}
-
-impl EqUnifyValue for IntVarValue {}
-
-impl UnifyKey for IntVid {
-    type Value = Option<IntVarValue>;
-    #[inline] // make this function eligible for inlining - it is quite hot.
-    fn index(&self) -> u32 {
-        self.as_u32()
-    }
-    #[inline]
-    fn from_index(i: u32) -> IntVid {
-        IntVid::from_u32(i)
-    }
-    fn tag() -> &'static str {
-        "IntVid"
-    }
-}
-
-impl EqUnifyValue for FloatVarValue {}
-
-impl UnifyKey for FloatVid {
-    type Value = Option<FloatVarValue>;
-    #[inline]
-    fn index(&self) -> u32 {
-        self.as_u32()
-    }
-    #[inline]
-    fn from_index(i: u32) -> FloatVid {
-        FloatVid::from_u32(i)
-    }
-    fn tag() -> &'static str {
-        "FloatVid"
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
 #[rustc_pass_by_value]
 pub enum Variance {
@@ -756,34 +236,6 @@ impl Variance {
     }
 }
 
-impl<CTX> HashStable<CTX> for InferTy {
-    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
-        use InferTy::*;
-        discriminant(self).hash_stable(ctx, hasher);
-        match self {
-            TyVar(_) | IntVar(_) | FloatVar(_) => {
-                panic!("type variables should not be hashed: {self:?}")
-            }
-            FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
-        }
-    }
-}
-
-impl fmt::Debug for IntVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            IntVarValue::IntType(ref v) => v.fmt(f),
-            IntVarValue::UintType(ref v) => v.fmt(f),
-        }
-    }
-}
-
-impl fmt::Debug for FloatVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
 impl fmt::Debug for Variance {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match *self {
@@ -795,20 +247,6 @@ impl fmt::Debug for Variance {
     }
 }
 
-impl fmt::Display for InferTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InferTy::*;
-        match *self {
-            TyVar(_) => write!(f, "_"),
-            IntVar(_) => write!(f, "{}", "{integer}"),
-            FloatVar(_) => write!(f, "{}", "{float}"),
-            FreshTy(v) => write!(f, "FreshTy({v})"),
-            FreshIntTy(v) => write!(f, "FreshIntTy({v})"),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"),
-        }
-    }
-}
-
 rustc_index::newtype_index! {
     /// "Universes" are used during type- and trait-checking in the
     /// presence of `for<..>` binders to control what sets of names are
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index 8c3cb228322..9e10c65c20d 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -33,3 +33,20 @@ macro_rules! TrivialTypeTraversalImpls {
         )+
     };
 }
+
+///////////////////////////////////////////////////////////////////////////
+// Atomic structs
+//
+// For things that don't carry any arena-allocated data (and are
+// copy...), just add them to this list.
+
+TrivialTypeTraversalImpls! {
+    (),
+    bool,
+    usize,
+    u16,
+    u32,
+    u64,
+    String,
+    crate::DebruijnIndex,
+}
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
new file mode 100644
index 00000000000..0006eec4d30
--- /dev/null
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -0,0 +1,412 @@
+use rustc_data_structures::stable_hasher::HashStable;
+use rustc_serialize::{Decodable, Decoder, Encodable};
+use std::cmp::Ordering;
+use std::fmt;
+use std::hash;
+
+use crate::{
+    DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx,
+    TyDecoder, TyEncoder,
+};
+
+use self::RegionKind::*;
+
+/// Representation of regions. Note that the NLL checker uses a distinct
+/// representation of regions. For this reason, it internally replaces all the
+/// regions with inference variables -- the index of the variable is then used
+/// to index into internal NLL data structures. See `rustc_const_eval::borrow_check`
+/// module for more information.
+///
+/// Note: operations are on the wrapper `Region` type, which is interned,
+/// rather than this type.
+///
+/// ## The Region lattice within a given function
+///
+/// In general, the region lattice looks like
+///
+/// ```text
+/// static ----------+-----...------+       (greatest)
+/// |                |              |
+/// early-bound and  |              |
+/// free regions     |              |
+/// |                |              |
+/// |                |              |
+/// empty(root)   placeholder(U1)   |
+/// |            /                  |
+/// |           /         placeholder(Un)
+/// empty(U1) --         /
+/// |                   /
+/// ...                /
+/// |                 /
+/// empty(Un) --------                      (smallest)
+/// ```
+///
+/// Early-bound/free regions are the named lifetimes in scope from the
+/// function declaration. They have relationships to one another
+/// determined based on the declared relationships from the
+/// function.
+///
+/// Note that inference variables and bound regions are not included
+/// in this diagram. In the case of inference variables, they should
+/// be inferred to some other region from the diagram. In the case of
+/// bound regions, they are excluded because they don't make sense to
+/// include -- the diagram indicates the relationship between free
+/// regions.
+///
+/// ## Inference variables
+///
+/// During region inference, we sometimes create inference variables,
+/// represented as `ReVar`. These will be inferred by the code in
+/// `infer::lexical_region_resolve` to some free region from the
+/// lattice above (the minimal region that meets the
+/// constraints).
+///
+/// During NLL checking, where regions are defined differently, we
+/// also use `ReVar` -- in that case, the index is used to index into
+/// the NLL region checker's data structures. The variable may in fact
+/// represent either a free region or an inference variable, in that
+/// case.
+///
+/// ## Bound Regions
+///
+/// These are regions that are stored behind a binder and must be substituted
+/// with some concrete region before being used. There are two kind of
+/// bound regions: early-bound, which are bound in an item's `Generics`,
+/// and are substituted by an `GenericArgs`, and late-bound, which are part of
+/// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
+/// the likes of `liberate_late_bound_regions`. The distinction exists
+/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
+///
+/// Unlike `Param`s, bound regions are not supposed to exist "in the wild"
+/// outside their binder, e.g., in types passed to type inference, and
+/// should first be substituted (by placeholder regions, free regions,
+/// or region variables).
+///
+/// ## Placeholder and Free Regions
+///
+/// One often wants to work with bound regions without knowing their precise
+/// identity. For example, when checking a function, the lifetime of a borrow
+/// can end up being assigned to some region parameter. In these cases,
+/// it must be ensured that bounds on the region can't be accidentally
+/// assumed without being checked.
+///
+/// To do this, we replace the bound regions with placeholder markers,
+/// which don't satisfy any relation not explicitly provided.
+///
+/// There are two kinds of placeholder regions in rustc: `ReFree` and
+/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
+/// to be used. These also support explicit bounds: both the internally-stored
+/// *scope*, which the region is assumed to outlive, as well as other
+/// relations stored in the `FreeRegionMap`. Note that these relations
+/// aren't checked when you `make_subregion` (or `eq_types`), only by
+/// `resolve_regions_and_report_errors`.
+///
+/// When working with higher-ranked types, some region relations aren't
+/// yet known, so you can't just call `resolve_regions_and_report_errors`.
+/// `RePlaceholder` is designed for this purpose. In these contexts,
+/// there's also the risk that some inference variable laying around will
+/// get unified with your placeholder region: if you want to check whether
+/// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
+/// with a placeholder region `'%a`, the variable `'_` would just be
+/// instantiated to the placeholder region `'%a`, which is wrong because
+/// the inference variable is supposed to satisfy the relation
+/// *for every value of the placeholder region*. To ensure that doesn't
+/// happen, you can use `leak_check`. This is more clearly explained
+/// by the [rustc dev guide].
+///
+/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
+/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
+pub enum RegionKind<I: Interner> {
+    /// Region bound in a type or fn declaration which will be
+    /// substituted 'early' -- that is, at the same time when type
+    /// parameters are substituted.
+    ReEarlyBound(I::EarlyBoundRegion),
+
+    /// Region bound in a function scope, which will be substituted when the
+    /// function is called.
+    ReLateBound(DebruijnIndex, I::BoundRegion),
+
+    /// When checking a function body, the types of all arguments and so forth
+    /// that refer to bound region parameters are modified to refer to free
+    /// region parameters.
+    ReFree(I::FreeRegion),
+
+    /// Static data that has an "infinite" lifetime. Top in the region lattice.
+    ReStatic,
+
+    /// A region variable. Should not exist outside of type inference.
+    ReVar(I::InferRegion),
+
+    /// A placeholder region -- basically, the higher-ranked version of `ReFree`.
+    /// Should not exist outside of type inference.
+    RePlaceholder(I::PlaceholderRegion),
+
+    /// Erased region, used by trait selection, in MIR and during codegen.
+    ReErased,
+
+    /// A region that resulted from some other error. Used exclusively for diagnostics.
+    ReError(I::ErrorGuaranteed),
+}
+
+// This is manually implemented for `RegionKind` because `std::mem::discriminant`
+// returns an opaque value that is `PartialEq` but not `PartialOrd`
+#[inline]
+const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
+    match value {
+        ReEarlyBound(_) => 0,
+        ReLateBound(_, _) => 1,
+        ReFree(_) => 2,
+        ReStatic => 3,
+        ReVar(_) => 4,
+        RePlaceholder(_) => 5,
+        ReErased => 6,
+        ReError(_) => 7,
+    }
+}
+
+// This is manually implemented because a derive would require `I: Copy`
+impl<I: Interner> Copy for RegionKind<I>
+where
+    I::EarlyBoundRegion: Copy,
+    I::BoundRegion: Copy,
+    I::FreeRegion: Copy,
+    I::InferRegion: Copy,
+    I::PlaceholderRegion: Copy,
+    I::ErrorGuaranteed: Copy,
+{
+}
+
+// This is manually implemented because a derive would require `I: Clone`
+impl<I: Interner> Clone for RegionKind<I> {
+    fn clone(&self) -> Self {
+        match self {
+            ReEarlyBound(r) => ReEarlyBound(r.clone()),
+            ReLateBound(d, r) => ReLateBound(*d, r.clone()),
+            ReFree(r) => ReFree(r.clone()),
+            ReStatic => ReStatic,
+            ReVar(r) => ReVar(r.clone()),
+            RePlaceholder(r) => RePlaceholder(r.clone()),
+            ReErased => ReErased,
+            ReError(r) => ReError(r.clone()),
+        }
+    }
+}
+
+// This is manually implemented because a derive would require `I: PartialEq`
+impl<I: Interner> PartialEq for RegionKind<I> {
+    #[inline]
+    fn eq(&self, other: &RegionKind<I>) -> bool {
+        regionkind_discriminant(self) == regionkind_discriminant(other)
+            && match (self, other) {
+                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
+                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
+                (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
+                (ReStatic, ReStatic) => true,
+                (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
+                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
+                (ReErased, ReErased) => true,
+                (ReError(_), ReError(_)) => true,
+                _ => {
+                    debug_assert!(
+                        false,
+                        "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
+                    );
+                    true
+                }
+            }
+    }
+}
+
+// This is manually implemented because a derive would require `I: Eq`
+impl<I: Interner> Eq for RegionKind<I> {}
+
+// This is manually implemented because a derive would require `I: PartialOrd`
+impl<I: Interner> PartialOrd for RegionKind<I> {
+    #[inline]
+    fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+// This is manually implemented because a derive would require `I: Ord`
+impl<I: Interner> Ord for RegionKind<I> {
+    #[inline]
+    fn cmp(&self, other: &RegionKind<I>) -> Ordering {
+        regionkind_discriminant(self).cmp(&regionkind_discriminant(other)).then_with(|| {
+            match (self, other) {
+                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
+                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
+                    a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
+                }
+                (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
+                (ReStatic, ReStatic) => Ordering::Equal,
+                (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
+                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
+                (ReErased, ReErased) => Ordering::Equal,
+                _ => {
+                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+                    Ordering::Equal
+                }
+            }
+        })
+    }
+}
+
+// This is manually implemented because a derive would require `I: Hash`
+impl<I: Interner> hash::Hash for RegionKind<I> {
+    fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
+        regionkind_discriminant(self).hash(state);
+        match self {
+            ReEarlyBound(r) => r.hash(state),
+            ReLateBound(d, r) => {
+                d.hash(state);
+                r.hash(state)
+            }
+            ReFree(r) => r.hash(state),
+            ReStatic => (),
+            ReVar(r) => r.hash(state),
+            RePlaceholder(r) => r.hash(state),
+            ReErased => (),
+            ReError(_) => (),
+        }
+    }
+}
+
+impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.data {
+            ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
+
+            ReLateBound(binder_id, bound_region) => {
+                write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
+            }
+
+            ReFree(fr) => write!(f, "{fr:?}"),
+
+            ReStatic => f.write_str("ReStatic"),
+
+            ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
+
+            RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
+
+            ReErased => f.write_str("ReErased"),
+
+            ReError(_) => f.write_str("ReError"),
+        }
+    }
+}
+impl<I: Interner> fmt::Debug for RegionKind<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+
+// This is manually implemented because a derive would require `I: Encodable`
+impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
+where
+    I::EarlyBoundRegion: Encodable<E>,
+    I::BoundRegion: Encodable<E>,
+    I::FreeRegion: Encodable<E>,
+    I::InferRegion: Encodable<E>,
+    I::PlaceholderRegion: Encodable<E>,
+{
+    fn encode(&self, e: &mut E) {
+        let disc = regionkind_discriminant(self);
+        match self {
+            ReEarlyBound(a) => e.emit_enum_variant(disc, |e| {
+                a.encode(e);
+            }),
+            ReLateBound(a, b) => e.emit_enum_variant(disc, |e| {
+                a.encode(e);
+                b.encode(e);
+            }),
+            ReFree(a) => e.emit_enum_variant(disc, |e| {
+                a.encode(e);
+            }),
+            ReStatic => e.emit_enum_variant(disc, |_| {}),
+            ReVar(a) => e.emit_enum_variant(disc, |e| {
+                a.encode(e);
+            }),
+            RePlaceholder(a) => e.emit_enum_variant(disc, |e| {
+                a.encode(e);
+            }),
+            ReErased => e.emit_enum_variant(disc, |_| {}),
+            ReError(_) => e.emit_enum_variant(disc, |_| {}),
+        }
+    }
+}
+
+// This is manually implemented because a derive would require `I: Decodable`
+impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I>
+where
+    I::EarlyBoundRegion: Decodable<D>,
+    I::BoundRegion: Decodable<D>,
+    I::FreeRegion: Decodable<D>,
+    I::InferRegion: Decodable<D>,
+    I::PlaceholderRegion: Decodable<D>,
+    I::ErrorGuaranteed: Decodable<D>,
+{
+    fn decode(d: &mut D) -> Self {
+        match Decoder::read_usize(d) {
+            0 => ReEarlyBound(Decodable::decode(d)),
+            1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)),
+            2 => ReFree(Decodable::decode(d)),
+            3 => ReStatic,
+            4 => ReVar(Decodable::decode(d)),
+            5 => RePlaceholder(Decodable::decode(d)),
+            6 => ReErased,
+            7 => ReError(Decodable::decode(d)),
+            _ => panic!(
+                "{}",
+                format!(
+                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                    "RegionKind", 8,
+                )
+            ),
+        }
+    }
+}
+
+// This is not a derived impl because a derive would require `I: HashStable`
+impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
+where
+    I::EarlyBoundRegion: HashStable<CTX>,
+    I::BoundRegion: HashStable<CTX>,
+    I::FreeRegion: HashStable<CTX>,
+    I::InferRegion: HashStable<CTX>,
+    I::PlaceholderRegion: HashStable<CTX>,
+{
+    #[inline]
+    fn hash_stable(
+        &self,
+        hcx: &mut CTX,
+        hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
+    ) {
+        std::mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            ReErased | ReStatic | ReError(_) => {
+                // No variant fields to hash for these ...
+            }
+            ReLateBound(d, r) => {
+                d.hash_stable(hcx, hasher);
+                r.hash_stable(hcx, hasher);
+            }
+            ReEarlyBound(r) => {
+                r.hash_stable(hcx, hasher);
+            }
+            ReFree(r) => {
+                r.hash_stable(hcx, hasher);
+            }
+            RePlaceholder(r) => {
+                r.hash_stable(hcx, hasher);
+            }
+            ReVar(_) => {
+                panic!("region variables should not be hashed: {self:?}")
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
deleted file mode 100644
index 93b3674b51a..00000000000
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-//! This module contains implementations of the `TypeFoldable` and `TypeVisitable`
-//! traits for various types in the Rust compiler. Most are written by hand, though
-//! we've recently added some macros and proc-macros to help with the tedium.
-
-use crate::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex};
-use rustc_data_structures::sync::Lrc;
-use rustc_index::{Idx, IndexVec};
-
-use core::fmt;
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::ControlFlow;
-
-///////////////////////////////////////////////////////////////////////////
-// Atomic structs
-//
-// For things that don't carry any arena-allocated data (and are
-// copy...), just add them to this list.
-
-TrivialTypeTraversalImpls! {
-    (),
-    bool,
-    usize,
-    u16,
-    u32,
-    u64,
-    String,
-    crate::DebruijnIndex,
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Traversal implementations.
-
-impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
-        Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.0.visit_with(visitor)?;
-        self.1.visit_with(visitor)
-    }
-}
-
-impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
-    for (A, B, C)
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(
-        self,
-        folder: &mut F,
-    ) -> Result<(A, B, C), F::Error> {
-        Ok((
-            self.0.try_fold_with(folder)?,
-            self.1.try_fold_with(folder)?,
-            self.2.try_fold_with(folder)?,
-        ))
-    }
-}
-
-impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
-    for (A, B, C)
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.0.visit_with(visitor)?;
-        self.1.visit_with(visitor)?;
-        self.2.visit_with(visitor)
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(match self {
-            Some(v) => Some(v.try_fold_with(folder)?),
-            None => None,
-        })
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        match self {
-            Some(v) => v.visit_with(visitor),
-            None => ControlFlow::Continue(()),
-        }
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(match self {
-            Ok(v) => Ok(v.try_fold_with(folder)?),
-            Err(e) => Err(e.try_fold_with(folder)?),
-        })
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        match self {
-            Ok(v) => v.visit_with(visitor),
-            Err(e) => e.visit_with(visitor),
-        }
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
-        // We merely want to replace the contained `T`, if at all possible,
-        // so that we don't needlessly allocate a new `Lrc` or indeed clone
-        // the contained type.
-        unsafe {
-            // First step is to ensure that we have a unique reference to
-            // the contained type, which `Lrc::make_mut` will accomplish (by
-            // allocating a new `Lrc` and cloning the `T` only if required).
-            // This is done *before* casting to `Lrc<ManuallyDrop<T>>` so that
-            // panicking during `make_mut` does not leak the `T`.
-            Lrc::make_mut(&mut self);
-
-            // Casting to `Lrc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
-            // is `repr(transparent)`.
-            let ptr = Lrc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
-            let mut unique = Lrc::from_raw(ptr);
-
-            // Call to `Lrc::make_mut` above guarantees that `unique` is the
-            // sole reference to the contained value, so we can avoid doing
-            // a checked `get_mut` here.
-            let slot = Lrc::get_mut_unchecked(&mut unique);
-
-            // Semantically move the contained type out from `unique`, fold
-            // it, then move the folded value back into `unique`. Should
-            // folding fail, `ManuallyDrop` ensures that the "moved-out"
-            // value is not re-dropped.
-            let owned = mem::ManuallyDrop::take(slot);
-            let folded = owned.try_fold_with(folder)?;
-            *slot = mem::ManuallyDrop::new(folded);
-
-            // Cast back to `Lrc<T>`.
-            Ok(Lrc::from_raw(Lrc::into_raw(unique).cast()))
-        }
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        (**self).visit_with(visitor)
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
-        *self = (*self).try_fold_with(folder)?;
-        Ok(self)
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        (**self).visit_with(visitor)
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        self.into_iter().map(|t| t.try_fold_with(folder)).collect()
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
-    }
-}
-
-// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general
-// case, because we can't return a new slice. But note that there are a couple
-// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
-    }
-}
-
-impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        self.raw.try_fold_with(folder).map(IndexVec::from_raw)
-    }
-}
-
-impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
-    }
-}
-
-///////////////////////////////////////////////////
-//  Debug impls
-
-pub trait InferCtxtLike<I: Interner> {
-    fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;
-    fn universe_of_lt(&self, lt: I::InferRegion) -> Option<UniverseIndex>;
-    fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
-}
-
-impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
-    fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
-        match *self {}
-    }
-    fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
-        match *self {}
-    }
-    fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
-        match *self {}
-    }
-}
-
-pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result;
-}
-
-impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        <T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
-    }
-}
-impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        match f.alternate() {
-            true => {
-                write!(f, "[\n")?;
-                for element in this.data.iter() {
-                    write!(f, "{:?},\n", &this.wrap(element))?;
-                }
-                write!(f, "]")
-            }
-            false => {
-                write!(f, "[")?;
-                if this.data.len() > 0 {
-                    for element in &this.data[..(this.data.len() - 1)] {
-                        write!(f, "{:?}, ", &this.wrap(element))?;
-                    }
-                    if let Some(element) = this.data.last() {
-                        write!(f, "{:?}", &this.wrap(element))?;
-                    }
-                }
-                write!(f, "]")
-            }
-        }
-    }
-}
-
-pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
-    pub data: T,
-    pub infcx: Option<&'a InfCtx>,
-    _interner: PhantomData<I>,
-}
-
-impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}
-impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
-    fn clone(&self) -> Self {
-        Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
-    }
-}
-
-impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
-    pub fn new_no_ctx(data: T) -> Self {
-        Self { data, infcx: None, _interner: PhantomData }
-    }
-}
-
-impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
-    pub fn new(data: T, infcx: &'a InfCtx) -> Self {
-        Self { data, infcx: Some(infcx), _interner: PhantomData }
-    }
-
-    pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
-        OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
-    }
-
-    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
-        OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
-    }
-
-    pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
-        OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
-    }
-}
-
-impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
-    for OptWithInfcx<'_, I, InfCtx, T>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        DebugWithInfcx::fmt(self.as_ref(), f)
-    }
-}
-
-impl fmt::Debug for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.name_str())
-    }
-}
-
-impl fmt::Debug for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.name_str())
-    }
-}
-
-impl fmt::Debug for FloatTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.name_str())
-    }
-}
-
-impl fmt::Debug for InferTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InferTy::*;
-        match *self {
-            TyVar(ref v) => v.fmt(f),
-            IntVar(ref v) => v.fmt(f),
-            FloatVar(ref v) => v.fmt(f),
-            FreshTy(v) => write!(f, "FreshTy({v:?})"),
-            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
-        }
-    }
-}
-impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut fmt::Formatter<'_>,
-    ) -> fmt::Result {
-        use InferTy::*;
-        match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) {
-            None => write!(f, "{:?}", this.data),
-            Some(universe) => match *this.data {
-                TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
-                IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
-                    unreachable!()
-                }
-            },
-        }
-    }
-}
-
-impl<I: Interner> fmt::Debug for ConstKind<I> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        OptWithInfcx::new_no_ctx(self).fmt(f)
-    }
-}
-impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        use ConstKind::*;
-
-        match this.data {
-            Param(param) => write!(f, "{param:?}"),
-            Infer(var) => write!(f, "{:?}", &this.wrap(var)),
-            Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
-            Placeholder(placeholder) => write!(f, "{placeholder:?}"),
-            Unevaluated(uv) => {
-                write!(f, "{:?}", &this.wrap(uv))
-            }
-            Value(valtree) => write!(f, "{valtree:?}"),
-            Error(_) => write!(f, "{{const error}}"),
-            Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
-        }
-    }
-}
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
index 4e5d424886a..d986e310c32 100644
--- a/compiler/rustc_type_ir/src/ty_info.rs
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -1,13 +1,8 @@
-use std::{
-    cmp::Ordering,
-    hash::{Hash, Hasher},
-    ops::Deref,
-};
-
-use rustc_data_structures::{
-    fingerprint::Fingerprint,
-    stable_hasher::{HashStable, StableHasher},
-};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use std::cmp::Ordering;
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
 
 use crate::{DebruijnIndex, TypeFlags};
 
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 5ca77701eb0..91bfce9a142 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,25 +1,22 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
+use rustc_serialize::{Decodable, Decoder, Encodable};
 use std::cmp::Ordering;
+use std::mem::discriminant;
 use std::{fmt, hash};
 
-use crate::FloatTy;
 use crate::HashStableContext;
-use crate::IntTy;
 use crate::Interner;
 use crate::TyDecoder;
 use crate::TyEncoder;
-use crate::UintTy;
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
 
-use self::RegionKind::*;
 use self::TyKind::*;
 
-use rustc_data_structures::stable_hasher::HashStable;
-use rustc_serialize::{Decodable, Decoder, Encodable};
-
-/// The movability of a generator / closure literal:
-/// whether a generator contains self-references, causing it to be `!Unpin`.
+/// The movability of a coroutine / closure literal:
+/// whether a coroutine contains self-references, causing it to be `!Unpin`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
 #[derive(HashStable_Generic)]
 pub enum Movability {
@@ -198,30 +195,30 @@ pub enum TyKind<I: Interner> {
     /// `ClosureArgs` for more details.
     Closure(I::DefId, I::GenericArgs),
 
-    /// The anonymous type of a generator. Used to represent the type of
+    /// The anonymous type of a coroutine. Used to represent the type of
     /// `|a| yield a`.
     ///
-    /// For more info about generator args, visit the documentation for
-    /// `GeneratorArgs`.
-    Generator(I::DefId, I::GenericArgs, Movability),
+    /// For more info about coroutine args, visit the documentation for
+    /// `CoroutineArgs`.
+    Coroutine(I::DefId, I::GenericArgs, Movability),
 
-    /// A type representing the types stored inside a generator.
-    /// This should only appear as part of the `GeneratorArgs`.
+    /// A type representing the types stored inside a coroutine.
+    /// This should only appear as part of the `CoroutineArgs`.
     ///
     /// Unlike upvars, the witness can reference lifetimes from
-    /// inside of the generator itself. To deal with them in
-    /// the type of the generator, we convert them to higher ranked
+    /// inside of the coroutine itself. To deal with them in
+    /// the type of the coroutine, we convert them to higher ranked
     /// lifetimes bound by the witness itself.
     ///
     /// This variant is only using when `drop_tracking_mir` is set.
-    /// This contains the `DefId` and the `GenericArgsRef` of the generator.
-    /// The actual witness types are computed on MIR by the `mir_generator_witnesses` query.
+    /// This contains the `DefId` and the `GenericArgsRef` of the coroutine.
+    /// The actual witness types are computed on MIR by the `mir_coroutine_witnesses` query.
     ///
-    /// Looking at the following example, the witness for this generator
+    /// Looking at the following example, the witness for this coroutine
     /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
     ///
     /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
-    /// #![feature(generators)]
+    /// #![feature(coroutines)]
     /// |a| {
     ///     let x = &vec![3];
     ///     yield a;
@@ -229,7 +226,7 @@ pub enum TyKind<I: Interner> {
     /// }
     /// # ;
     /// ```
-    GeneratorWitness(I::DefId, I::GenericArgs),
+    CoroutineWitness(I::DefId, I::GenericArgs),
 
     /// The never type `!`.
     Never,
@@ -314,8 +311,8 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
         FnPtr(_) => 13,
         Dynamic(..) => 14,
         Closure(_, _) => 15,
-        Generator(_, _, _) => 16,
-        GeneratorWitness(_, _) => 17,
+        Coroutine(_, _, _) => 16,
+        CoroutineWitness(_, _) => 17,
         Never => 18,
         Tuple(_) => 19,
         Alias(_, _) => 20,
@@ -347,8 +344,8 @@ impl<I: Interner> Clone for TyKind<I> {
             FnPtr(s) => FnPtr(s.clone()),
             Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
             Closure(d, s) => Closure(d.clone(), s.clone()),
-            Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
-            GeneratorWitness(d, s) => GeneratorWitness(d.clone(), s.clone()),
+            Coroutine(d, s, m) => Coroutine(d.clone(), s.clone(), m.clone()),
+            CoroutineWitness(d, s) => CoroutineWitness(d.clone(), s.clone()),
             Never => Never,
             Tuple(t) => Tuple(t.clone()),
             Alias(k, p) => Alias(*k, p.clone()),
@@ -387,10 +384,10 @@ impl<I: Interner> PartialEq for TyKind<I> {
                 a_p == b_p && a_r == b_r && a_repr == b_repr
             }
             (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
-            (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+            (Coroutine(a_d, a_s, a_m), Coroutine(b_d, b_s, b_m)) => {
                 a_d == b_d && a_s == b_s && a_m == b_m
             }
-            (GeneratorWitness(a_d, a_s), GeneratorWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
+            (CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
             (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
             (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
             (Param(a_p), Param(b_p)) => a_p == b_p,
@@ -444,12 +441,12 @@ impl<I: Interner> Ord for TyKind<I> {
                     a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr)))
                 }
                 (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)),
-                (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+                (Coroutine(a_d, a_s, a_m), Coroutine(b_d, b_s, b_m)) => {
                     a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
                 }
                 (
-                    GeneratorWitness(a_d, a_s),
-                    GeneratorWitness(b_d, b_s),
+                    CoroutineWitness(a_d, a_s),
+                    CoroutineWitness(b_d, b_s),
                 ) => match Ord::cmp(a_d, b_d) {
                     Ordering::Equal => Ord::cmp(a_s, b_s),
                     cmp => cmp,
@@ -509,12 +506,12 @@ impl<I: Interner> hash::Hash for TyKind<I> {
                 d.hash(state);
                 s.hash(state)
             }
-            Generator(d, s, m) => {
+            Coroutine(d, s, m) => {
                 d.hash(state);
                 s.hash(state);
                 m.hash(state)
             }
-            GeneratorWitness(d, s) => {
+            CoroutineWitness(d, s) => {
                 d.hash(state);
                 s.hash(state);
             }
@@ -587,9 +584,9 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                 }
             },
             Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
-            Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m),
-            GeneratorWitness(d, s) => {
-                f.debug_tuple_field2_finish("GeneratorWitness", d, &this.wrap(s))
+            Coroutine(d, s, m) => f.debug_tuple_field3_finish("Coroutine", d, &this.wrap(s), m),
+            CoroutineWitness(d, s) => {
+                f.debug_tuple_field2_finish("CoroutineWitness", d, &this.wrap(s))
             }
             Never => write!(f, "!"),
             Tuple(t) => {
@@ -699,12 +696,12 @@ where
                 def_id.encode(e);
                 args.encode(e);
             }),
-            Generator(def_id, args, m) => e.emit_enum_variant(disc, |e| {
+            Coroutine(def_id, args, m) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
                 args.encode(e);
                 m.encode(e);
             }),
-            GeneratorWitness(def_id, args) => e.emit_enum_variant(disc, |e| {
+            CoroutineWitness(def_id, args) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
                 args.encode(e);
             }),
@@ -777,8 +774,8 @@ where
             13 => FnPtr(Decodable::decode(d)),
             14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
             15 => Closure(Decodable::decode(d), Decodable::decode(d)),
-            16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
-            17 => GeneratorWitness(Decodable::decode(d), Decodable::decode(d)),
+            16 => Coroutine(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
+            17 => CoroutineWitness(Decodable::decode(d), Decodable::decode(d)),
             18 => Never,
             19 => Tuple(Decodable::decode(d)),
             20 => Alias(Decodable::decode(d), Decodable::decode(d)),
@@ -877,12 +874,12 @@ where
                 def_id.hash_stable(__hcx, __hasher);
                 args.hash_stable(__hcx, __hasher);
             }
-            Generator(def_id, args, m) => {
+            Coroutine(def_id, args, m) => {
                 def_id.hash_stable(__hcx, __hasher);
                 args.hash_stable(__hcx, __hasher);
                 m.hash_stable(__hcx, __hasher);
             }
-            GeneratorWitness(def_id, args) => {
+            CoroutineWitness(def_id, args) => {
                 def_id.hash_stable(__hcx, __hasher);
                 args.hash_stable(__hcx, __hasher);
             }
@@ -914,620 +911,347 @@ where
     }
 }
 
-/// Represents a constant in Rust.
-// #[derive(derive_more::From)]
-pub enum ConstKind<I: Interner> {
-    /// A const generic parameter.
-    Param(I::ParamConst),
-
-    /// Infer the value of the const.
-    Infer(I::InferConst),
-
-    /// Bound const variable, used only when preparing a trait query.
-    Bound(DebruijnIndex, I::BoundConst),
-
-    /// A placeholder const - universally quantified higher-ranked const.
-    Placeholder(I::PlaceholderConst),
-
-    /// An unnormalized const item such as an anon const or assoc const or free const item.
-    /// Right now anything other than anon consts does not actually work properly but this
-    /// should
-    Unevaluated(I::AliasConst),
-
-    /// Used to hold computed value.
-    Value(I::ValueConst),
-
-    /// A placeholder for a const which could not be computed; this is
-    /// propagated to avoid useless error messages.
-    Error(I::ErrorGuaranteed),
-
-    /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
-    /// const arguments such as `N + 1` or `foo(N)`
-    Expr(I::ExprConst),
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum IntTy {
+    Isize,
+    I8,
+    I16,
+    I32,
+    I64,
+    I128,
 }
 
-const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
-    match value {
-        ConstKind::Param(_) => 0,
-        ConstKind::Infer(_) => 1,
-        ConstKind::Bound(_, _) => 2,
-        ConstKind::Placeholder(_) => 3,
-        ConstKind::Unevaluated(_) => 4,
-        ConstKind::Value(_) => 5,
-        ConstKind::Error(_) => 6,
-        ConstKind::Expr(_) => 7,
+impl IntTy {
+    pub fn name_str(&self) -> &'static str {
+        match *self {
+            IntTy::Isize => "isize",
+            IntTy::I8 => "i8",
+            IntTy::I16 => "i16",
+            IntTy::I32 => "i32",
+            IntTy::I64 => "i64",
+            IntTy::I128 => "i128",
+        }
     }
-}
 
-impl<I: Interner> hash::Hash for ConstKind<I> {
-    fn hash<H: hash::Hasher>(&self, state: &mut H) {
-        const_kind_discriminant(self).hash(state);
+    pub fn bit_width(&self) -> Option<u64> {
+        Some(match *self {
+            IntTy::Isize => return None,
+            IntTy::I8 => 8,
+            IntTy::I16 => 16,
+            IntTy::I32 => 32,
+            IntTy::I64 => 64,
+            IntTy::I128 => 128,
+        })
+    }
+
+    pub fn normalize(&self, target_width: u32) -> Self {
         match self {
-            ConstKind::Param(p) => p.hash(state),
-            ConstKind::Infer(i) => i.hash(state),
-            ConstKind::Bound(d, b) => {
-                d.hash(state);
-                b.hash(state);
-            }
-            ConstKind::Placeholder(p) => p.hash(state),
-            ConstKind::Unevaluated(u) => u.hash(state),
-            ConstKind::Value(v) => v.hash(state),
-            ConstKind::Error(e) => e.hash(state),
-            ConstKind::Expr(e) => e.hash(state),
+            IntTy::Isize => match target_width {
+                16 => IntTy::I16,
+                32 => IntTy::I32,
+                64 => IntTy::I64,
+                _ => unreachable!(),
+            },
+            _ => *self,
         }
     }
-}
 
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
-where
-    I::ParamConst: HashStable<CTX>,
-    I::InferConst: HashStable<CTX>,
-    I::BoundConst: HashStable<CTX>,
-    I::PlaceholderConst: HashStable<CTX>,
-    I::AliasConst: HashStable<CTX>,
-    I::ValueConst: HashStable<CTX>,
-    I::ErrorGuaranteed: HashStable<CTX>,
-    I::ExprConst: HashStable<CTX>,
-{
-    fn hash_stable(
-        &self,
-        hcx: &mut CTX,
-        hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
-    ) {
-        const_kind_discriminant(self).hash_stable(hcx, hasher);
+    pub fn to_unsigned(self) -> UintTy {
         match self {
-            ConstKind::Param(p) => p.hash_stable(hcx, hasher),
-            ConstKind::Infer(i) => i.hash_stable(hcx, hasher),
-            ConstKind::Bound(d, b) => {
-                d.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            ConstKind::Placeholder(p) => p.hash_stable(hcx, hasher),
-            ConstKind::Unevaluated(u) => u.hash_stable(hcx, hasher),
-            ConstKind::Value(v) => v.hash_stable(hcx, hasher),
-            ConstKind::Error(e) => e.hash_stable(hcx, hasher),
-            ConstKind::Expr(e) => e.hash_stable(hcx, hasher),
+            IntTy::Isize => UintTy::Usize,
+            IntTy::I8 => UintTy::U8,
+            IntTy::I16 => UintTy::U16,
+            IntTy::I32 => UintTy::U32,
+            IntTy::I64 => UintTy::U64,
+            IntTy::I128 => UintTy::U128,
         }
     }
 }
 
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
-where
-    I::ParamConst: Decodable<D>,
-    I::InferConst: Decodable<D>,
-    I::BoundConst: Decodable<D>,
-    I::PlaceholderConst: Decodable<D>,
-    I::AliasConst: Decodable<D>,
-    I::ValueConst: Decodable<D>,
-    I::ErrorGuaranteed: Decodable<D>,
-    I::ExprConst: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => ConstKind::Param(Decodable::decode(d)),
-            1 => ConstKind::Infer(Decodable::decode(d)),
-            2 => ConstKind::Bound(Decodable::decode(d), Decodable::decode(d)),
-            3 => ConstKind::Placeholder(Decodable::decode(d)),
-            4 => ConstKind::Unevaluated(Decodable::decode(d)),
-            5 => ConstKind::Value(Decodable::decode(d)),
-            6 => ConstKind::Error(Decodable::decode(d)),
-            7 => ConstKind::Expr(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "ConstKind", 8,
-                )
-            ),
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum UintTy {
+    Usize,
+    U8,
+    U16,
+    U32,
+    U64,
+    U128,
+}
+
+impl UintTy {
+    pub fn name_str(&self) -> &'static str {
+        match *self {
+            UintTy::Usize => "usize",
+            UintTy::U8 => "u8",
+            UintTy::U16 => "u16",
+            UintTy::U32 => "u32",
+            UintTy::U64 => "u64",
+            UintTy::U128 => "u128",
         }
     }
-}
 
-impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
-where
-    I::ParamConst: Encodable<E>,
-    I::InferConst: Encodable<E>,
-    I::BoundConst: Encodable<E>,
-    I::PlaceholderConst: Encodable<E>,
-    I::AliasConst: Encodable<E>,
-    I::ValueConst: Encodable<E>,
-    I::ErrorGuaranteed: Encodable<E>,
-    I::ExprConst: Encodable<E>,
-{
-    fn encode(&self, e: &mut E) {
-        let disc = const_kind_discriminant(self);
+    pub fn bit_width(&self) -> Option<u64> {
+        Some(match *self {
+            UintTy::Usize => return None,
+            UintTy::U8 => 8,
+            UintTy::U16 => 16,
+            UintTy::U32 => 32,
+            UintTy::U64 => 64,
+            UintTy::U128 => 128,
+        })
+    }
+
+    pub fn normalize(&self, target_width: u32) -> Self {
         match self {
-            ConstKind::Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
-            ConstKind::Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
-            ConstKind::Bound(d, b) => e.emit_enum_variant(disc, |e| {
-                d.encode(e);
-                b.encode(e);
-            }),
-            ConstKind::Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
-            ConstKind::Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
-            ConstKind::Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
-            ConstKind::Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
-            ConstKind::Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
+            UintTy::Usize => match target_width {
+                16 => UintTy::U16,
+                32 => UintTy::U32,
+                64 => UintTy::U64,
+                _ => unreachable!(),
+            },
+            _ => *self,
         }
     }
-}
 
-impl<I: Interner> PartialOrd for ConstKind<I> {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(self.cmp(other))
+    pub fn to_signed(self) -> IntTy {
+        match self {
+            UintTy::Usize => IntTy::Isize,
+            UintTy::U8 => IntTy::I8,
+            UintTy::U16 => IntTy::I16,
+            UintTy::U32 => IntTy::I32,
+            UintTy::U64 => IntTy::I64,
+            UintTy::U128 => IntTy::I128,
+        }
     }
 }
 
-impl<I: Interner> Ord for ConstKind<I> {
-    fn cmp(&self, other: &Self) -> Ordering {
-        const_kind_discriminant(self)
-            .cmp(&const_kind_discriminant(other))
-            .then_with(|| match (self, other) {
-                (ConstKind::Param(p1), ConstKind::Param(p2)) => p1.cmp(p2),
-                (ConstKind::Infer(i1), ConstKind::Infer(i2)) => i1.cmp(i2),
-                (ConstKind::Bound(d1, b1), ConstKind::Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
-                (ConstKind::Placeholder(p1), ConstKind::Placeholder(p2)) => p1.cmp(p2),
-                (ConstKind::Unevaluated(u1), ConstKind::Unevaluated(u2)) => u1.cmp(u2),
-                (ConstKind::Value(v1), ConstKind::Value(v2)) => v1.cmp(v2),
-                (ConstKind::Error(e1), ConstKind::Error(e2)) => e1.cmp(e2),
-                (ConstKind::Expr(e1), ConstKind::Expr(e2)) => e1.cmp(e2),
-                _ => {
-                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
-                    Ordering::Equal
-                }
-            })
-    }
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum FloatTy {
+    F32,
+    F64,
 }
 
-impl<I: Interner> PartialEq for ConstKind<I> {
-    fn eq(&self, other: &Self) -> bool {
-        match (self, other) {
-            (Self::Param(l0), Self::Param(r0)) => l0 == r0,
-            (Self::Infer(l0), Self::Infer(r0)) => l0 == r0,
-            (Self::Bound(l0, l1), Self::Bound(r0, r1)) => l0 == r0 && l1 == r1,
-            (Self::Placeholder(l0), Self::Placeholder(r0)) => l0 == r0,
-            (Self::Unevaluated(l0), Self::Unevaluated(r0)) => l0 == r0,
-            (Self::Value(l0), Self::Value(r0)) => l0 == r0,
-            (Self::Error(l0), Self::Error(r0)) => l0 == r0,
-            (Self::Expr(l0), Self::Expr(r0)) => l0 == r0,
-            _ => false,
+impl FloatTy {
+    pub fn name_str(self) -> &'static str {
+        match self {
+            FloatTy::F32 => "f32",
+            FloatTy::F64 => "f64",
         }
     }
-}
-
-impl<I: Interner> Eq for ConstKind<I> {}
 
-impl<I: Interner> Clone for ConstKind<I> {
-    fn clone(&self) -> Self {
+    pub fn bit_width(self) -> u64 {
         match self {
-            Self::Param(arg0) => Self::Param(arg0.clone()),
-            Self::Infer(arg0) => Self::Infer(arg0.clone()),
-            Self::Bound(arg0, arg1) => Self::Bound(arg0.clone(), arg1.clone()),
-            Self::Placeholder(arg0) => Self::Placeholder(arg0.clone()),
-            Self::Unevaluated(arg0) => Self::Unevaluated(arg0.clone()),
-            Self::Value(arg0) => Self::Value(arg0.clone()),
-            Self::Error(arg0) => Self::Error(arg0.clone()),
-            Self::Expr(arg0) => Self::Expr(arg0.clone()),
+            FloatTy::F32 => 32,
+            FloatTy::F64 => 64,
         }
     }
 }
 
-/// Representation of regions. Note that the NLL checker uses a distinct
-/// representation of regions. For this reason, it internally replaces all the
-/// regions with inference variables -- the index of the variable is then used
-/// to index into internal NLL data structures. See `rustc_const_eval::borrow_check`
-/// module for more information.
-///
-/// Note: operations are on the wrapper `Region` type, which is interned,
-/// rather than this type.
-///
-/// ## The Region lattice within a given function
-///
-/// In general, the region lattice looks like
-///
-/// ```text
-/// static ----------+-----...------+       (greatest)
-/// |                |              |
-/// early-bound and  |              |
-/// free regions     |              |
-/// |                |              |
-/// |                |              |
-/// empty(root)   placeholder(U1)   |
-/// |            /                  |
-/// |           /         placeholder(Un)
-/// empty(U1) --         /
-/// |                   /
-/// ...                /
-/// |                 /
-/// empty(Un) --------                      (smallest)
-/// ```
-///
-/// Early-bound/free regions are the named lifetimes in scope from the
-/// function declaration. They have relationships to one another
-/// determined based on the declared relationships from the
-/// function.
-///
-/// Note that inference variables and bound regions are not included
-/// in this diagram. In the case of inference variables, they should
-/// be inferred to some other region from the diagram. In the case of
-/// bound regions, they are excluded because they don't make sense to
-/// include -- the diagram indicates the relationship between free
-/// regions.
-///
-/// ## Inference variables
-///
-/// During region inference, we sometimes create inference variables,
-/// represented as `ReVar`. These will be inferred by the code in
-/// `infer::lexical_region_resolve` to some free region from the
-/// lattice above (the minimal region that meets the
-/// constraints).
-///
-/// During NLL checking, where regions are defined differently, we
-/// also use `ReVar` -- in that case, the index is used to index into
-/// the NLL region checker's data structures. The variable may in fact
-/// represent either a free region or an inference variable, in that
-/// case.
-///
-/// ## Bound Regions
-///
-/// These are regions that are stored behind a binder and must be substituted
-/// with some concrete region before being used. There are two kind of
-/// bound regions: early-bound, which are bound in an item's `Generics`,
-/// and are substituted by an `GenericArgs`, and late-bound, which are part of
-/// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
-/// the likes of `liberate_late_bound_regions`. The distinction exists
-/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
-///
-/// Unlike `Param`s, bound regions are not supposed to exist "in the wild"
-/// outside their binder, e.g., in types passed to type inference, and
-/// should first be substituted (by placeholder regions, free regions,
-/// or region variables).
-///
-/// ## Placeholder and Free Regions
-///
-/// One often wants to work with bound regions without knowing their precise
-/// identity. For example, when checking a function, the lifetime of a borrow
-/// can end up being assigned to some region parameter. In these cases,
-/// it must be ensured that bounds on the region can't be accidentally
-/// assumed without being checked.
-///
-/// To do this, we replace the bound regions with placeholder markers,
-/// which don't satisfy any relation not explicitly provided.
-///
-/// There are two kinds of placeholder regions in rustc: `ReFree` and
-/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
-/// to be used. These also support explicit bounds: both the internally-stored
-/// *scope*, which the region is assumed to outlive, as well as other
-/// relations stored in the `FreeRegionMap`. Note that these relations
-/// aren't checked when you `make_subregion` (or `eq_types`), only by
-/// `resolve_regions_and_report_errors`.
-///
-/// When working with higher-ranked types, some region relations aren't
-/// yet known, so you can't just call `resolve_regions_and_report_errors`.
-/// `RePlaceholder` is designed for this purpose. In these contexts,
-/// there's also the risk that some inference variable laying around will
-/// get unified with your placeholder region: if you want to check whether
-/// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
-/// with a placeholder region `'%a`, the variable `'_` would just be
-/// instantiated to the placeholder region `'%a`, which is wrong because
-/// the inference variable is supposed to satisfy the relation
-/// *for every value of the placeholder region*. To ensure that doesn't
-/// happen, you can use `leak_check`. This is more clearly explained
-/// by the [rustc dev guide].
-///
-/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
-/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-pub enum RegionKind<I: Interner> {
-    /// Region bound in a type or fn declaration which will be
-    /// substituted 'early' -- that is, at the same time when type
-    /// parameters are substituted.
-    ReEarlyBound(I::EarlyBoundRegion),
-
-    /// Region bound in a function scope, which will be substituted when the
-    /// function is called.
-    ReLateBound(DebruijnIndex, I::BoundRegion),
-
-    /// When checking a function body, the types of all arguments and so forth
-    /// that refer to bound region parameters are modified to refer to free
-    /// region parameters.
-    ReFree(I::FreeRegion),
-
-    /// Static data that has an "infinite" lifetime. Top in the region lattice.
-    ReStatic,
-
-    /// A region variable. Should not exist outside of type inference.
-    ReVar(I::InferRegion),
-
-    /// A placeholder region -- basically, the higher-ranked version of `ReFree`.
-    /// Should not exist outside of type inference.
-    RePlaceholder(I::PlaceholderRegion),
-
-    /// Erased region, used by trait selection, in MIR and during codegen.
-    ReErased,
-
-    /// A region that resulted from some other error. Used exclusively for diagnostics.
-    ReError(I::ErrorGuaranteed),
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum IntVarValue {
+    IntType(IntTy),
+    UintType(UintTy),
 }
 
-// This is manually implemented for `RegionKind` because `std::mem::discriminant`
-// returns an opaque value that is `PartialEq` but not `PartialOrd`
-#[inline]
-const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
-    match value {
-        ReEarlyBound(_) => 0,
-        ReLateBound(_, _) => 1,
-        ReFree(_) => 2,
-        ReStatic => 3,
-        ReVar(_) => 4,
-        RePlaceholder(_) => 5,
-        ReErased => 6,
-        ReError(_) => 7,
-    }
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct FloatVarValue(pub FloatTy);
+
+rustc_index::newtype_index! {
+    /// A **ty**pe **v**ariable **ID**.
+    #[debug_format = "?{}t"]
+    pub struct TyVid {}
 }
 
-// This is manually implemented because a derive would require `I: Copy`
-impl<I: Interner> Copy for RegionKind<I>
-where
-    I::EarlyBoundRegion: Copy,
-    I::BoundRegion: Copy,
-    I::FreeRegion: Copy,
-    I::InferRegion: Copy,
-    I::PlaceholderRegion: Copy,
-    I::ErrorGuaranteed: Copy,
-{
+rustc_index::newtype_index! {
+    /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
+    #[debug_format = "?{}i"]
+    pub struct IntVid {}
 }
 
-// This is manually implemented because a derive would require `I: Clone`
-impl<I: Interner> Clone for RegionKind<I> {
-    fn clone(&self) -> Self {
-        match self {
-            ReEarlyBound(r) => ReEarlyBound(r.clone()),
-            ReLateBound(d, r) => ReLateBound(*d, r.clone()),
-            ReFree(r) => ReFree(r.clone()),
-            ReStatic => ReStatic,
-            ReVar(r) => ReVar(r.clone()),
-            RePlaceholder(r) => RePlaceholder(r.clone()),
-            ReErased => ReErased,
-            ReError(r) => ReError(r.clone()),
-        }
-    }
+rustc_index::newtype_index! {
+    /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
+    #[debug_format = "?{}f"]
+    pub struct FloatVid {}
 }
 
-// This is manually implemented because a derive would require `I: PartialEq`
-impl<I: Interner> PartialEq for RegionKind<I> {
+/// A placeholder for a type that hasn't been inferred yet.
+///
+/// E.g., if we have an empty array (`[]`), then we create a fresh
+/// type variable for the element type since we won't know until it's
+/// used what the element type is supposed to be.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+pub enum InferTy {
+    /// A type variable.
+    TyVar(TyVid),
+    /// An integral type variable (`{integer}`).
+    ///
+    /// These are created when the compiler sees an integer literal like
+    /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.).
+    /// We don't know until it's used what type it's supposed to be, so
+    /// we create a fresh type variable.
+    IntVar(IntVid),
+    /// A floating-point type variable (`{float}`).
+    ///
+    /// These are created when the compiler sees an float literal like
+    /// `1.0` that could be either an `f32` or an `f64`.
+    /// We don't know until it's used what type it's supposed to be, so
+    /// we create a fresh type variable.
+    FloatVar(FloatVid),
+
+    /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement
+    /// for an unbound type variable. This is convenient for caching etc. See
+    /// `rustc_infer::infer::freshen` for more details.
+    ///
+    /// Compare with [`TyVar`][Self::TyVar].
+    FreshTy(u32),
+    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar].
+    FreshIntTy(u32),
+    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar].
+    FreshFloatTy(u32),
+}
+
+/// Raw `TyVid` are used as the unification key for `sub_relations`;
+/// they carry no values.
+impl UnifyKey for TyVid {
+    type Value = ();
     #[inline]
-    fn eq(&self, other: &RegionKind<I>) -> bool {
-        regionkind_discriminant(self) == regionkind_discriminant(other)
-            && match (self, other) {
-                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
-                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
-                (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
-                (ReStatic, ReStatic) => true,
-                (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
-                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
-                (ReErased, ReErased) => true,
-                (ReError(_), ReError(_)) => true,
-                _ => {
-                    debug_assert!(
-                        false,
-                        "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
-                    );
-                    true
-                }
-            }
+    fn index(&self) -> u32 {
+        self.as_u32()
+    }
+    #[inline]
+    fn from_index(i: u32) -> TyVid {
+        TyVid::from_u32(i)
+    }
+    fn tag() -> &'static str {
+        "TyVid"
     }
 }
 
-// This is manually implemented because a derive would require `I: Eq`
-impl<I: Interner> Eq for RegionKind<I> {}
+impl EqUnifyValue for IntVarValue {}
 
-// This is manually implemented because a derive would require `I: PartialOrd`
-impl<I: Interner> PartialOrd for RegionKind<I> {
+impl UnifyKey for IntVid {
+    type Value = Option<IntVarValue>;
+    #[inline] // make this function eligible for inlining - it is quite hot.
+    fn index(&self) -> u32 {
+        self.as_u32()
+    }
     #[inline]
-    fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
-        Some(self.cmp(other))
+    fn from_index(i: u32) -> IntVid {
+        IntVid::from_u32(i)
+    }
+    fn tag() -> &'static str {
+        "IntVid"
     }
 }
 
-// This is manually implemented because a derive would require `I: Ord`
-impl<I: Interner> Ord for RegionKind<I> {
+impl EqUnifyValue for FloatVarValue {}
+
+impl UnifyKey for FloatVid {
+    type Value = Option<FloatVarValue>;
     #[inline]
-    fn cmp(&self, other: &RegionKind<I>) -> Ordering {
-        regionkind_discriminant(self).cmp(&regionkind_discriminant(other)).then_with(|| {
-            match (self, other) {
-                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
-                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
-                    a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
-                }
-                (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
-                (ReStatic, ReStatic) => Ordering::Equal,
-                (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
-                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
-                (ReErased, ReErased) => Ordering::Equal,
-                _ => {
-                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
-                    Ordering::Equal
-                }
-            }
-        })
+    fn index(&self) -> u32 {
+        self.as_u32()
+    }
+    #[inline]
+    fn from_index(i: u32) -> FloatVid {
+        FloatVid::from_u32(i)
+    }
+    fn tag() -> &'static str {
+        "FloatVid"
     }
 }
 
-// This is manually implemented because a derive would require `I: Hash`
-impl<I: Interner> hash::Hash for RegionKind<I> {
-    fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
-        regionkind_discriminant(self).hash(state);
+impl<CTX> HashStable<CTX> for InferTy {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        use InferTy::*;
+        discriminant(self).hash_stable(ctx, hasher);
         match self {
-            ReEarlyBound(r) => r.hash(state),
-            ReLateBound(d, r) => {
-                d.hash(state);
-                r.hash(state)
+            TyVar(_) | IntVar(_) | FloatVar(_) => {
+                panic!("type variables should not be hashed: {self:?}")
             }
-            ReFree(r) => r.hash(state),
-            ReStatic => (),
-            ReVar(r) => r.hash(state),
-            RePlaceholder(r) => r.hash(state),
-            ReErased => (),
-            ReError(_) => (),
+            FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
         }
     }
 }
 
-impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
-    fn fmt<InfCtx: InferCtxtLike<I>>(
-        this: OptWithInfcx<'_, I, InfCtx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.data {
-            ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
-
-            ReLateBound(binder_id, bound_region) => {
-                write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
-            }
-
-            ReFree(fr) => write!(f, "{fr:?}"),
-
-            ReStatic => f.write_str("ReStatic"),
-
-            ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
-
-            RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
+impl fmt::Debug for IntVarValue {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            IntVarValue::IntType(ref v) => v.fmt(f),
+            IntVarValue::UintType(ref v) => v.fmt(f),
+        }
+    }
+}
 
-            ReErased => f.write_str("ReErased"),
+impl fmt::Debug for FloatVarValue {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
 
-            ReError(_) => f.write_str("ReError"),
+impl fmt::Display for InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use InferTy::*;
+        match *self {
+            TyVar(_) => write!(f, "_"),
+            IntVar(_) => write!(f, "{}", "{integer}"),
+            FloatVar(_) => write!(f, "{}", "{float}"),
+            FreshTy(v) => write!(f, "FreshTy({v})"),
+            FreshIntTy(v) => write!(f, "FreshIntTy({v})"),
+            FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"),
         }
     }
 }
-impl<I: Interner> fmt::Debug for RegionKind<I> {
+
+impl fmt::Debug for IntTy {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        OptWithInfcx::new_no_ctx(self).fmt(f)
+        write!(f, "{}", self.name_str())
     }
 }
 
-// This is manually implemented because a derive would require `I: Encodable`
-impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
-where
-    I::EarlyBoundRegion: Encodable<E>,
-    I::BoundRegion: Encodable<E>,
-    I::FreeRegion: Encodable<E>,
-    I::InferRegion: Encodable<E>,
-    I::PlaceholderRegion: Encodable<E>,
-{
-    fn encode(&self, e: &mut E) {
-        let disc = regionkind_discriminant(self);
-        match self {
-            ReEarlyBound(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReLateBound(a, b) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-                b.encode(e);
-            }),
-            ReFree(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReStatic => e.emit_enum_variant(disc, |_| {}),
-            ReVar(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            RePlaceholder(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
-            ReErased => e.emit_enum_variant(disc, |_| {}),
-            ReError(_) => e.emit_enum_variant(disc, |_| {}),
-        }
+impl fmt::Debug for UintTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.name_str())
     }
 }
 
-// This is manually implemented because a derive would require `I: Decodable`
-impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I>
-where
-    I::EarlyBoundRegion: Decodable<D>,
-    I::BoundRegion: Decodable<D>,
-    I::FreeRegion: Decodable<D>,
-    I::InferRegion: Decodable<D>,
-    I::PlaceholderRegion: Decodable<D>,
-    I::ErrorGuaranteed: Decodable<D>,
-{
-    fn decode(d: &mut D) -> Self {
-        match Decoder::read_usize(d) {
-            0 => ReEarlyBound(Decodable::decode(d)),
-            1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)),
-            2 => ReFree(Decodable::decode(d)),
-            3 => ReStatic,
-            4 => ReVar(Decodable::decode(d)),
-            5 => RePlaceholder(Decodable::decode(d)),
-            6 => ReErased,
-            7 => ReError(Decodable::decode(d)),
-            _ => panic!(
-                "{}",
-                format!(
-                    "invalid enum variant tag while decoding `{}`, expected 0..{}",
-                    "RegionKind", 8,
-                )
-            ),
+impl fmt::Debug for FloatTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.name_str())
+    }
+}
+
+impl fmt::Debug for InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use InferTy::*;
+        match *self {
+            TyVar(ref v) => v.fmt(f),
+            IntVar(ref v) => v.fmt(f),
+            FloatVar(ref v) => v.fmt(f),
+            FreshTy(v) => write!(f, "FreshTy({v:?})"),
+            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
+            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
         }
     }
 }
 
-// This is not a derived impl because a derive would require `I: HashStable`
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
-where
-    I::EarlyBoundRegion: HashStable<CTX>,
-    I::BoundRegion: HashStable<CTX>,
-    I::FreeRegion: HashStable<CTX>,
-    I::InferRegion: HashStable<CTX>,
-    I::PlaceholderRegion: HashStable<CTX>,
-{
-    #[inline]
-    fn hash_stable(
-        &self,
-        hcx: &mut CTX,
-        hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
-    ) {
-        std::mem::discriminant(self).hash_stable(hcx, hasher);
-        match self {
-            ReErased | ReStatic | ReError(_) => {
-                // No variant fields to hash for these ...
-            }
-            ReLateBound(d, r) => {
-                d.hash_stable(hcx, hasher);
-                r.hash_stable(hcx, hasher);
-            }
-            ReEarlyBound(r) => {
-                r.hash_stable(hcx, hasher);
-            }
-            ReFree(r) => {
-                r.hash_stable(hcx, hasher);
-            }
-            RePlaceholder(r) => {
-                r.hash_stable(hcx, hasher);
-            }
-            ReVar(_) => {
-                panic!("region variables should not be hashed: {self:?}")
-            }
+impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        use InferTy::*;
+        match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) {
+            None => write!(f, "{:?}", this.data),
+            Some(universe) => match *this.data {
+                TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
+                IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
+                    unreachable!()
+                }
+            },
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 891a4dda22f..9c7b8156b04 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -40,11 +40,14 @@
 //!     - ty.super_visit_with(visitor)
 //! - u.visit_with(visitor)
 //! ```
-use crate::Interner;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_index::{Idx, IndexVec};
 use std::fmt;
 use std::ops::ControlFlow;
 
+use crate::Interner;
+
 /// This trait is implemented for every type that can be visited,
 /// providing the skeleton of the traversal.
 ///
@@ -116,3 +119,80 @@ pub trait TypeVisitor<I: Interner>: Sized {
         p.super_visit_with(self)
     }
 }
+
+///////////////////////////////////////////////////////////////////////////
+// Traversal implementations.
+
+impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.0.visit_with(visitor)?;
+        self.1.visit_with(visitor)
+    }
+}
+
+impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
+    for (A, B, C)
+{
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.0.visit_with(visitor)?;
+        self.1.visit_with(visitor)?;
+        self.2.visit_with(visitor)
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match self {
+            Some(v) => v.visit_with(visitor),
+            None => ControlFlow::Continue(()),
+        }
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match self {
+            Ok(v) => v.visit_with(visitor),
+            Err(e) => e.visit_with(visitor),
+        }
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        (**self).visit_with(visitor)
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        (**self).visit_with(visitor)
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.iter().try_for_each(|t| t.visit_with(visitor))
+    }
+}
+
+// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general
+// case, because we can't return a new slice. But note that there are a couple
+// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.iter().try_for_each(|t| t.visit_with(visitor))
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.iter().try_for_each(|t| t.visit_with(visitor))
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.iter().try_for_each(|t| t.visit_with(visitor))
+    }
+}
diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs
index 12ac8f1ca65..19910691456 100644
--- a/compiler/stable_mir/src/error.rs
+++ b/compiler/stable_mir/src/error.rs
@@ -4,6 +4,7 @@
 //! - [CompilerError]: This represents errors that can be raised when invoking the compiler.
 //! - [Error]: Generic error that represents the reason why a request that could not be fulfilled.
 
+use std::convert::From;
 use std::fmt::{Debug, Display, Formatter};
 use std::{error, fmt};
 
@@ -31,6 +32,12 @@ impl Error {
     }
 }
 
+impl From<&str> for Error {
+    fn from(value: &str) -> Self {
+        Self(value.into())
+    }
+}
+
 impl Display for Error {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         Display::fmt(&self.0, f)
diff --git a/compiler/stable_mir/src/fold.rs b/compiler/stable_mir/src/fold.rs
index 6471b2c2a3a..ca6ea92c4a1 100644
--- a/compiler/stable_mir/src/fold.rs
+++ b/compiler/stable_mir/src/fold.rs
@@ -155,7 +155,7 @@ impl Foldable for RigidTy {
             RigidTy::FnDef(_, args) => *args = args.fold(folder)?,
             RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?,
             RigidTy::Closure(_, args) => *args = args.fold(folder)?,
-            RigidTy::Generator(_, args, _) => *args = args.fold(folder)?,
+            RigidTy::Coroutine(_, args, _) => *args = args.fold(folder)?,
             RigidTy::Dynamic(pred, r, _) => {
                 *pred = pred.fold(folder)?;
                 *r = r.fold(folder)?;
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 59af3f64ad3..be5ccac78c7 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -39,6 +39,7 @@ pub mod visitor;
 
 pub use error::*;
 use mir::mono::Instance;
+use ty::{FnDef, GenericArgs};
 
 /// Use String for now but we should replace it.
 pub type Symbol = String;
@@ -233,6 +234,9 @@ pub trait Context {
 
     /// Item requires monomorphization.
     fn requires_monomorphization(&self, def_id: DefId) -> bool;
+
+    /// Resolve an instance from the given function definition and generic arguments.
+    fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
 }
 
 // A thread local variable that stores a pointer to the tables mapping between TyCtxt
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 72f026ee8de..5eee1ec00df 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,13 +1,15 @@
-use crate::ty::{AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region};
+use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region};
 use crate::Opaque;
 use crate::{ty::Ty, Span};
 
 #[derive(Clone, Debug)]
 pub struct Body {
     pub blocks: Vec<BasicBlock>,
-    pub locals: Vec<LocalDecl>,
+    pub locals: LocalDecls,
 }
 
+type LocalDecls = Vec<LocalDecl>;
+
 #[derive(Clone, Debug)]
 pub struct LocalDecl {
     pub ty: Ty,
@@ -59,7 +61,7 @@ pub enum TerminatorKind {
         target: usize,
         unwind: UnwindAction,
     },
-    GeneratorDrop,
+    CoroutineDrop,
     InlineAsm {
         template: String,
         operands: Vec<InlineAsmOperand>,
@@ -94,8 +96,8 @@ pub enum AssertMessage {
     OverflowNeg(Operand),
     DivisionByZero(Operand),
     RemainderByZero(Operand),
-    ResumedAfterReturn(GeneratorKind),
-    ResumedAfterPanic(GeneratorKind),
+    ResumedAfterReturn(CoroutineKind),
+    ResumedAfterPanic(CoroutineKind),
     MisalignedPointerDereference { required: Operand, found: Operand },
 }
 
@@ -132,13 +134,13 @@ pub enum UnOp {
 }
 
 #[derive(Clone, Debug)]
-pub enum GeneratorKind {
-    Async(AsyncGeneratorKind),
-    Gen,
+pub enum CoroutineKind {
+    Async(AsyncCoroutineKind),
+    Coroutine,
 }
 
 #[derive(Clone, Debug)]
-pub enum AsyncGeneratorKind {
+pub enum AsyncCoroutineKind {
     Block,
     Closure,
     Fn,
@@ -227,8 +229,8 @@ pub enum Rvalue {
     /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
     /// has a destructor.
     ///
-    /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
-    /// generator lowering, `Generator` aggregate kinds are disallowed too.
+    /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
+    /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
     Aggregate(AggregateKind, Vec<Operand>),
 
     /// * `Offset` has the same semantics as `<*const T>::offset`, except that the second
@@ -331,7 +333,7 @@ pub enum AggregateKind {
     Tuple,
     Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
     Closure(ClosureDef, GenericArgs),
-    Generator(GeneratorDef, GenericArgs, Movability),
+    Coroutine(CoroutineDef, GenericArgs, Movability),
 }
 
 #[derive(Clone, Debug)]
@@ -344,6 +346,7 @@ pub enum Operand {
 #[derive(Clone, Debug)]
 pub struct Place {
     pub local: Local,
+    /// projection out of a place (access a field, deref a pointer, etc)
     pub projection: String,
 }
 
@@ -462,3 +465,25 @@ pub enum NullOp {
     /// Returns the offset of a field.
     OffsetOf(Vec<FieldIdx>),
 }
+
+impl Operand {
+    pub fn ty(&self, locals: &LocalDecls) -> Ty {
+        match self {
+            Operand::Copy(place) | Operand::Move(place) => place.ty(locals),
+            Operand::Constant(c) => c.ty(),
+        }
+    }
+}
+
+impl Constant {
+    pub fn ty(&self) -> Ty {
+        self.literal.ty
+    }
+}
+
+impl Place {
+    pub fn ty(&self, locals: &LocalDecls) -> Ty {
+        let _start_ty = locals[self.local].ty;
+        todo!("Implement projection")
+    }
+}
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index d8e8ccb0454..997576fc7cb 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -1,5 +1,5 @@
 use crate::mir::Body;
-use crate::ty::{IndexedVal, Ty};
+use crate::ty::{FnDef, GenericArgs, IndexedVal, Ty};
 use crate::{with, CrateItem, DefId, Error, Opaque};
 use std::fmt::Debug;
 
@@ -41,6 +41,15 @@ impl Instance {
     pub fn ty(&self) -> Ty {
         with(|context| context.instance_ty(self.def))
     }
+
+    /// Resolve an instance starting from a function definition and generic arguments.
+    pub fn resolve(def: FnDef, args: &GenericArgs) -> Result<Instance, crate::Error> {
+        with(|context| {
+            context.resolve_instance(def, args).ok_or_else(|| {
+                crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))
+            })
+        })
+    }
 }
 
 /// Try to convert a crate item into an instance.
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 003045a4696..8f7f8bd4e38 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -142,7 +142,7 @@ pub enum RigidTy {
     FnDef(FnDef, GenericArgs),
     FnPtr(PolyFnSig),
     Closure(ClosureDef, GenericArgs),
-    Generator(GeneratorDef, GenericArgs, Movability),
+    Coroutine(CoroutineDef, GenericArgs, Movability),
     Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
     Never,
     Tuple(Vec<Ty>),
@@ -196,7 +196,7 @@ impl FnDef {
 pub struct ClosureDef(pub DefId);
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub struct GeneratorDef(pub DefId);
+pub struct CoroutineDef(pub DefId);
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct ParamDef(pub DefId);
@@ -225,6 +225,7 @@ pub struct ImplDef(pub DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct RegionDef(pub DefId);
 
+/// A list of generic arguments.
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index 96100958138..a6020cc5bd9 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -148,7 +148,7 @@ impl Visitable for RigidTy {
             RigidTy::FnDef(_, args) => args.visit(visitor),
             RigidTy::FnPtr(sig) => sig.visit(visitor),
             RigidTy::Closure(_, args) => args.visit(visitor),
-            RigidTy::Generator(_, args, _) => args.visit(visitor),
+            RigidTy::Coroutine(_, args, _) => args.visit(visitor),
             RigidTy::Dynamic(pred, r, _) => {
                 pred.visit(visitor)?;
                 r.visit(visitor)
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 96b93830f96..8ab851a0ea6 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -159,7 +159,7 @@ use core::marker::Tuple;
 use core::marker::Unsize;
 use core::mem::{self, SizedTypeProperties};
 use core::ops::{
-    CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver,
+    CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFromDyn, Receiver,
 };
 use core::pin::Pin;
 use core::ptr::{self, NonNull, Unique};
@@ -2106,28 +2106,28 @@ impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> where A: 'static {}
 
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R> + Unpin, R, A: Allocator> Generator<R> for Box<G, A>
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R> + Unpin, R, A: Allocator> Coroutine<R> for Box<G, A>
 where
     A: 'static,
 {
     type Yield = G::Yield;
     type Return = G::Return;
 
-    fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
         G::resume(Pin::new(&mut *self), arg)
     }
 }
 
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R>, R, A: Allocator> Generator<R> for Pin<Box<G, A>>
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R>, R, A: Allocator> Coroutine<R> for Pin<Box<G, A>>
 where
     A: 'static,
 {
     type Yield = G::Yield;
     type Return = G::Return;
 
-    fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
         G::resume((*self).as_mut(), arg)
     }
 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index d47f9de941c..f28ae9a07b4 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -169,7 +169,7 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(not(test), feature(generator_trait))]
+#![cfg_attr(not(test), feature(coroutine_trait))]
 #![cfg_attr(test, feature(panic_update_hook))]
 #![cfg_attr(test, feature(test))]
 #![feature(allocator_internals)]
diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs
index 6a8e55bff23..b41e457614e 100644
--- a/library/alloc/tests/autotraits.rs
+++ b/library/alloc/tests/autotraits.rs
@@ -14,8 +14,8 @@ fn test_btree_map() {
     //
     // We test autotraits in this convoluted way, instead of a straightforward
     // `require_send_sync::<TypeIWantToTest>()`, because the interaction with
-    // generators exposes some current limitations in rustc's ability to prove a
-    // lifetime bound on the erased generator witness types. See the above link.
+    // coroutines exposes some current limitations in rustc's ability to prove a
+    // lifetime bound on the erased coroutine witness types. See the above link.
     //
     // A typical way this would surface in real code is:
     //
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 089493d3766..0f77a2d8343 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -38,7 +38,7 @@ pub use poll_fn::{poll_fn, PollFn};
 
 /// This type is needed because:
 ///
-/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
+/// a) Coroutines cannot implement `for<'a, 'b> Coroutine<&'a mut Context<'b>>`, so we need to pass
 ///    a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>).
 /// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
 ///    non-Send/Sync as well, and we don't want that.
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index ca977d1ef82..937a149acaa 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -391,11 +391,11 @@ pub use self::traits::Iterator;
 pub use self::range::Step;
 
 #[unstable(
-    feature = "iter_from_generator",
+    feature = "iter_from_coroutine",
     issue = "43122",
-    reason = "generators are unstable"
+    reason = "coroutines are unstable"
 )]
-pub use self::sources::from_generator;
+pub use self::sources::from_coroutine;
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub use self::sources::{empty, Empty};
 #[stable(feature = "iter_from_fn", since = "1.34.0")]
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 3ec426a3ad9..56c1f86079a 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -1,6 +1,6 @@
 mod empty;
+mod from_coroutine;
 mod from_fn;
-mod from_generator;
 mod once;
 mod once_with;
 mod repeat;
@@ -27,11 +27,11 @@ pub use self::repeat_with::{repeat_with, RepeatWith};
 pub use self::from_fn::{from_fn, FromFn};
 
 #[unstable(
-    feature = "iter_from_generator",
+    feature = "iter_from_coroutine",
     issue = "43122",
-    reason = "generators are unstable"
+    reason = "coroutines are unstable"
 )]
-pub use self::from_generator::from_generator;
+pub use self::from_coroutine::from_coroutine;
 
 #[stable(feature = "iter_successors", since = "1.34.0")]
 pub use self::successors::{successors, Successors};
diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs
new file mode 100644
index 00000000000..16fbca9b65e
--- /dev/null
+++ b/library/core/src/iter/sources/from_coroutine.rs
@@ -0,0 +1,59 @@
+use crate::fmt;
+use crate::ops::{Coroutine, CoroutineState};
+use crate::pin::Pin;
+
+/// Creates a new iterator where each iteration calls the provided coroutine.
+///
+/// Similar to [`iter::from_fn`].
+///
+/// [`iter::from_fn`]: crate::iter::from_fn
+///
+/// # Examples
+///
+/// ```
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(iter_from_coroutine)]
+///
+/// let it = std::iter::from_coroutine(|| {
+///     yield 1;
+///     yield 2;
+///     yield 3;
+/// });
+/// let v: Vec<_> = it.collect();
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+#[inline]
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+pub fn from_coroutine<G: Coroutine<Return = ()> + Unpin>(coroutine: G) -> FromCoroutine<G> {
+    FromCoroutine(coroutine)
+}
+
+/// An iterator over the values yielded by an underlying coroutine.
+///
+/// This `struct` is created by the [`iter::from_coroutine()`] function. See its documentation for
+/// more.
+///
+/// [`iter::from_coroutine()`]: from_coroutine
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+#[derive(Clone)]
+pub struct FromCoroutine<G>(G);
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G: Coroutine<Return = ()> + Unpin> Iterator for FromCoroutine<G> {
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match Pin::new(&mut self.0).resume(()) {
+            CoroutineState::Yielded(n) => Some(n),
+            CoroutineState::Complete(()) => None,
+        }
+    }
+}
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G> fmt::Debug for FromCoroutine<G> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FromCoroutine").finish()
+    }
+}
diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs
deleted file mode 100644
index 4cbe731b222..00000000000
--- a/library/core/src/iter/sources/from_generator.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use crate::fmt;
-use crate::ops::{Generator, GeneratorState};
-use crate::pin::Pin;
-
-/// Creates a new iterator where each iteration calls the provided generator.
-///
-/// Similar to [`iter::from_fn`].
-///
-/// [`iter::from_fn`]: crate::iter::from_fn
-///
-/// # Examples
-///
-/// ```
-/// #![feature(generators)]
-/// #![feature(iter_from_generator)]
-///
-/// let it = std::iter::from_generator(|| {
-///     yield 1;
-///     yield 2;
-///     yield 3;
-/// });
-/// let v: Vec<_> = it.collect();
-/// assert_eq!(v, [1, 2, 3]);
-/// ```
-#[inline]
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-pub fn from_generator<G: Generator<Return = ()> + Unpin>(generator: G) -> FromGenerator<G> {
-    FromGenerator(generator)
-}
-
-/// An iterator over the values yielded by an underlying generator.
-///
-/// This `struct` is created by the [`iter::from_generator()`] function. See its documentation for
-/// more.
-///
-/// [`iter::from_generator()`]: from_generator
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-#[derive(Clone)]
-pub struct FromGenerator<G>(G);
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
-    type Item = G::Yield;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match Pin::new(&mut self.0).resume(()) {
-            GeneratorState::Yielded(n) => Some(n),
-            GeneratorState::Complete(()) => None,
-        }
-    }
-}
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G> fmt::Debug for FromGenerator<G> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("FromGenerator").finish()
-    }
-}
diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs
index 9309a06c8cf..8b31ab2ff90 100644
--- a/library/core/src/iter/sources/once_with.rs
+++ b/library/core/src/iter/sources/once_with.rs
@@ -4,7 +4,7 @@ use crate::iter::{FusedIterator, TrustedLen};
 /// Creates an iterator that lazily generates a value exactly once by invoking
 /// the provided closure.
 ///
-/// This is commonly used to adapt a single value generator into a [`chain()`] of
+/// This is commonly used to adapt a single value coroutine into a [`chain()`] of
 /// other kinds of iteration. Maybe you have an iterator that covers almost
 /// everything, but you need an extra special case. Maybe you have a function
 /// which works on iterators, but you only need to process one value.
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 6274a916f3e..855bb1675c5 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -242,7 +242,7 @@ use crate::slice;
 /// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that
 /// guarantee may evolve.
 #[stable(feature = "maybe_uninit", since = "1.36.0")]
-// Lang item so we can wrap other types in it. This is useful for generators.
+// Lang item so we can wrap other types in it. This is useful for coroutines.
 #[lang = "maybe_uninit"]
 #[derive(Copy)]
 #[repr(transparent)]
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
new file mode 100644
index 00000000000..e01a893a068
--- /dev/null
+++ b/library/core/src/ops/coroutine.rs
@@ -0,0 +1,139 @@
+use crate::marker::Unpin;
+use crate::pin::Pin;
+
+/// The result of a coroutine resumption.
+///
+/// This enum is returned from the `Coroutine::resume` method and indicates the
+/// possible return values of a coroutine. Currently this corresponds to either
+/// a suspension point (`Yielded`) or a termination point (`Complete`).
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[cfg_attr(bootstrap, lang = "generator_state")]
+#[cfg_attr(not(bootstrap), lang = "coroutine_state")]
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+pub enum CoroutineState<Y, R> {
+    /// The coroutine suspended with a value.
+    ///
+    /// This state indicates that a coroutine has been suspended, and typically
+    /// corresponds to a `yield` statement. The value provided in this variant
+    /// corresponds to the expression passed to `yield` and allows coroutines to
+    /// provide a value each time they yield.
+    Yielded(Y),
+
+    /// The coroutine completed with a return value.
+    ///
+    /// This state indicates that a coroutine has finished execution with the
+    /// provided value. Once a coroutine has returned `Complete` it is
+    /// considered a programmer error to call `resume` again.
+    Complete(R),
+}
+
+/// The trait implemented by builtin coroutine types.
+///
+/// Coroutines, also commonly referred to as coroutines, are currently an
+/// experimental language feature in Rust. Added in [RFC 2033] coroutines are
+/// currently intended to primarily provide a building block for async/await
+/// syntax but will likely extend to also providing an ergonomic definition for
+/// iterators and other primitives.
+///
+/// The syntax and semantics for coroutines is unstable and will require a
+/// further RFC for stabilization. At this time, though, the syntax is
+/// closure-like:
+///
+/// ```rust
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(coroutine_trait)]
+///
+/// use std::ops::{Coroutine, CoroutineState};
+/// use std::pin::Pin;
+///
+/// fn main() {
+///     let mut coroutine = || {
+///         yield 1;
+///         "foo"
+///     };
+///
+///     match Pin::new(&mut coroutine).resume(()) {
+///         CoroutineState::Yielded(1) => {}
+///         _ => panic!("unexpected return from resume"),
+///     }
+///     match Pin::new(&mut coroutine).resume(()) {
+///         CoroutineState::Complete("foo") => {}
+///         _ => panic!("unexpected return from resume"),
+///     }
+/// }
+/// ```
+///
+/// More documentation of coroutines can be found in the [unstable book].
+///
+/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
+/// [unstable book]: ../../unstable-book/language-features/coroutines.html
+#[cfg_attr(bootstrap, lang = "generator")]
+#[cfg_attr(not(bootstrap), lang = "coroutine")]
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+#[fundamental]
+pub trait Coroutine<R = ()> {
+    /// The type of value this coroutine yields.
+    ///
+    /// This associated type corresponds to the `yield` expression and the
+    /// values which are allowed to be returned each time a coroutine yields.
+    /// For example an iterator-as-a-coroutine would likely have this type as
+    /// `T`, the type being iterated over.
+    type Yield;
+
+    /// The type of value this coroutine returns.
+    ///
+    /// This corresponds to the type returned from a coroutine either with a
+    /// `return` statement or implicitly as the last expression of a coroutine
+    /// literal. For example futures would use this as `Result<T, E>` as it
+    /// represents a completed future.
+    type Return;
+
+    /// Resumes the execution of this coroutine.
+    ///
+    /// This function will resume execution of the coroutine or start execution
+    /// if it hasn't already. This call will return back into the coroutine's
+    /// last suspension point, resuming execution from the latest `yield`. The
+    /// coroutine will continue executing until it either yields or returns, at
+    /// which point this function will return.
+    ///
+    /// # Return value
+    ///
+    /// The `CoroutineState` enum returned from this function indicates what
+    /// state the coroutine is in upon returning. If the `Yielded` variant is
+    /// returned then the coroutine has reached a suspension point and a value
+    /// has been yielded out. Coroutines in this state are available for
+    /// resumption at a later point.
+    ///
+    /// If `Complete` is returned then the coroutine has completely finished
+    /// with the value provided. It is invalid for the coroutine to be resumed
+    /// again.
+    ///
+    /// # Panics
+    ///
+    /// This function may panic if it is called after the `Complete` variant has
+    /// been returned previously. While coroutine literals in the language are
+    /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
+    /// for all implementations of the `Coroutine` trait.
+    fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>;
+}
+
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R>, R> Coroutine<R> for Pin<&mut G> {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
+        G::resume((*self).as_mut(), arg)
+    }
+}
+
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R> + Unpin, R> Coroutine<R> for &mut G {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
+        G::resume(Pin::new(&mut *self), arg)
+    }
+}
diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs
deleted file mode 100644
index fee4beb1e84..00000000000
--- a/library/core/src/ops/generator.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-use crate::marker::Unpin;
-use crate::pin::Pin;
-
-/// The result of a generator resumption.
-///
-/// This enum is returned from the `Generator::resume` method and indicates the
-/// possible return values of a generator. Currently this corresponds to either
-/// a suspension point (`Yielded`) or a termination point (`Complete`).
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
-#[lang = "generator_state"]
-#[unstable(feature = "generator_trait", issue = "43122")]
-pub enum GeneratorState<Y, R> {
-    /// The generator suspended with a value.
-    ///
-    /// This state indicates that a generator has been suspended, and typically
-    /// corresponds to a `yield` statement. The value provided in this variant
-    /// corresponds to the expression passed to `yield` and allows generators to
-    /// provide a value each time they yield.
-    Yielded(Y),
-
-    /// The generator completed with a return value.
-    ///
-    /// This state indicates that a generator has finished execution with the
-    /// provided value. Once a generator has returned `Complete` it is
-    /// considered a programmer error to call `resume` again.
-    Complete(R),
-}
-
-/// The trait implemented by builtin generator types.
-///
-/// Generators, also commonly referred to as coroutines, are currently an
-/// experimental language feature in Rust. Added in [RFC 2033] generators are
-/// currently intended to primarily provide a building block for async/await
-/// syntax but will likely extend to also providing an ergonomic definition for
-/// iterators and other primitives.
-///
-/// The syntax and semantics for generators is unstable and will require a
-/// further RFC for stabilization. At this time, though, the syntax is
-/// closure-like:
-///
-/// ```rust
-/// #![feature(generators, generator_trait)]
-///
-/// use std::ops::{Generator, GeneratorState};
-/// use std::pin::Pin;
-///
-/// fn main() {
-///     let mut generator = || {
-///         yield 1;
-///         "foo"
-///     };
-///
-///     match Pin::new(&mut generator).resume(()) {
-///         GeneratorState::Yielded(1) => {}
-///         _ => panic!("unexpected return from resume"),
-///     }
-///     match Pin::new(&mut generator).resume(()) {
-///         GeneratorState::Complete("foo") => {}
-///         _ => panic!("unexpected return from resume"),
-///     }
-/// }
-/// ```
-///
-/// More documentation of generators can be found in the [unstable book].
-///
-/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
-/// [unstable book]: ../../unstable-book/language-features/generators.html
-#[lang = "generator"]
-#[unstable(feature = "generator_trait", issue = "43122")]
-#[fundamental]
-pub trait Generator<R = ()> {
-    /// The type of value this generator yields.
-    ///
-    /// This associated type corresponds to the `yield` expression and the
-    /// values which are allowed to be returned each time a generator yields.
-    /// For example an iterator-as-a-generator would likely have this type as
-    /// `T`, the type being iterated over.
-    type Yield;
-
-    /// The type of value this generator returns.
-    ///
-    /// This corresponds to the type returned from a generator either with a
-    /// `return` statement or implicitly as the last expression of a generator
-    /// literal. For example futures would use this as `Result<T, E>` as it
-    /// represents a completed future.
-    type Return;
-
-    /// Resumes the execution of this generator.
-    ///
-    /// This function will resume execution of the generator or start execution
-    /// if it hasn't already. This call will return back into the generator's
-    /// last suspension point, resuming execution from the latest `yield`. The
-    /// generator will continue executing until it either yields or returns, at
-    /// which point this function will return.
-    ///
-    /// # Return value
-    ///
-    /// The `GeneratorState` enum returned from this function indicates what
-    /// state the generator is in upon returning. If the `Yielded` variant is
-    /// returned then the generator has reached a suspension point and a value
-    /// has been yielded out. Generators in this state are available for
-    /// resumption at a later point.
-    ///
-    /// If `Complete` is returned then the generator has completely finished
-    /// with the value provided. It is invalid for the generator to be resumed
-    /// again.
-    ///
-    /// # Panics
-    ///
-    /// This function may panic if it is called after the `Complete` variant has
-    /// been returned previously. While generator literals in the language are
-    /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
-    /// for all implementations of the `Generator` trait.
-    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
-}
-
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut(), arg)
-    }
-}
-
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self), arg)
-    }
-}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 97d9b750d92..fd8271b1344 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -141,10 +141,10 @@
 mod arith;
 mod bit;
 mod control_flow;
+mod coroutine;
 mod deref;
 mod drop;
 mod function;
-mod generator;
 mod index;
 mod index_range;
 mod range;
@@ -198,8 +198,8 @@ pub use self::try_trait::Residual;
 
 pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
 
-#[unstable(feature = "generator_trait", issue = "43122")]
-pub use self::generator::{Generator, GeneratorState};
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+pub use self::coroutine::{Coroutine, CoroutineState};
 
 #[unstable(feature = "coerce_unsized", issue = "18598")]
 pub use self::unsize::CoerceUnsized;
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 94c682b615a..bca97d4ee36 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1085,17 +1085,19 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// # assert_eq!(42, block_on(async { 42 }));
 /// ```
 ///
-/// ### With `Generator`s
+/// ### With `Coroutine`s
 ///
 /// ```rust
-/// #![feature(generators, generator_trait)]
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(coroutine_trait)]
 /// use core::{
-///     ops::{Generator, GeneratorState},
+///     ops::{Coroutine, CoroutineState},
 ///     pin::pin,
 /// };
 ///
-/// fn generator_fn() -> impl Generator<Yield = usize, Return = ()> /* not Unpin */ {
-///  // Allow generator to be self-referential (not `Unpin`)
+/// 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 || {
 ///         let foo = String::from("foo");
@@ -1107,18 +1109,18 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// }
 ///
 /// fn main() {
-///     let mut generator = pin!(generator_fn());
-///     match generator.as_mut().resume(()) {
-///         GeneratorState::Yielded(0) => {},
+///     let mut coroutine = pin!(coroutine_fn());
+///     match coroutine.as_mut().resume(()) {
+///         CoroutineState::Yielded(0) => {},
 ///         _ => unreachable!(),
 ///     }
-///     match generator.as_mut().resume(()) {
-///         GeneratorState::Yielded(3) => {},
+///     match coroutine.as_mut().resume(()) {
+///         CoroutineState::Yielded(3) => {},
 ///         _ => unreachable!(),
 ///     }
-///     match generator.resume(()) {
-///         GeneratorState::Yielded(_) => unreachable!(),
-///         GeneratorState::Complete(()) => {},
+///     match coroutine.resume(()) {
+///         CoroutineState::Yielded(_) => unreachable!(),
+///         CoroutineState::Complete(()) => {},
 ///     }
 /// }
 /// ```
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 073488817c4..b5ad3f280e6 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -102,7 +102,7 @@
 //!
 //! | `target_arch` | Size limit |
 //! |---------------|---------|
-//! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes |
+//! | `x86`, `arm`, `mips`, `mips32r6`, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes |
 //! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes |
 //!
 //! Atomics loads that are larger than this limit as well as atomic loads with ordering other
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index ff538d55c60..fa02dd52e00 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -3,7 +3,7 @@
 use core::fmt;
 use core::future::Future;
 use core::marker::Tuple;
-use core::ops::{Generator, GeneratorState};
+use core::ops::{Coroutine, CoroutineState};
 use core::pin::Pin;
 use core::task::{Context, Poll};
 
@@ -206,16 +206,16 @@ where
     }
 }
 
-#[unstable(feature = "generator_trait", issue = "43122")] // also #98407
-impl<R, G> Generator<R> for Exclusive<G>
+#[unstable(feature = "coroutine_trait", issue = "43122")] // also #98407
+impl<R, G> Coroutine<R> for Exclusive<G>
 where
-    G: Generator<R> + ?Sized,
+    G: Coroutine<R> + ?Sized,
 {
     type Yield = G::Yield;
     type Return = G::Return;
 
     #[inline]
-    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+    fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
         G::resume(self.get_pin_mut(), arg)
     }
 }
diff --git a/library/std/build.rs b/library/std/build.rs
index 046ac488b1f..ad0a82eab8c 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -3,17 +3,11 @@ use std::env;
 fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
-    if target.contains("freebsd") {
-        if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() {
-            println!("cargo:rustc-cfg=freebsd12");
-        } else if env::var("RUST_STD_FREEBSD_13_ABI").is_ok() {
-            println!("cargo:rustc-cfg=freebsd12");
-            println!("cargo:rustc-cfg=freebsd13");
-        }
-    } else if target.contains("linux")
+    if target.contains("linux")
         || target.contains("netbsd")
         || target.contains("dragonfly")
         || target.contains("openbsd")
+        || target.contains("freebsd")
         || target.contains("solaris")
         || target.contains("illumos")
         || target.contains("apple-darwin")
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index be173a7ace6..4d109285d16 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -24,7 +24,7 @@ use crate::sys;
 /// reasonable best-effort is made to generate this seed from a high quality,
 /// secure source of randomness provided by the host without blocking the
 /// program. Because of this, the randomness of the seed depends on the output
-/// quality of the system's random number generator when the seed is created.
+/// quality of the system's random number coroutine when the seed is created.
 /// In particular, seeds generated when the system's entropy pool is abnormally
 /// low such as during system boot may be of a lower quality.
 ///
diff --git a/library/std/src/os/freebsd/fs.rs b/library/std/src/os/freebsd/fs.rs
index 8db3a950c40..5689a82e00a 100644
--- a/library/std/src/os/freebsd/fs.rs
+++ b/library/std/src/os/freebsd/fs.rs
@@ -76,12 +76,7 @@ impl MetadataExt for Metadata {
     fn as_raw_stat(&self) -> &raw::stat {
         // The methods below use libc::stat, so they work fine when libc is built with FreeBSD 12 ABI.
         // This method would just return nonsense.
-        #[cfg(freebsd12)]
         panic!("as_raw_stat not supported with FreeBSD 12 ABI");
-        #[cfg(not(freebsd12))]
-        unsafe {
-            &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat)
-        }
     }
     fn st_dev(&self) -> u64 {
         self.as_inner().as_inner().st_dev as u64
@@ -143,12 +138,7 @@ impl MetadataExt for Metadata {
     fn st_flags(&self) -> u32 {
         self.as_inner().as_inner().st_flags as u32
     }
-    #[cfg(freebsd12)]
     fn st_lspare(&self) -> u32 {
         panic!("st_lspare not supported with FreeBSD 12 ABI");
     }
-    #[cfg(not(freebsd12))]
-    fn st_lspare(&self) -> u32 {
-        self.as_inner().as_inner().st_lspare as u32
-    }
 }
diff --git a/src/doc/unstable-book/src/language-features/closure-track-caller.md b/src/doc/unstable-book/src/language-features/closure-track-caller.md
index c948810d3e5..99745223195 100644
--- a/src/doc/unstable-book/src/language-features/closure-track-caller.md
+++ b/src/doc/unstable-book/src/language-features/closure-track-caller.md
@@ -6,7 +6,7 @@ The tracking issue for this feature is: [#87417]
 
 ------------------------
 
-Allows using the `#[track_caller]` attribute on closures and generators.
-Calls made to the closure or generator will have caller information
+Allows using the `#[track_caller]` attribute on closures and coroutines.
+Calls made to the closure or coroutine will have caller information
 available through `std::panic::Location::caller()`, just like using
 `#[track_caller]` on a function.
diff --git a/src/doc/unstable-book/src/language-features/coroutines.md b/src/doc/unstable-book/src/language-features/coroutines.md
new file mode 100644
index 00000000000..fb1ba791aef
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/coroutines.md
@@ -0,0 +1,246 @@
+# `coroutines`
+
+The tracking issue for this feature is: [#43122]
+
+[#43122]: https://github.com/rust-lang/rust/issues/43122
+
+------------------------
+
+The `coroutines` feature gate in Rust allows you to define coroutine or
+coroutine literals. A coroutine is a "resumable function" that syntactically
+resembles a closure but compiles to much different semantics in the compiler
+itself. The primary feature of a coroutine is that it can be suspended during
+execution to be resumed at a later date. Coroutines use the `yield` keyword to
+"return", and then the caller can `resume` a coroutine to resume execution just
+after the `yield` keyword.
+
+Coroutines are an extra-unstable feature in the compiler right now. Added in
+[RFC 2033] they're mostly intended right now as a information/constraint
+gathering phase. The intent is that experimentation can happen on the nightly
+compiler before actual stabilization. A further RFC will be required to
+stabilize coroutines/coroutines and will likely contain at least a few small
+tweaks to the overall design.
+
+[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
+
+A syntactical example of a coroutine is:
+
+```rust
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+fn main() {
+    let mut coroutine = || {
+        yield 1;
+        return "foo"
+    };
+
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
+        _ => panic!("unexpected value from resume"),
+    }
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
+        _ => panic!("unexpected value from resume"),
+    }
+}
+```
+
+Coroutines are closure-like literals which 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
+resumes execution of the coroutine at the previous suspension point.
+
+An example of the control flow of coroutines is that the following example
+prints all numbers in order:
+
+```rust
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn main() {
+    let mut coroutine = || {
+        println!("2");
+        yield;
+        println!("4");
+    };
+
+    println!("1");
+    Pin::new(&mut coroutine).resume(());
+    println!("3");
+    Pin::new(&mut coroutine).resume(());
+    println!("5");
+}
+```
+
+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.
+Feedback on the design and usage is always appreciated!
+
+### The `Coroutine` trait
+
+The `Coroutine` trait in `std::ops` currently looks like:
+
+```rust
+# #![feature(arbitrary_self_types, coroutine_trait)]
+# use std::ops::CoroutineState;
+# use std::pin::Pin;
+
+pub trait Coroutine<R = ()> {
+    type Yield;
+    type Return;
+    fn resume(self: Pin<&mut Self>, resume: R) -> CoroutineState<Self::Yield, Self::Return>;
+}
+```
+
+The `Coroutine::Yield` type is the type of values that can be yielded with the
+`yield` statement. The `Coroutine::Return` type is the returned type of the
+coroutine. This is typically the last expression in a coroutine's definition or
+any value passed to `return` in a coroutine. The `resume` function is the entry
+point for executing the `Coroutine` itself.
+
+The return value of `resume`, `CoroutineState`, looks like:
+
+```rust
+pub enum CoroutineState<Y, R> {
+    Yielded(Y),
+    Complete(R),
+}
+```
+
+The `Yielded` variant indicates that the coroutine can later be resumed. This
+corresponds to a `yield` point in a coroutine. The `Complete` variant indicates
+that the coroutine is complete and cannot be resumed again. Calling `resume`
+after a coroutine has returned `Complete` will likely result in a panic of the
+program.
+
+### Closure-like semantics
+
+The closure-like syntax for coroutines alludes to the fact that they also have
+closure-like semantics. Namely:
+
+* When created, a coroutine executes no code. A closure literal does not
+  actually execute any of the closure's code on construction, and similarly a
+  coroutine literal does not execute any code inside the coroutine when
+  constructed.
+
+* Coroutines can capture outer variables by reference or by move, and this can
+  be tweaked with the `move` keyword at the beginning of the closure. Like
+  closures all coroutines will have an implicit environment which is inferred by
+  the compiler. Outer variables can be moved into a coroutine for use as the
+  coroutine progresses.
+
+* Coroutine literals produce a value with a unique type which implements the
+  `std::ops::Coroutine` trait. This allows actual execution of the coroutine
+  through the `Coroutine::resume` method as well as also naming it in return
+  types and such.
+
+* Traits like `Send` and `Sync` are automatically implemented for a `Coroutine`
+  depending on the captured variables of the environment. Unlike closures,
+  coroutines also depend on variables live across suspension points. This means
+  that although the ambient environment may be `Send` or `Sync`, the coroutine
+  itself may not be due to internal variables live across `yield` points being
+  not-`Send` or not-`Sync`. Note that coroutines do
+  not implement traits like `Copy` or `Clone` automatically.
+
+* Whenever a coroutine is dropped it will drop all captured environment
+  variables.
+
+### Coroutines as state machines
+
+In the compiler, coroutines are currently compiled as state machines. Each
+`yield` expression will correspond to a different state that stores all live
+variables over that suspension point. Resumption of a coroutine will dispatch on
+the current state and then execute internally until a `yield` is reached, at
+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)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn main() {
+    let ret = "foo";
+    let mut coroutine = move || {
+        yield 1;
+        return ret
+    };
+
+    Pin::new(&mut coroutine).resume(());
+    Pin::new(&mut coroutine).resume(());
+}
+```
+
+This coroutine literal will compile down to something similar to:
+
+```rust
+#![feature(arbitrary_self_types, coroutines, coroutine_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+fn main() {
+    let ret = "foo";
+    let mut coroutine = {
+        enum __Coroutine {
+            Start(&'static str),
+            Yield1(&'static str),
+            Done,
+        }
+
+        impl Coroutine for __Coroutine {
+            type Yield = i32;
+            type Return = &'static str;
+
+            fn resume(mut self: Pin<&mut Self>, resume: ()) -> CoroutineState<i32, &'static str> {
+                use std::mem;
+                match mem::replace(&mut *self, __Coroutine::Done) {
+                    __Coroutine::Start(s) => {
+                        *self = __Coroutine::Yield1(s);
+                        CoroutineState::Yielded(1)
+                    }
+
+                    __Coroutine::Yield1(s) => {
+                        *self = __Coroutine::Done;
+                        CoroutineState::Complete(s)
+                    }
+
+                    __Coroutine::Done => {
+                        panic!("coroutine resumed after completion")
+                    }
+                }
+            }
+        }
+
+        __Coroutine::Start(ret)
+    };
+
+    Pin::new(&mut coroutine).resume(());
+    Pin::new(&mut coroutine).resume(());
+}
+```
+
+Notably here we can see that the compiler is generating a fresh type,
+`__Coroutine` in this case. This type has a number of states (represented here
+as an `enum`) corresponding to each of the conceptual states of the coroutine.
+At the beginning we're closing over our outer variable `foo` and then that
+variable is also live over the `yield` point, so it's stored in both states.
+
+When the coroutine starts it'll immediately yield 1, but it saves off its state
+just before it does so indicating that it has reached the yield point. Upon
+resuming again we'll execute the `return ret` which returns the `Complete`
+state.
+
+Here we can also note that the `Done` state, if resumed, panics immediately as
+it's invalid to resume a completed coroutine. It's also worth noting that this
+is just a rough desugaring, not a normative specification for what the compiler
+does.
diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
deleted file mode 100644
index 7b865c9c679..00000000000
--- a/src/doc/unstable-book/src/language-features/generators.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# `generators`
-
-The tracking issue for this feature is: [#43122]
-
-[#43122]: https://github.com/rust-lang/rust/issues/43122
-
-------------------------
-
-The `generators` feature gate in Rust allows you to define generator or
-coroutine literals. A generator is a "resumable function" that syntactically
-resembles a closure but compiles to much different semantics in the compiler
-itself. The primary feature of a generator is that it can be suspended during
-execution to be resumed at a later date. Generators use the `yield` keyword to
-"return", and then the caller can `resume` a generator to resume execution just
-after the `yield` keyword.
-
-Generators are an extra-unstable feature in the compiler right now. Added in
-[RFC 2033] they're mostly intended right now as a information/constraint
-gathering phase. The intent is that experimentation can happen on the nightly
-compiler before actual stabilization. A further RFC will be required to
-stabilize generators/coroutines and will likely contain at least a few small
-tweaks to the overall design.
-
-[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
-
-A syntactical example of a generator is:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
-    let mut generator = || {
-        yield 1;
-        return "foo"
-    };
-
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
-        _ => panic!("unexpected value from resume"),
-    }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
-        _ => panic!("unexpected value from resume"),
-    }
-}
-```
-
-Generators are closure-like literals which can contain a `yield` statement. The
-`yield` statement takes an optional expression of a value to yield out of the
-generator. All generator literals implement the `Generator` trait in the
-`std::ops` module. The `Generator` trait has one main method, `resume`, which
-resumes execution of the generator at the previous suspension point.
-
-An example of the control flow of generators is that the following example
-prints all numbers in order:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-use std::pin::Pin;
-
-fn main() {
-    let mut generator = || {
-        println!("2");
-        yield;
-        println!("4");
-    };
-
-    println!("1");
-    Pin::new(&mut generator).resume(());
-    println!("3");
-    Pin::new(&mut generator).resume(());
-    println!("5");
-}
-```
-
-At this time the main intended use case of generators is an implementation
-primitive for async/await syntax, but generators will likely be extended to
-ergonomic implementations of iterators and other primitives in the future.
-Feedback on the design and usage is always appreciated!
-
-### The `Generator` trait
-
-The `Generator` trait in `std::ops` currently looks like:
-
-```rust
-# #![feature(arbitrary_self_types, generator_trait)]
-# use std::ops::GeneratorState;
-# use std::pin::Pin;
-
-pub trait Generator<R = ()> {
-    type Yield;
-    type Return;
-    fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
-}
-```
-
-The `Generator::Yield` type is the type of values that can be yielded with the
-`yield` statement. The `Generator::Return` type is the returned type of the
-generator. This is typically the last expression in a generator's definition or
-any value passed to `return` in a generator. The `resume` function is the entry
-point for executing the `Generator` itself.
-
-The return value of `resume`, `GeneratorState`, looks like:
-
-```rust
-pub enum GeneratorState<Y, R> {
-    Yielded(Y),
-    Complete(R),
-}
-```
-
-The `Yielded` variant indicates that the generator can later be resumed. This
-corresponds to a `yield` point in a generator. The `Complete` variant indicates
-that the generator is complete and cannot be resumed again. Calling `resume`
-after a generator has returned `Complete` will likely result in a panic of the
-program.
-
-### Closure-like semantics
-
-The closure-like syntax for generators alludes to the fact that they also have
-closure-like semantics. Namely:
-
-* When created, a generator executes no code. A closure literal does not
-  actually execute any of the closure's code on construction, and similarly a
-  generator literal does not execute any code inside the generator when
-  constructed.
-
-* Generators can capture outer variables by reference or by move, and this can
-  be tweaked with the `move` keyword at the beginning of the closure. Like
-  closures all generators will have an implicit environment which is inferred by
-  the compiler. Outer variables can be moved into a generator for use as the
-  generator progresses.
-
-* Generator literals produce a value with a unique type which implements the
-  `std::ops::Generator` trait. This allows actual execution of the generator
-  through the `Generator::resume` method as well as also naming it in return
-  types and such.
-
-* Traits like `Send` and `Sync` are automatically implemented for a `Generator`
-  depending on the captured variables of the environment. Unlike closures,
-  generators also depend on variables live across suspension points. This means
-  that although the ambient environment may be `Send` or `Sync`, the generator
-  itself may not be due to internal variables live across `yield` points being
-  not-`Send` or not-`Sync`. Note that generators do
-  not implement traits like `Copy` or `Clone` automatically.
-
-* Whenever a generator is dropped it will drop all captured environment
-  variables.
-
-### Generators as state machines
-
-In the compiler, generators are currently compiled as state machines. Each
-`yield` expression will correspond to a different state that stores all live
-variables over that suspension point. Resumption of a generator will dispatch on
-the current state and then execute internally until a `yield` is reached, at
-which point all state is saved off in the generator and a value is returned.
-
-Let's take a look at an example to see what's going on here:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-use std::pin::Pin;
-
-fn main() {
-    let ret = "foo";
-    let mut generator = move || {
-        yield 1;
-        return ret
-    };
-
-    Pin::new(&mut generator).resume(());
-    Pin::new(&mut generator).resume(());
-}
-```
-
-This generator literal will compile down to something similar to:
-
-```rust
-#![feature(arbitrary_self_types, generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
-    let ret = "foo";
-    let mut generator = {
-        enum __Generator {
-            Start(&'static str),
-            Yield1(&'static str),
-            Done,
-        }
-
-        impl Generator for __Generator {
-            type Yield = i32;
-            type Return = &'static str;
-
-            fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
-                use std::mem;
-                match mem::replace(&mut *self, __Generator::Done) {
-                    __Generator::Start(s) => {
-                        *self = __Generator::Yield1(s);
-                        GeneratorState::Yielded(1)
-                    }
-
-                    __Generator::Yield1(s) => {
-                        *self = __Generator::Done;
-                        GeneratorState::Complete(s)
-                    }
-
-                    __Generator::Done => {
-                        panic!("generator resumed after completion")
-                    }
-                }
-            }
-        }
-
-        __Generator::Start(ret)
-    };
-
-    Pin::new(&mut generator).resume(());
-    Pin::new(&mut generator).resume(());
-}
-```
-
-Notably here we can see that the compiler is generating a fresh type,
-`__Generator` in this case. This type has a number of states (represented here
-as an `enum`) corresponding to each of the conceptual states of the generator.
-At the beginning we're closing over our outer variable `foo` and then that
-variable is also live over the `yield` point, so it's stored in both states.
-
-When the generator starts it'll immediately yield 1, but it saves off its state
-just before it does so indicating that it has reached the yield point. Upon
-resuming again we'll execute the `return ret` which returns the `Complete`
-state.
-
-Here we can also note that the `Done` state, if resumed, panics immediately as
-it's invalid to resume a completed generator. It's also worth noting that this
-is just a rough desugaring, not a normative specification for what the compiler
-does.
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
index 9090b134dc6..0f4fb405669 100644
--- a/src/doc/unstable-book/src/the-unstable-book.md
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -5,31 +5,31 @@ 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(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut generator = || {
+    let mut coroutine = || {
         yield 1;
         return "foo"
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
         _ => panic!("unexpected value from resume"),
     }
 }
 ```
 
-The `generators` feature [has a chapter][generators] describing how to use it.
+The `coroutines` feature [has a chapter][coroutines] describing how to use it.
 
-[generators]: language-features/generators.md
+[coroutines]: language-features/coroutines.md
 
 Because this documentation relates to unstable features, we make no guarantees
 that what is contained here is accurate or up to date. It's developed on a
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e08318e4f54..7becc156142 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2266,9 +2266,9 @@ pub(crate) fn clean_middle_ty<'tcx>(
         }
 
         ty::Closure(..) => panic!("Closure"),
-        ty::Generator(..) => panic!("Generator"),
+        ty::Coroutine(..) => panic!("Coroutine"),
         ty::Placeholder(..) => panic!("Placeholder"),
-        ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
+        ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
         ty::Infer(..) => panic!("Infer"),
         ty::Error(_) => rustc_errors::FatalError.raise(),
     }
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index be2ee791588..e37d16f5bd0 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -141,7 +141,7 @@ impl From<DefKind> for ItemType {
             | DefKind::GlobalAsm
             | DefKind::Impl { .. }
             | DefKind::Closure
-            | DefKind::Generator => Self::ForeignType,
+            | DefKind::Coroutine => Self::ForeignType,
         }
     }
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index d216305e6a9..fcd07885894 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -521,8 +521,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             }
             ty::Alias(..)
             | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
+            | ty::Coroutine(..)
+            | ty::CoroutineWitness(..)
             | ty::Dynamic(..)
             | ty::Param(_)
             | ty::Bound(..)
@@ -1918,7 +1918,7 @@ fn resolution_failure(
                             Variant
                             | Field
                             | Closure
-                            | Generator
+                            | Coroutine
                             | AssocTy
                             | AssocConst
                             | AssocFn
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index fef25ad8635..26c9877dbff 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5463,6 +5463,7 @@ Released 2018-09-13
 [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 [`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
 [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
+[`struct_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names
 [`stutter`]: https://rust-lang.github.io/rust-clippy/master/index.html#stutter
 [`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
@@ -5625,6 +5626,7 @@ Released 2018-09-13
 [`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
 [`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
 [`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold
+[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold
 [`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold
 [`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
 [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index cbcb42dad79..2c50addfd7d 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -29,7 +29,7 @@ color-print = "0.3.4" # Sync version with Cargo
 anstream = "0.5.0"
 
 [dev-dependencies]
-ui_test = "0.20"
+ui_test = "0.21.2"
 tester = "0.9"
 regex = "1.5"
 toml = "0.7.3"
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index e001197842b..55c0e105b30 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -30,6 +30,7 @@ because that's clearly a non-descriptive name.
   - [Documentation](#documentation)
   - [Running rustfmt](#running-rustfmt)
   - [Debugging](#debugging)
+  - [Conflicting lints](#conflicting-lints)
   - [PR Checklist](#pr-checklist)
   - [Adding configuration to a lint](#adding-configuration-to-a-lint)
   - [Cheat Sheet](#cheat-sheet)
@@ -612,6 +613,24 @@ output in the `stdout` part.
 
 [`dbg!`]: https://doc.rust-lang.org/std/macro.dbg.html
 
+## Conflicting lints
+
+There are several lints that deal with the same pattern but suggest different approaches. In other words, some lints
+may suggest modifications that go in the opposite direction to what some other lints already propose for the same
+code, creating conflicting diagnostics.
+
+When you are creating a lint that ends up in this scenario, the following tips should be encouraged to guide
+classification:
+
+* The only case where they should be in the same category is if that category is `restriction`. For example,
+`semicolon_inside_block` and `semicolon_outside_block`.
+* For all the other cases, they should be in different categories with different levels of allowance. For example,
+`implicit_return` (restriction, allow) and `needless_return` (style, warn).
+
+For lints that are in different categories, it is also recommended that at least one of them should be in the
+`restriction` category. The reason for this is that the `restriction` group is the only group where we don't
+recommend to enable the entire set, but cherry pick lints out of.
+
 ## PR Checklist
 
 Before submitting your PR make sure you followed all the basic requirements:
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 2c958ccbbc2..c7eeed17954 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -100,7 +100,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat
 ## `msrv`
 The minimum rust version that the project supports
 
-**Default Value:** `None` (`Option<String>`)
+**Default Value:** `Msrv { stack: [] }` (`crate::Msrv`)
 
 ---
 **Affected lints:**
@@ -273,6 +273,16 @@ The minimum number of enum variants for the lints about variant names to trigger
 * [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
 
 
+## `struct-field-name-threshold`
+The minimum number of struct fields for the lints about field names to trigger
+
+**Default Value:** `3` (`u64`)
+
+---
+**Affected lints:**
+* [`struct_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_variant_names)
+
+
 ## `enum-variant-size-threshold`
 The maximum size of an enum's variant to avoid box suggestion
 
diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
index 9464694a3b5..56f56fff1e7 100644
--- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs
+++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::implements_trait;
 use rustc_errors::Applicability;
-use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath};
+use rustc_hir::{AsyncCoroutineKind, Body, BodyId, CoroutineKind, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -45,10 +45,10 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]);
 
 impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
     fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
-        use AsyncGeneratorKind::{Block, Closure};
+        use AsyncCoroutineKind::{Block, Closure};
         // For functions, with explicitly defined types, don't warn.
         // XXXkhuey maybe we should?
-        if let Some(GeneratorKind::Async(Block | Closure)) = body.generator_kind {
+        if let Some(CoroutineKind::Async(Block | Closure)) = body.coroutine_kind {
             if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() {
                 let body_id = BodyId {
                     hir_id: body.value.hir_id,
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index accff9b0a34..ae8618dcaa0 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{match_def_path, paths};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{AsyncGeneratorKind, Body, GeneratorKind};
+use rustc_hir::{AsyncCoroutineKind, Body, CoroutineKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::GeneratorLayout;
+use rustc_middle::mir::CoroutineLayout;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
 
@@ -195,26 +195,26 @@ impl LateLintPass<'_> for AwaitHolding {
     }
 
     fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
-        use AsyncGeneratorKind::{Block, Closure, Fn};
-        if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {
+        use AsyncCoroutineKind::{Block, Closure, Fn};
+        if let Some(CoroutineKind::Async(Block | Closure | Fn)) = body.coroutine_kind {
             let def_id = cx.tcx.hir().body_owner_def_id(body.id());
-            if let Some(generator_layout) = cx.tcx.mir_generator_witnesses(def_id) {
-                self.check_interior_types(cx, generator_layout);
+            if let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(def_id) {
+                self.check_interior_types(cx, coroutine_layout);
             }
         }
     }
 }
 
 impl AwaitHolding {
-    fn check_interior_types(&self, cx: &LateContext<'_>, generator: &GeneratorLayout<'_>) {
-        for (ty_index, ty_cause) in generator.field_tys.iter_enumerated() {
+    fn check_interior_types(&self, cx: &LateContext<'_>, coroutine: &CoroutineLayout<'_>) {
+        for (ty_index, ty_cause) in coroutine.field_tys.iter_enumerated() {
             if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
                 let await_points = || {
-                    generator
+                    coroutine
                         .variant_source_info
                         .iter_enumerated()
                         .filter_map(|(variant, source_info)| {
-                            generator.variant_fields[variant]
+                            coroutine.variant_fields[variant]
                                 .raw
                                 .contains(&ty_index)
                                 .then_some(source_info.span)
@@ -287,5 +287,8 @@ fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
 }
 
 fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool {
-    matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RefCellRef | sym::RefCellRefMut))
+    matches!(
+        cx.tcx.get_diagnostic_name(def_id),
+        Some(sym::RefCellRef | sym::RefCellRefMut)
+    )
 }
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 3f1ff66b8cf..cc9bd727937 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -3,8 +3,9 @@ use clippy_utils::macros::macro_backtrace;
 use clippy_utils::ty::expr_sig;
 use clippy_utils::{get_parent_node, is_default_equivalent, path_def_id};
 use rustc_errors::Applicability;
+use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::{def::Res, Block, Expr, ExprKind, Local, Node, QPath, TyKind};
+use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 481c44031cf..77438b27f90 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -154,9 +154,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO,
     crate::entry::MAP_ENTRY_INFO,
     crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO,
-    crate::enum_variants::ENUM_VARIANT_NAMES_INFO,
-    crate::enum_variants::MODULE_INCEPTION_INFO,
-    crate::enum_variants::MODULE_NAME_REPETITIONS_INFO,
     crate::equatable_if_let::EQUATABLE_IF_LET_INFO,
     crate::error_impl_error::ERROR_IMPL_ERROR_INFO,
     crate::escape::BOXED_LOCAL_INFO,
@@ -226,6 +223,10 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
     crate::int_plus_one::INT_PLUS_ONE_INFO,
     crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
+    crate::item_name_repetitions::ENUM_VARIANT_NAMES_INFO,
+    crate::item_name_repetitions::MODULE_INCEPTION_INFO,
+    crate::item_name_repetitions::MODULE_NAME_REPETITIONS_INFO,
+    crate::item_name_repetitions::STRUCT_FIELD_NAMES_INFO,
     crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
     crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
     crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index 3d6d257e386..2d11fa6b647 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_context;
 use clippy_utils::last_path_segment;
+use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 5134cf66050..efe82036dc8 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -842,8 +842,8 @@ impl TyCoercionStability {
                 | ty::Adt(..)
                 | ty::Foreign(_)
                 | ty::FnDef(..)
-                | ty::Generator(..)
-                | ty::GeneratorWitness(..)
+                | ty::Coroutine(..)
+                | ty::CoroutineWitness(..)
                 | ty::Closure(..)
                 | ty::Never
                 | ty::Tuple(_)
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index e789e0da679..fc9b381664a 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -436,8 +436,8 @@ fn lint_for_missing_headers(
                 let body = cx.tcx.hir().body(body_id);
                 let ret_ty = typeck.expr_ty(body.value);
                 if implements_trait(cx, ret_ty, future, &[]);
-                if let ty::Generator(_, subs, _) = ret_ty.kind();
-                if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result);
+                if let ty::Coroutine(_, subs, _) = ret_ty.kind();
+                if is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result);
                 then {
                     span_lint(
                         cx,
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index 5de79133c7d..5ecd0ffadf3 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{is_entrypoint_fn};
+use clippy_utils::is_entrypoint_fn;
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
index d82ea6d2fc8..617c96b4fcb 100644
--- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_c_void;
 use clippy_utils::path_def_id;
+use clippy_utils::ty::is_c_void;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
index 597fca88885..ee66c841ed2 100644
--- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -1,50 +1,104 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_test_function;
 
+use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, HirId};
+use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::symbol::Ident;
+use rustc_span::{BytePos, Span};
 
 use super::IMPL_TRAIT_IN_PARAMS;
 
+fn report(
+    cx: &LateContext<'_>,
+    param: &GenericParam<'_>,
+    ident: &Ident,
+    generics: &Generics<'_>,
+    first_param_span: Span,
+) {
+    // No generics with nested generics, and no generics like FnMut(x)
+    span_lint_and_then(
+        cx,
+        IMPL_TRAIT_IN_PARAMS,
+        param.span,
+        "`impl Trait` used as a function parameter",
+        |diag| {
+            if let Some(gen_span) = generics.span_for_param_suggestion() {
+                // If there's already a generic param with the same bound, do not lint **this** suggestion.
+                diag.span_suggestion_with_style(
+                    gen_span,
+                    "add a type parameter",
+                    format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
+                    rustc_errors::Applicability::HasPlaceholders,
+                    rustc_errors::SuggestionStyle::ShowAlways,
+                );
+            } else {
+                diag.span_suggestion_with_style(
+                    Span::new(
+                        first_param_span.lo() - rustc_span::BytePos(1),
+                        ident.span.hi(),
+                        ident.span.ctxt(),
+                        ident.span.parent(),
+                    ),
+                    "add a type parameter",
+                    format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
+                    rustc_errors::Applicability::HasPlaceholders,
+                    rustc_errors::SuggestionStyle::ShowAlways,
+                );
+            }
+        },
+    );
+}
+
 pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
-    if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() && !is_in_test_function(cx.tcx, hir_id)
-    {
-        if let FnKind::ItemFn(ident, generics, _) = kind {
+    if_chain! {
+        if let FnKind::ItemFn(ident, generics, _) = kind;
+        if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public();
+        if !is_in_test_function(cx.tcx, hir_id);
+        then {
             for param in generics.params {
                 if param.is_impl_trait() {
-                    // No generics with nested generics, and no generics like FnMut(x)
-                    span_lint_and_then(
-                        cx,
-                        IMPL_TRAIT_IN_PARAMS,
-                        param.span,
-                        "'`impl Trait` used as a function parameter'",
-                        |diag| {
-                            if let Some(gen_span) = generics.span_for_param_suggestion() {
-                                diag.span_suggestion_with_style(
-                                    gen_span,
-                                    "add a type parameter",
-                                    format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
-                                    rustc_errors::Applicability::HasPlaceholders,
-                                    rustc_errors::SuggestionStyle::ShowAlways,
-                                );
-                            } else {
-                                diag.span_suggestion_with_style(
-                                    Span::new(
-                                        body.params[0].span.lo() - rustc_span::BytePos(1),
-                                        ident.span.hi(),
-                                        ident.span.ctxt(),
-                                        ident.span.parent(),
-                                    ),
-                                    "add a type parameter",
-                                    format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
-                                    rustc_errors::Applicability::HasPlaceholders,
-                                    rustc_errors::SuggestionStyle::ShowAlways,
-                                );
-                            }
-                        },
-                    );
+                    report(cx, param, ident, generics, body.params[0].span);
+                };
+            }
+        }
+    }
+}
+
+pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
+    if_chain! {
+        if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
+        if let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id());
+        if let hir::ItemKind::Impl(impl_) = item.kind;
+        if let hir::Impl { of_trait, .. } = *impl_;
+        if of_trait.is_none();
+        let body = cx.tcx.hir().body(body_id);
+        if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public();
+        if !is_in_test_function(cx.tcx, impl_item.hir_id());
+        then {
+            for param in impl_item.generics.params {
+                if param.is_impl_trait() {
+                    report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span);
+                }
+            }
+        }
+    }
+}
+
+pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>, avoid_breaking_exported_api: bool) {
+    if_chain! {
+        if !avoid_breaking_exported_api;
+        if let TraitItemKind::Fn(_, _) = trait_item.kind;
+        if let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id());
+        // ^^ (Will always be a trait)
+        if !item.vis_span.is_empty(); // Is public
+        if !is_in_test_function(cx.tcx, trait_item.hir_id());
+        then {
+            for param in trait_item.generics.params {
+                if param.is_impl_trait() {
+                    let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1));
+                    report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi());
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index ee10334c67f..716908483e9 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -360,18 +360,26 @@ declare_clippy_lint! {
 }
 
 #[derive(Copy, Clone)]
+#[allow(clippy::struct_field_names)]
 pub struct Functions {
     too_many_arguments_threshold: u64,
     too_many_lines_threshold: u64,
     large_error_threshold: u64,
+    avoid_breaking_exported_api: bool,
 }
 
 impl Functions {
-    pub fn new(too_many_arguments_threshold: u64, too_many_lines_threshold: u64, large_error_threshold: u64) -> Self {
+    pub fn new(
+        too_many_arguments_threshold: u64,
+        too_many_lines_threshold: u64,
+        large_error_threshold: u64,
+        avoid_breaking_exported_api: bool,
+    ) -> Self {
         Self {
             too_many_arguments_threshold,
             too_many_lines_threshold,
             large_error_threshold,
+            avoid_breaking_exported_api,
         }
     }
 }
@@ -415,6 +423,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
         must_use::check_impl_item(cx, item);
         result::check_impl_item(cx, item, self.large_error_threshold);
+        impl_trait_in_params::check_impl_item(cx, item);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
@@ -422,5 +431,6 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
         not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
         must_use::check_trait_item(cx, item);
         result::check_trait_item(cx, item, self.large_error_threshold);
+        impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index e332f681b6d..8b4984da3dd 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -1,9 +1,10 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
+use clippy_utils::macros::span_is_local;
 use clippy_utils::source::is_present_in_source;
-use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start};
-use rustc_hir::{EnumDef, Item, ItemKind, OwnerId, Variant};
+use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
+use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
@@ -103,32 +104,184 @@ declare_clippy_lint! {
     style,
     "modules that have the same name as their parent module"
 }
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects struct fields that are prefixed or suffixed
+    /// by the same characters or the name of the struct itself.
+    ///
+    /// ### Why is this bad?
+    /// Information common to all struct fields is better represented in the struct name.
+    ///
+    /// ### Limitations
+    /// Characters with no casing will be considered when comparing prefixes/suffixes
+    /// This applies to numbers and non-ascii characters without casing
+    /// e.g. `foo1` and `foo2` is considered to have different prefixes
+    /// (the prefixes are `foo1` and `foo2` respectively), as also `bar螃`, `bar蟹`
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct Cake {
+    ///     cake_sugar: u8,
+    ///     cake_flour: u8,
+    ///     cake_eggs: u8
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct Cake {
+    ///     sugar: u8,
+    ///     flour: u8,
+    ///     eggs: u8
+    /// }
+    /// ```
+    #[clippy::version = "1.75.0"]
+    pub STRUCT_FIELD_NAMES,
+    pedantic,
+    "structs where all fields share a prefix/postfix or contain the name of the struct"
+}
 
-pub struct EnumVariantNames {
+pub struct ItemNameRepetitions {
     modules: Vec<(Symbol, String, OwnerId)>,
-    threshold: u64,
+    enum_threshold: u64,
+    struct_threshold: u64,
     avoid_breaking_exported_api: bool,
     allow_private_module_inception: bool,
 }
 
-impl EnumVariantNames {
+impl ItemNameRepetitions {
     #[must_use]
-    pub fn new(threshold: u64, avoid_breaking_exported_api: bool, allow_private_module_inception: bool) -> Self {
+    pub fn new(
+        enum_threshold: u64,
+        struct_threshold: u64,
+        avoid_breaking_exported_api: bool,
+        allow_private_module_inception: bool,
+    ) -> Self {
         Self {
             modules: Vec::new(),
-            threshold,
+            enum_threshold,
+            struct_threshold,
             avoid_breaking_exported_api,
             allow_private_module_inception,
         }
     }
 }
 
-impl_lint_pass!(EnumVariantNames => [
+impl_lint_pass!(ItemNameRepetitions => [
     ENUM_VARIANT_NAMES,
+    STRUCT_FIELD_NAMES,
     MODULE_NAME_REPETITIONS,
     MODULE_INCEPTION
 ]);
 
+#[must_use]
+fn have_no_extra_prefix(prefixes: &[&str]) -> bool {
+    prefixes.iter().all(|p| p == &"" || p == &"_")
+}
+
+fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &[FieldDef<'_>]) {
+    if (fields.len() as u64) < threshold {
+        return;
+    }
+
+    check_struct_name_repetition(cx, item, fields);
+
+    // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them.
+    // this prevents linting in macros in which the location of the field identifier names differ
+    if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) {
+        return;
+    }
+
+    let mut pre: Vec<&str> = match fields.first() {
+        Some(first_field) => first_field.ident.name.as_str().split('_').collect(),
+        None => return,
+    };
+    let mut post = pre.clone();
+    post.reverse();
+    for field in fields {
+        let field_split: Vec<&str> = field.ident.name.as_str().split('_').collect();
+        if field_split.len() == 1 {
+            return;
+        }
+
+        pre = pre
+            .into_iter()
+            .zip(field_split.iter())
+            .take_while(|(a, b)| &a == b)
+            .map(|e| e.0)
+            .collect();
+        post = post
+            .into_iter()
+            .zip(field_split.iter().rev())
+            .take_while(|(a, b)| &a == b)
+            .map(|e| e.0)
+            .collect();
+    }
+    let prefix = pre.join("_");
+    post.reverse();
+    let postfix = match post.last() {
+        Some(&"") => post.join("_") + "_",
+        Some(_) | None => post.join("_"),
+    };
+    if fields.len() > 1 {
+        let (what, value) = match (
+            prefix.is_empty() || prefix.chars().all(|c| c == '_'),
+            postfix.is_empty(),
+        ) {
+            (true, true) => return,
+            (false, _) => ("pre", prefix),
+            (true, false) => ("post", postfix),
+        };
+        span_lint_and_help(
+            cx,
+            STRUCT_FIELD_NAMES,
+            item.span,
+            &format!("all fields have the same {what}fix: `{value}`"),
+            None,
+            &format!("remove the {what}fixes"),
+        );
+    }
+}
+
+fn check_struct_name_repetition(cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
+    let snake_name = to_snake_case(item.ident.name.as_str());
+    let item_name_words: Vec<&str> = snake_name.split('_').collect();
+    for field in fields {
+        if field.ident.span.eq_ctxt(item.ident.span) {
+            //consider linting only if the field identifier has the same SyntaxContext as the item(struct)
+            let field_words: Vec<&str> = field.ident.name.as_str().split('_').collect();
+            if field_words.len() >= item_name_words.len() {
+                // if the field name is shorter than the struct name it cannot contain it
+                if field_words.iter().zip(item_name_words.iter()).all(|(a, b)| a == b) {
+                    span_lint_hir(
+                        cx,
+                        STRUCT_FIELD_NAMES,
+                        field.hir_id,
+                        field.span,
+                        "field name starts with the struct's name",
+                    );
+                }
+                if field_words.len() > item_name_words.len() {
+                    // lint only if the end is not covered by the start
+                    if field_words
+                        .iter()
+                        .rev()
+                        .zip(item_name_words.iter().rev())
+                        .all(|(a, b)| a == b)
+                    {
+                        span_lint_hir(
+                            cx,
+                            STRUCT_FIELD_NAMES,
+                            field.hir_id,
+                            field.span,
+                            "field name ends with the struct's name",
+                        );
+                    }
+                }
+            }
+        }
+    }
+}
+
 fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>) {
     let name = variant.ident.name.as_str();
     let item_name_chars = item_name.chars().count();
@@ -218,35 +371,7 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
     );
 }
 
-#[must_use]
-fn have_no_extra_prefix(prefixes: &[&str]) -> bool {
-    prefixes.iter().all(|p| p == &"" || p == &"_")
-}
-
-#[must_use]
-fn to_camel_case(item_name: &str) -> String {
-    let mut s = String::new();
-    let mut up = true;
-    for c in item_name.chars() {
-        if c.is_uppercase() {
-            // we only turn snake case text into CamelCase
-            return item_name.to_string();
-        }
-        if c == '_' {
-            up = true;
-            continue;
-        }
-        if up {
-            up = false;
-            s.extend(c.to_uppercase());
-        } else {
-            s.push(c);
-        }
-    }
-    s
-}
-
-impl LateLintPass<'_> for EnumVariantNames {
+impl LateLintPass<'_> for ItemNameRepetitions {
     fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
         let last = self.modules.pop();
         assert!(last.is_some());
@@ -303,9 +428,15 @@ impl LateLintPass<'_> for EnumVariantNames {
                 }
             }
         }
-        if let ItemKind::Enum(ref def, _) = item.kind {
-            if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) {
-                check_variant(cx, self.threshold, def, item_name, item.span);
+        if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id))
+            && span_is_local(item.span)
+        {
+            match item.kind {
+                ItemKind::Enum(def, _) => check_variant(cx, self.enum_threshold, &def, item_name, item.span),
+                ItemKind::Struct(VariantData::Struct(fields, _), _) => {
+                    check_fields(cx, self.struct_threshold, item, fields);
+                },
+                _ => (),
             }
         }
         self.modules.push((item.ident.name, item_camel, item.owner_id));
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index 43e1b92c9b9..0ee291a4e9d 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -9,6 +9,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Symbol};
+use std::iter;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -52,12 +53,13 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// This is the opposite of the `iter_without_into_iter` lint.
-    /// It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method.
+    /// It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method
+    /// on the type or on any of the types in its `Deref` chain.
     ///
     /// ### Why is this bad?
     /// It's not bad, but having them is idiomatic and allows the type to be used in iterator chains
-    /// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).iter()` syntax
-    /// in case of ambiguity with another `Intoiterator` impl.
+    /// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).into_iter()` syntax
+    /// in case of ambiguity with another `IntoIterator` impl.
     ///
     /// ### Example
     /// ```rust
@@ -102,7 +104,20 @@ fn is_nameable_in_impl_trait(ty: &rustc_hir::Ty<'_>) -> bool {
     !matches!(ty.kind, TyKind::OpaqueDef(..))
 }
 
-fn type_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
+/// Returns the deref chain of a type, starting with the type itself.
+fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
+    iter::successors(Some(ty), |&ty| {
+        if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
+            && implements_trait(cx, ty, deref_did, &[])
+        {
+            make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
+        } else {
+            None
+        }
+    })
+}
+
+fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
     if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
         cx.tcx.inherent_impls(ty_did).iter().any(|&did| {
             cx.tcx
@@ -127,7 +142,11 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
                 Mutability::Mut => sym::iter_mut,
                 Mutability::Not => sym::iter,
             }
-            && !type_has_inherent_method(cx, ty, expected_method_name)
+            && !deref_chain(cx, ty)
+                .any(|ty| {
+                    // We can't check inherent impls for slices, but we know that they have an `iter(_mut)` method
+                    ty.peel_refs().is_slice() || adt_has_inherent_method(cx, ty, expected_method_name)
+                })
             && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
                 if item.ident.name == sym!(IntoIter) {
                     Some(cx.tcx.hir().impl_item(item.id).expect_type().span)
diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs
index 19f1e08b57a..90096f0f506 100644
--- a/src/tools/clippy/clippy_lints/src/large_futures.rs
+++ b/src/tools/clippy/clippy_lints/src/large_futures.rs
@@ -12,7 +12,7 @@ declare_clippy_lint! {
     /// It checks for the size of a `Future` created by `async fn` or `async {}`.
     ///
     /// ### Why is this bad?
-    /// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Generator`,
+    /// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Coroutine`,
     /// large size of a `Future` may cause stack overflows.
     ///
     /// ### Example
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 0f35ec27665..a70a38ee08b 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -50,9 +50,6 @@ extern crate clippy_utils;
 #[macro_use]
 extern crate declare_clippy_lint;
 
-use std::io;
-use std::path::PathBuf;
-
 use clippy_utils::msrvs::Msrv;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::{Lint, LintId};
@@ -121,7 +118,6 @@ mod empty_structs_with_brackets;
 mod endian_bytes;
 mod entry;
 mod enum_clike;
-mod enum_variants;
 mod equatable_if_let;
 mod error_impl_error;
 mod escape;
@@ -166,6 +162,7 @@ mod inline_fn_without_body;
 mod instant_subtraction;
 mod int_plus_one;
 mod invalid_upcast_comparisons;
+mod item_name_repetitions;
 mod items_after_statements;
 mod items_after_test_module;
 mod iter_not_returning_iterator;
@@ -362,7 +359,6 @@ mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
 use crate::utils::conf::metadata::get_configuration_metadata;
-use crate::utils::conf::TryConf;
 pub use crate::utils::conf::{lookup_conf_file, Conf};
 use crate::utils::FindAll;
 
@@ -374,65 +370,13 @@ use crate::utils::FindAll;
 /// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
 ///
 /// Used in `./src/driver.rs`.
-pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
+pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
-    let msrv = Msrv::read(&conf.msrv, sess);
-    let msrv = move || msrv.clone();
+    let msrv = || conf.msrv.clone();
 
     store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() }));
 }
 
-#[doc(hidden)]
-pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
-    if let Ok((_, warnings)) = path {
-        for warning in warnings {
-            sess.warn(warning.clone());
-        }
-    }
-    let file_name = match path {
-        Ok((Some(path), _)) => path,
-        Ok((None, _)) => return Conf::default(),
-        Err(error) => {
-            sess.err(format!("error finding Clippy's configuration file: {error}"));
-            return Conf::default();
-        },
-    };
-
-    let TryConf { conf, errors, warnings } = utils::conf::read(sess, file_name);
-    // all conf errors are non-fatal, we just use the default conf in case of error
-    for error in errors {
-        if let Some(span) = error.span {
-            sess.span_err(
-                span,
-                format!("error reading Clippy's configuration file: {}", error.message),
-            );
-        } else {
-            sess.err(format!(
-                "error reading Clippy's configuration file `{}`: {}",
-                file_name.display(),
-                error.message
-            ));
-        }
-    }
-
-    for warning in warnings {
-        if let Some(span) = warning.span {
-            sess.span_warn(
-                span,
-                format!("error reading Clippy's configuration file: {}", warning.message),
-            );
-        } else {
-            sess.warn(format!(
-                "error reading Clippy's configuration file `{}`: {}",
-                file_name.display(),
-                warning.message
-            ));
-        }
-    }
-
-    conf
-}
-
 #[derive(Default)]
 struct RegistrationGroups {
     all: Vec<LintId>,
@@ -558,7 +502,7 @@ fn register_categories(store: &mut rustc_lint::LintStore) {
 ///
 /// Used in `./src/driver.rs`.
 #[expect(clippy::too_many_lines)]
-pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
+pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &'static Conf) {
     register_removed_non_tool_lints(store);
     register_categories(store);
 
@@ -660,8 +604,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
     store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
 
-    let msrv = Msrv::read(&conf.msrv, sess);
-    let msrv = move || msrv.clone();
+    let msrv = || conf.msrv.clone();
     let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
     let allow_expect_in_tests = conf.allow_expect_in_tests;
     let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
@@ -762,6 +705,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             too_many_arguments_threshold,
             too_many_lines_threshold,
             large_error_threshold,
+            avoid_breaking_exported_api,
         ))
     });
     let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
@@ -806,7 +750,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             suppress_restriction_lint_in_const,
         ))
     });
-    store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
+    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
+    store.register_late_pass(move |_| Box::new(non_copy_const::NonCopyConst::new(ignore_interior_mutability.clone())));
     store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
     store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
     store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit));
@@ -851,10 +796,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     let enum_variant_name_threshold = conf.enum_variant_name_threshold;
+    let struct_field_name_threshold = conf.struct_field_name_threshold;
     let allow_private_module_inception = conf.allow_private_module_inception;
     store.register_late_pass(move |_| {
-        Box::new(enum_variants::EnumVariantNames::new(
+        Box::new(item_name_repetitions::ItemNameRepetitions::new(
             enum_variant_name_threshold,
+            struct_field_name_threshold,
             avoid_breaking_exported_api,
             allow_private_module_inception,
         ))
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index f7b3b2358a0..5fffb27cda2 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -185,7 +185,7 @@ fn get_vec_push<'tcx>(
             if let StmtKind::Semi(semi_stmt) = &stmt.kind;
             if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
             // Figure out the parameters for the method call
-            if let Some(pushed_item) = args.get(0);
+            if let Some(pushed_item) = args.first();
             // Check that the method being called is push() on a Vec
             if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
             if path.ident.name.as_str() == "push";
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 577bc1d661d..5a87e75722d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -4,7 +4,7 @@ use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
-    AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
+    AsyncCoroutineKind, Block, Body, Closure, CoroutineKind, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, GenericBound,
     ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
@@ -188,7 +188,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
             ..
         } = block_expr;
         let closure_body = cx.tcx.hir().body(body);
-        if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
+        if closure_body.coroutine_kind == Some(CoroutineKind::Async(AsyncCoroutineKind::Block));
         then {
             return Some(closure_body);
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs
index 6c7c57ba1d6..552c57d5e02 100644
--- a/src/tools/clippy/clippy_lints/src/manual_bits.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs
@@ -103,9 +103,9 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
         if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
 
         if let QPath::Resolved(_, count_func_path) = count_func_qpath;
-        if let Some(segment_zero) = count_func_path.segments.get(0);
+        if let Some(segment_zero) = count_func_path.segments.first();
         if let Some(args) = segment_zero.args;
-        if let Some(GenericArg::Type(real_ty)) = args.args.get(0);
+        if let Some(GenericArg::Type(real_ty)) = args.args.first();
 
         if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
         if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id);
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index f264424470d..9da20a28fba 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -15,12 +15,13 @@ use rustc_span::{sym, Span};
 declare_clippy_lint! {
     /// ### What it does
     /// Suggests to use dedicated built-in methods,
-    /// `is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range
+    /// `is_ascii_(lowercase|uppercase|digit|hexdigit)` for checking on corresponding
+    /// ascii range
     ///
     /// ### Why is this bad?
     /// Using the built-in functions is more readable and makes it
     /// clear that it's not a specific subset of characters, but all
-    /// ASCII (lowercase|uppercase|digit) characters.
+    /// ASCII (lowercase|uppercase|digit|hexdigit) characters.
     /// ### Example
     /// ```rust
     /// fn main() {
@@ -28,6 +29,7 @@ declare_clippy_lint! {
     ///     assert!(matches!(b'X', b'A'..=b'Z'));
     ///     assert!(matches!('2', '0'..='9'));
     ///     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    ///     assert!(matches!('C', '0'..='9' | 'a'..='f' | 'A'..='F'));
     ///
     ///     ('0'..='9').contains(&'0');
     ///     ('a'..='z').contains(&'a');
@@ -41,6 +43,7 @@ declare_clippy_lint! {
     ///     assert!(b'X'.is_ascii_uppercase());
     ///     assert!('2'.is_ascii_digit());
     ///     assert!('x'.is_ascii_alphabetic());
+    ///     assert!('C'.is_ascii_hexdigit());
     ///
     ///     '0'.is_ascii_digit();
     ///     'a'.is_ascii_lowercase();
@@ -75,6 +78,12 @@ enum CharRange {
     FullChar,
     /// '0..=9'
     Digit,
+    /// 'a..=f'
+    LowerHexLetter,
+    /// 'A..=F'
+    UpperHexLetter,
+    /// '0..=9' | 'a..=f' | 'A..=F'
+    HexDigit,
     Otherwise,
 }
 
@@ -116,7 +125,8 @@ fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &Cha
         CharRange::LowerChar => Some("is_ascii_lowercase"),
         CharRange::FullChar => Some("is_ascii_alphabetic"),
         CharRange::Digit => Some("is_ascii_digit"),
-        CharRange::Otherwise => None,
+        CharRange::HexDigit => Some("is_ascii_hexdigit"),
+        CharRange::Otherwise | CharRange::LowerHexLetter | CharRange::UpperHexLetter => None,
     } {
         let default_snip = "..";
         let mut app = Applicability::MachineApplicable;
@@ -141,6 +151,12 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
 
             if ranges.len() == 2 && ranges.contains(&CharRange::UpperChar) && ranges.contains(&CharRange::LowerChar) {
                 CharRange::FullChar
+            } else if ranges.len() == 3
+                && ranges.contains(&CharRange::Digit)
+                && ranges.contains(&CharRange::LowerHexLetter)
+                && ranges.contains(&CharRange::UpperHexLetter)
+            {
+                CharRange::HexDigit
             } else {
                 CharRange::Otherwise
             }
@@ -156,6 +172,8 @@ fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
         match (&start_lit.node, &end_lit.node) {
             (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
             (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
+            (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
+            (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
             (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
             _ => CharRange::Otherwise,
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index a23000e5fe1..b5ab94b3a2f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -967,7 +967,6 @@ declare_clippy_lint! {
     "checks for unnecessary guards in match expressions"
 }
 
-#[derive(Default)]
 pub struct Matches {
     msrv: Msrv,
     infallible_destructuring_match_linted: bool,
@@ -978,7 +977,7 @@ impl Matches {
     pub fn new(msrv: Msrv) -> Self {
         Self {
             msrv,
-            ..Matches::default()
+            infallible_destructuring_match_linted: false,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
index 3337b250c0e..20878f1e4df 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_expr_identity_function, is_trait_method};
+use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -9,7 +9,7 @@ use rustc_span::sym;
 use super::FILTER_MAP_IDENTITY;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) {
-    if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, filter_map_arg) {
+    if is_trait_method(cx, expr, sym::Iterator) && is_expr_untyped_identity_function(cx, filter_map_arg) {
         span_lint_and_sugg(
             cx,
             FILTER_MAP_IDENTITY,
diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
index 84a21de0ac8..8849a4f4942 100644
--- a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_expr_identity_function, is_trait_method};
+use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -15,7 +15,7 @@ pub(super) fn check<'tcx>(
     flat_map_arg: &'tcx hir::Expr<'_>,
     flat_map_span: Span,
 ) {
-    if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, flat_map_arg) {
+    if is_trait_method(cx, expr, sym::Iterator) && is_expr_untyped_identity_function(cx, flat_map_arg) {
         span_lint_and_sugg(
             cx,
             FLAT_MAP_IDENTITY,
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
index ee063adac64..e7b4564c651 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_slice_of_primitives;
 use clippy_utils::source::snippet_with_applicability;
 use if_chain::if_chain;
 use rustc_ast::LitKind;
@@ -20,7 +19,6 @@ pub(super) fn check<'tcx>(
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
         if cx.tcx.type_of(impl_id).instantiate_identity().is_slice();
-        if let Some(_) = is_slice_of_primitives(cx, recv);
         if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
         then {
             let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 674d3451748..b44a2716dde 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if !expr.span.from_expansion();
         if let ExprKind::Closure(c) = m_arg.kind;
-        if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
+        if let Body {params: [p], value: body_expr, coroutine_kind: _ } = cx.tcx.hir().body(c.body);
         if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
 
         let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
index 7be1ce483f6..57581363cfa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_expr_identity_function, is_trait_method};
+use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -23,7 +23,7 @@ pub(super) fn check(
         if is_trait_method(cx, expr, sym::Iterator)
             || is_type_diagnostic_item(cx, caller_ty, sym::Result)
             || is_type_diagnostic_item(cx, caller_ty, sym::Option);
-        if is_expr_identity_function(cx, map_arg);
+        if is_expr_untyped_identity_function(cx, map_arg);
         if let Some(sugg_span) = expr.span.trim_start(caller.span);
         then {
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index afdb8ce94ac..04ddaaa2f46 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -39,7 +39,7 @@ pub(super) fn check<'tcx>(
                 if search_method == "find";
                 if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind;
                 let closure_body = cx.tcx.hir().body(body);
-                if let Some(closure_arg) = closure_body.params.get(0);
+                if let Some(closure_arg) = closure_body.params.first();
                 then {
                     if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
                         Some(search_snippet.replacen('&', "", 1))
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 47e2e744112..4a651396f14 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{eager_or_lazy, is_from_proc_macro, usage};
+use hir::FnRetTy;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -27,7 +28,7 @@ pub(super) fn check<'tcx>(
     let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
 
     if is_option || is_result || is_bool {
-        if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind {
+        if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind {
             let body = cx.tcx.hir().body(body);
             let body_expr = &body.value;
 
@@ -48,7 +49,14 @@ pub(super) fn check<'tcx>(
                     .iter()
                     // bindings are checked to be unused above
                     .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
-                {
+                    && matches!(
+                        fn_decl.output,
+                        FnRetTy::DefaultReturn(_)
+                            | FnRetTy::Return(hir::Ty {
+                                kind: hir::TyKind::Infer,
+                                ..
+                            })
+                    ) {
                     Applicability::MachineApplicable
                 } else {
                     // replacing the lambda may break type inference
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index f2773cad400..0629dee4f72 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -67,7 +67,7 @@ impl MissingDoc {
         if_chain! {
             if let Some(meta) = meta;
             if let MetaItemKind::List(list) = meta.kind;
-            if let Some(meta) = list.get(0);
+            if let Some(meta) = list.first();
             if let Some(name) = meta.ident();
             then {
                 name.name == sym::include
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index 96d83e114a4..fc088710e42 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -17,6 +17,9 @@ declare_clippy_lint! {
     /// Checks for imports that do not rename the item as specified
     /// in the `enforce-import-renames` config option.
     ///
+    /// Note: Even though this lint is warn-by-default, it will only trigger if
+    /// import renames are defined in the clippy.toml file.
+    ///
     /// ### Why is this bad?
     /// Consistency is important, if a project has defined import
     /// renames they should be followed. More practically, some item names are too
@@ -38,7 +41,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.55.0"]
     pub MISSING_ENFORCED_IMPORT_RENAMES,
-    restriction,
+    style,
     "enforce import renames"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index f0b865be804..d205237a591 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -1,9 +1,9 @@
 use std::ops::ControlFlow;
 
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_path_lang_item;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::{for_each_expr, Visitable};
-use clippy_utils::is_path_lang_item;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index fe35126aab2..2c42a7a3676 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -9,7 +9,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -64,7 +64,10 @@ declare_lint_pass!(MultipleUnsafeOpsPerBlock => [MULTIPLE_UNSAFE_OPS_PER_BLOCK])
 
 impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
-        if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) || in_external_macro(cx.tcx.sess, block.span) {
+        if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_))
+            || in_external_macro(cx.tcx.sess, block.span)
+            || block.span.is_desugaring(DesugaringKind::Await)
+        {
             return;
         }
         let mut unsafe_ops = vec![];
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 38a75034cd3..377cbef7b99 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -189,7 +189,7 @@ fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>)
 }
 
 fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
-    block.stmts.get(0).map_or(false, |stmt| match stmt.kind {
+    block.stmts.first().map_or(false, |stmt| match stmt.kind {
         ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
             if let ast::ExprKind::Continue(ref l) = e.kind {
                 compare_labels(label, l.as_ref())
@@ -434,7 +434,7 @@ fn erode_from_back(s: &str) -> String {
 }
 
 fn span_of_first_expr_in_block(block: &ast::Block) -> Option<Span> {
-    block.stmts.get(0).map(|stmt| stmt.span)
+    block.stmts.first().map(|stmt| stmt.span)
 }
 
 #[cfg(test)]
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 212d6234bdb..1d5874f6fea 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -7,7 +7,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
 use rustc_hir::{
-    Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath,
+    BlockCheckMode, Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node,
+    PatKind, QPath,
 };
 use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -139,13 +140,23 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
         let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
         let is_async = match kind {
             FnKind::ItemFn(.., header) => {
+                if header.is_unsafe() {
+                    // We don't check unsafe functions.
+                    return;
+                }
                 let attrs = cx.tcx.hir().attrs(hir_id);
                 if header.abi != Abi::Rust || requires_exact_signature(attrs) {
                     return;
                 }
                 header.is_async()
             },
-            FnKind::Method(.., sig) => sig.header.is_async(),
+            FnKind::Method(.., sig) => {
+                if sig.header.is_unsafe() {
+                    // We don't check unsafe functions.
+                    return;
+                }
+                sig.header.is_async()
+            },
             FnKind::Closure => return,
         };
 
@@ -186,20 +197,21 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
             };
             let infcx = cx.tcx.infer_ctxt().build();
             euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
-            if is_async {
-                let mut checked_closures = FxHashSet::default();
-
-                // We retrieve all the closures declared in the async function because they will
-                // not be found by `euv::Delegate`.
-                let mut closures: FxHashSet<LocalDefId> = FxHashSet::default();
-                for_each_expr_with_closures(cx, body, |expr| {
-                    if let ExprKind::Closure(closure) = expr.kind {
-                        closures.insert(closure.def_id);
-                    }
-                    ControlFlow::<()>::Continue(())
-                });
-                check_closures(&mut ctx, cx, &infcx, &mut checked_closures, closures);
 
+            let mut checked_closures = FxHashSet::default();
+
+            // We retrieve all the closures declared in the function because they will not be found
+            // by `euv::Delegate`.
+            let mut closures: FxHashSet<LocalDefId> = FxHashSet::default();
+            for_each_expr_with_closures(cx, body, |expr| {
+                if let ExprKind::Closure(closure) = expr.kind {
+                    closures.insert(closure.def_id);
+                }
+                ControlFlow::<()>::Continue(())
+            });
+            check_closures(&mut ctx, cx, &infcx, &mut checked_closures, closures);
+
+            if is_async {
                 while !ctx.async_closures.is_empty() {
                     let async_closures = ctx.async_closures.clone();
                     ctx.async_closures.clear();
@@ -304,10 +316,27 @@ impl<'tcx> MutablyUsedVariablesCtxt<'tcx> {
         }
         self.aliases.insert(alias, target);
     }
+
+    // The goal here is to find if the current scope is unsafe or not. It stops when it finds
+    // a function or an unsafe block.
+    fn is_in_unsafe_block(&self, item: HirId) -> bool {
+        let hir = self.tcx.hir();
+        for (parent, node) in hir.parent_iter(item) {
+            if let Some(fn_sig) = hir.fn_sig_by_hir_id(parent) {
+                return fn_sig.header.is_unsafe();
+            } else if let Node::Block(block) = node {
+                if matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) {
+                    return true;
+                }
+            }
+        }
+        false
+    }
 }
 
 impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
-    fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) {
+    #[allow(clippy::if_same_then_else)]
+    fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) {
         if let euv::Place {
             base:
                 euv::PlaceBase::Local(vid)
@@ -327,13 +356,18 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 && matches!(base_ty.ref_mutability(), Some(Mutability::Mut))
             {
                 self.add_mutably_used_var(*vid);
+            } else if self.is_in_unsafe_block(id) {
+                // If we are in an unsafe block, any operation on this variable must not be warned
+                // upon!
+                self.add_mutably_used_var(*vid);
             }
             self.prev_bind = None;
             self.prev_move_to_closure.remove(vid);
         }
     }
 
-    fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId, borrow: ty::BorrowKind) {
+    #[allow(clippy::if_same_then_else)]
+    fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) {
         self.prev_bind = None;
         if let euv::Place {
             base:
@@ -355,6 +389,10 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 || (borrow == ty::BorrowKind::UniqueImmBorrow && base_ty.ref_mutability() == Some(Mutability::Mut))
             {
                 self.add_mutably_used_var(*vid);
+            } else if self.is_in_unsafe_block(id) {
+                // If we are in an unsafe block, any operation on this variable must not be warned
+                // upon!
+                self.add_mutably_used_var(*vid);
             }
         } else if borrow == ty::ImmBorrow {
             // If there is an `async block`, it'll contain a call to a closure which we need to
@@ -397,7 +435,21 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
         }
     }
 
-    fn copy(&mut self, _cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) {
+    fn copy(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) {
+        if let euv::Place {
+            base:
+                euv::PlaceBase::Local(vid)
+                | euv::PlaceBase::Upvar(UpvarId {
+                    var_path: UpvarPath { hir_id: vid },
+                    ..
+                }),
+            ..
+        } = &cmt.place
+        {
+            if self.is_in_unsafe_block(id) {
+                self.add_mutably_used_var(*vid);
+            }
+        }
         self.prev_bind = None;
     }
 
@@ -427,8 +479,22 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
         }
     }
 
-    fn bind(&mut self, _cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) {
+    fn bind(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) {
         self.prev_bind = Some(id);
+        if let euv::Place {
+            base:
+                euv::PlaceBase::Local(vid)
+                | euv::PlaceBase::Upvar(UpvarId {
+                    var_path: UpvarPath { hir_id: vid },
+                    ..
+                }),
+            ..
+        } = &cmt.place
+        {
+            if self.is_in_unsafe_block(id) {
+                self.add_mutably_used_var(*vid);
+            }
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 6d7df2eac62..f3c0d616473 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::is_self;
 use clippy_utils::ptr::get_spans;
 use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
 };
-use clippy_utils::is_self;
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_errors::{Applicability, Diagnostic};
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index 0e834fb3ac7..ed279a3813d 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
+use rustc_hir::{AsyncCoroutineKind, Block, Body, CoroutineKind, Expr, ExprKind, LangItem, MatchSource, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -87,7 +87,7 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
     }
 
     fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
-        if let Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) = body.generator_kind {
+        if let Some(CoroutineKind::Async(AsyncCoroutineKind::Fn)) = body.coroutine_kind {
             if let ExprKind::Block(
                 Block {
                     expr:
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 2b4e3260c56..613afa46a91 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -5,9 +5,10 @@
 use std::ptr;
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::in_constant;
 use clippy_utils::macros::macro_backtrace;
+use clippy_utils::{def_path_def_ids, in_constant};
 use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
@@ -15,9 +16,10 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass, Lint};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
+use rustc_middle::query::Key;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, InnerSpan, Span};
 use rustc_target::abi::VariantIdx;
 
@@ -126,128 +128,6 @@ declare_clippy_lint! {
     "referencing `const` with interior mutability"
 }
 
-fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`,
-    // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is
-    // 'unfrozen'. However, this code causes a false negative in which
-    // a type contains a layout-unknown type, but also an unsafe cell like `const CELL: Cell<T>`.
-    // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)`
-    // since it works when a pointer indirection involves (`Cell<*const T>`).
-    // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
-    // but I'm not sure whether it's a decent way, if possible.
-    cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env)
-}
-
-fn is_value_unfrozen_raw<'tcx>(
-    cx: &LateContext<'tcx>,
-    result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
-    ty: Ty<'tcx>,
-) -> bool {
-    fn inner<'tcx>(cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool {
-        match *ty.kind() {
-            // the fact that we have to dig into every structs to search enums
-            // leads us to the point checking `UnsafeCell` directly is the only option.
-            ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
-            // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
-            // contained value.
-            ty::Adt(def, ..) if def.is_union() => false,
-            ty::Array(ty, _) => val.unwrap_branch().iter().any(|field| inner(cx, *field, ty)),
-            ty::Adt(def, _) if def.is_union() => false,
-            ty::Adt(def, args) if def.is_enum() => {
-                let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap();
-                let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
-                fields
-                    .iter()
-                    .copied()
-                    .zip(
-                        def.variants()[variant_index]
-                            .fields
-                            .iter()
-                            .map(|field| field.ty(cx.tcx, args)),
-                    )
-                    .any(|(field, ty)| inner(cx, field, ty))
-            },
-            ty::Adt(def, args) => val
-                .unwrap_branch()
-                .iter()
-                .zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, args)))
-                .any(|(field, ty)| inner(cx, *field, ty)),
-            ty::Tuple(tys) => val
-                .unwrap_branch()
-                .iter()
-                .zip(tys)
-                .any(|(field, ty)| inner(cx, *field, ty)),
-            _ => false,
-        }
-    }
-    result.map_or_else(
-        |err| {
-            // Consider `TooGeneric` cases as being unfrozen.
-            // This causes a false positive where an assoc const whose type is unfrozen
-            // have a value that is a frozen variant with a generic param (an example is
-            // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::GENERIC_VARIANT`).
-            // However, it prevents a number of false negatives that is, I think, important:
-            // 1. assoc consts in trait defs referring to consts of themselves (an example is
-            //    `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`).
-            // 2. a path expr referring to assoc consts whose type is doesn't have any frozen variants in trait
-            //    defs (i.e. without substitute for `Self`). (e.g. borrowing
-            //    `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`)
-            // 3. similar to the false positive above; but the value is an unfrozen variant, or the type has no
-            //    enums. (An example is
-            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT` and
-            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`).
-            // One might be able to prevent these FNs correctly, and replace this with `false`;
-            // e.g. implementing `has_frozen_variant` described above, and not running this function
-            // when the type doesn't have any frozen variants would be the 'correct' way for the 2nd
-            // case (that actually removes another suboptimal behavior (I won't say 'false positive') where,
-            // similar to 2., but with the a frozen variant) (e.g. borrowing
-            // `borrow_interior_mutable_const::enums::AssocConsts::TO_BE_FROZEN_VARIANT`).
-            // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
-            matches!(err, ErrorHandled::TooGeneric(..))
-        },
-        |val| val.map_or(true, |val| inner(cx, val, ty)),
-    )
-}
-
-fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
-    let def_id = body_id.hir_id.owner.to_def_id();
-    let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id);
-    let instance = ty::Instance::new(def_id, args);
-    let cid = rustc_middle::mir::interpret::GlobalId {
-        instance,
-        promoted: None,
-    };
-    let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
-    let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, None);
-    is_value_unfrozen_raw(cx, result, ty)
-}
-
-fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
-    let args = cx.typeck_results().node_args(hir_id);
-
-    let result = const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), None);
-    is_value_unfrozen_raw(cx, result, ty)
-}
-
-pub fn const_eval_resolve<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ct: ty::UnevaluatedConst<'tcx>,
-    span: Option<Span>,
-) -> EvalToValTreeResult<'tcx> {
-    match ty::Instance::resolve(tcx, param_env, ct.def, ct.args) {
-        Ok(Some(instance)) => {
-            let cid = GlobalId {
-                instance,
-                promoted: None,
-            };
-            tcx.const_eval_global_id_for_typeck(param_env, cid, span)
-        },
-        Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP))),
-        Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(rustc_span::DUMMY_SP))),
-    }
-}
-
 #[derive(Copy, Clone)]
 enum Source {
     Item { item: Span },
@@ -292,13 +172,178 @@ fn lint(cx: &LateContext<'_>, source: Source) {
     });
 }
 
-declare_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]);
+#[derive(Clone)]
+pub struct NonCopyConst {
+    ignore_interior_mutability: Vec<String>,
+    ignore_mut_def_ids: FxHashSet<DefId>,
+}
+
+impl_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]);
+
+impl NonCopyConst {
+    pub fn new(ignore_interior_mutability: Vec<String>) -> Self {
+        Self {
+            ignore_interior_mutability,
+            ignore_mut_def_ids: FxHashSet::default(),
+        }
+    }
+
+    fn is_ty_ignored(&self, ty: Ty<'_>) -> bool {
+        matches!(ty.ty_adt_id(), Some(adt_id) if self.ignore_mut_def_ids.contains(&adt_id))
+    }
+
+    fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+        // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`,
+        // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is
+        // 'unfrozen'. However, this code causes a false negative in which
+        // a type contains a layout-unknown type, but also an unsafe cell like `const CELL: Cell<T>`.
+        // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)`
+        // since it works when a pointer indirection involves (`Cell<*const T>`).
+        // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
+        // but I'm not sure whether it's a decent way, if possible.
+        cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env)
+    }
+
+    fn is_value_unfrozen_raw_inner<'tcx>(&self, cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool {
+        if self.is_ty_ignored(ty) {
+            return false;
+        }
+        match *ty.kind() {
+            // the fact that we have to dig into every structs to search enums
+            // leads us to the point checking `UnsafeCell` directly is the only option.
+            ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
+            // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
+            // contained value.
+            ty::Adt(def, ..) if def.is_union() => false,
+            ty::Array(ty, _) => val
+                .unwrap_branch()
+                .iter()
+                .any(|field| self.is_value_unfrozen_raw_inner(cx, *field, ty)),
+            ty::Adt(def, _) if def.is_union() => false,
+            ty::Adt(def, args) if def.is_enum() => {
+                let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap();
+                let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
+                fields
+                    .iter()
+                    .copied()
+                    .zip(
+                        def.variants()[variant_index]
+                            .fields
+                            .iter()
+                            .map(|field| field.ty(cx.tcx, args)),
+                    )
+                    .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, field, ty))
+            },
+            ty::Adt(def, args) => val
+                .unwrap_branch()
+                .iter()
+                .zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, args)))
+                .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, *field, ty)),
+            ty::Tuple(tys) => val
+                .unwrap_branch()
+                .iter()
+                .zip(tys)
+                .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, *field, ty)),
+            _ => false,
+        }
+    }
+
+    fn is_value_unfrozen_raw<'tcx>(
+        &self,
+        cx: &LateContext<'tcx>,
+        result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
+        ty: Ty<'tcx>,
+    ) -> bool {
+        result.map_or_else(
+            |err| {
+                // Consider `TooGeneric` cases as being unfrozen.
+                // This causes a false positive where an assoc const whose type is unfrozen
+                // have a value that is a frozen variant with a generic param (an example is
+                // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::GENERIC_VARIANT`).
+                // However, it prevents a number of false negatives that is, I think, important:
+                // 1. assoc consts in trait defs referring to consts of themselves (an example is
+                //    `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`).
+                // 2. a path expr referring to assoc consts whose type is doesn't have any frozen variants in trait
+                //    defs (i.e. without substitute for `Self`). (e.g. borrowing
+                //    `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`)
+                // 3. similar to the false positive above; but the value is an unfrozen variant, or the type has no
+                //    enums. (An example is
+                //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT` and
+                //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`).
+                // One might be able to prevent these FNs correctly, and replace this with `false`;
+                // e.g. implementing `has_frozen_variant` described above, and not running this function
+                // when the type doesn't have any frozen variants would be the 'correct' way for the 2nd
+                // case (that actually removes another suboptimal behavior (I won't say 'false positive') where,
+                // similar to 2., but with the a frozen variant) (e.g. borrowing
+                // `borrow_interior_mutable_const::enums::AssocConsts::TO_BE_FROZEN_VARIANT`).
+                // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
+                matches!(err, ErrorHandled::TooGeneric(..))
+            },
+            |val| val.map_or(true, |val| self.is_value_unfrozen_raw_inner(cx, val, ty)),
+        )
+    }
+
+    fn is_value_unfrozen_poly<'tcx>(&self, cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
+        let def_id = body_id.hir_id.owner.to_def_id();
+        let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id);
+        let instance = ty::Instance::new(def_id, args);
+        let cid = rustc_middle::mir::interpret::GlobalId {
+            instance,
+            promoted: None,
+        };
+        let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
+        let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, None);
+        self.is_value_unfrozen_raw(cx, result, ty)
+    }
+
+    fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
+        let args = cx.typeck_results().node_args(hir_id);
+
+        let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), None);
+        self.is_value_unfrozen_raw(cx, result, ty)
+    }
+
+    pub fn const_eval_resolve<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        ct: ty::UnevaluatedConst<'tcx>,
+        span: Option<Span>,
+    ) -> EvalToValTreeResult<'tcx> {
+        match ty::Instance::resolve(tcx, param_env, ct.def, ct.args) {
+            Ok(Some(instance)) => {
+                let cid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                tcx.const_eval_global_id_for_typeck(param_env, cid, span)
+            },
+            Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP))),
+            Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(rustc_span::DUMMY_SP))),
+        }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
+    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
+        self.ignore_mut_def_ids.clear();
+        let mut path = Vec::new();
+        for ty in &self.ignore_interior_mutability {
+            path.extend(ty.split("::"));
+            for id in def_path_def_ids(cx, &path[..]) {
+                self.ignore_mut_def_ids.insert(id);
+            }
+            path.clear();
+        }
+    }
+
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) {
         if let ItemKind::Const(.., body_id) = it.kind {
             let ty = cx.tcx.type_of(it.owner_id).instantiate_identity();
-            if !ignored_macro(cx, it) && is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, body_id, ty) {
+            if !ignored_macro(cx, it)
+                && !self.is_ty_ignored(ty)
+                && Self::is_unfrozen(cx, ty)
+                && self.is_value_unfrozen_poly(cx, body_id, ty)
+            {
                 lint(cx, Source::Item { item: it.span });
             }
         }
@@ -311,7 +356,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
             // Normalize assoc types because ones originated from generic params
             // bounded other traits could have their bound.
             let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-            if is_unfrozen(cx, normalized)
+            if !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized)
                 // When there's no default value, lint it only according to its type;
                 // in other words, lint consts whose value *could* be unfrozen, not definitely is.
                 // This feels inconsistent with how the lint treats generic types,
@@ -324,7 +369,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                 // i.e. having an enum doesn't necessary mean a type has a frozen variant.
                 // And, implementing it isn't a trivial task; it'll probably end up
                 // re-implementing the trait predicate evaluation specific to `Freeze`.
-                && body_id_opt.map_or(true, |body_id| is_value_unfrozen_poly(cx, body_id, normalized))
+                && body_id_opt.map_or(true, |body_id| self.is_value_unfrozen_poly(cx, body_id, normalized))
             {
                 lint(cx, Source::Assoc { item: trait_item.span });
             }
@@ -367,8 +412,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                             // e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
                         let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity();
                         let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-                        if is_unfrozen(cx, normalized);
-                        if is_value_unfrozen_poly(cx, *body_id, normalized);
+                        if !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized);
+                        if self.is_value_unfrozen_poly(cx, *body_id, normalized);
                         then {
                             lint(
                                cx,
@@ -384,7 +429,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                     // Normalize assoc types originated from generic params.
                     let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
 
-                    if is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, *body_id, normalized) {
+                    if !self.is_ty_ignored(ty)
+                        && Self::is_unfrozen(cx, ty)
+                        && self.is_value_unfrozen_poly(cx, *body_id, normalized)
+                    {
                         lint(cx, Source::Assoc { item: impl_item.span });
                     }
                 },
@@ -478,7 +526,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                 cx.typeck_results().expr_ty(dereferenced_expr)
             };
 
-            if is_unfrozen(cx, ty) && is_value_unfrozen_expr(cx, expr.hir_id, item_def_id, ty) {
+            if !self.is_ty_ignored(ty)
+                && Self::is_unfrozen(cx, ty)
+                && self.is_value_unfrozen_expr(cx, expr.hir_id, item_def_id, ty)
+            {
                 lint(cx, Source::Expr { expr: expr.span });
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index d388dfc08f3..62ef48c8a90 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_lint_allowed;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::is_lint_allowed;
 use rustc_ast::ImplPolarity;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{FieldDef, Item, ItemKind, Node};
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 3dc652f9dc0..f0f8d510c7e 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -134,6 +134,7 @@ impl Usage {
 /// The parameters being checked by the lint, indexed by both the parameter's `HirId` and the
 /// `DefId` of the function paired with the parameter's index.
 #[derive(Default)]
+#[allow(clippy::struct_field_names)]
 struct Params {
     params: Vec<Param>,
     by_id: HirIdMap<usize>,
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 136642d69dc..ea8ed28ba62 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::path_def_id;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::path_def_id;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
index 1a127c2bcf6..bd0ca66b761 100644
--- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
+use clippy_utils::last_path_segment;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::{indent_of, snippet};
-use clippy_utils::last_path_segment;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
index 8193057a6eb..2e895d5f236 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -5,7 +5,7 @@ use clippy_utils::peel_blocks;
 use clippy_utils::source::{snippet, walk_span_to_context};
 use clippy_utils::visitors::for_each_expr;
 use rustc_errors::Applicability;
-use rustc_hir::{AsyncGeneratorKind, Closure, Expr, ExprKind, GeneratorKind, MatchSource};
+use rustc_hir::{AsyncCoroutineKind, Closure, CoroutineKind, Expr, ExprKind, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::UpvarCapture;
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
 fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind &&
         let body = cx.tcx.hir().body(*body) &&
-        matches!(body.generator_kind, Some(GeneratorKind::Async(AsyncGeneratorKind::Block)))
+        matches!(body.coroutine_kind, Some(CoroutineKind::Async(AsyncCoroutineKind::Block)))
     {
         cx
             .typeck_results()
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index f42836611ca..c18237e887d 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
             // without this check, we'd end up linting twice.
             && !matches!(recv.kind, hir::ExprKind::Call(..))
             && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
-            && let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth)
+            && let Some((body, fn_decl, coroutine_kind)) = find_innermost_closure(cx, recv, call_depth)
         {
             span_lint_and_then(
                 cx,
@@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                         let mut applicability = Applicability::MachineApplicable;
                         let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability);
 
-                        if generator_kind.is_async()
+                        if coroutine_kind.is_async()
                             && let hir::ExprKind::Closure(closure) = body.kind
                         {
                             let async_closure_body = cx.tcx.hir().body(closure.body);
diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
index 197742b5dd4..a1a0e8f3520 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
             if let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id);
             if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id);
             // the previous binding has the same mutability
-            if find_binding(binding_pat, ident).unwrap().1 == mutability;
+            if find_binding(binding_pat, ident).is_some_and(|bind| bind.1 == mutability);
             // the local does not change the effect of assignments to the binding. see #11290
             if !affects_assignments(cx, mutability, binding_id, local.hir_id);
             // the local does not affect the code's drop behavior
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index 9db18c2976c..2278e41be37 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -335,7 +335,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
 
     fn visit_block(&mut self, block: &'tcx Block<'_>) {
         if self.initialization_found {
-            if let Some(s) = block.stmts.get(0) {
+            if let Some(s) = block.stmts.first() {
                 self.visit_stmt(s);
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
index 3685432a253..4bfbe3bf37e 100644
--- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_context;
 use clippy_utils::path_def_id;
+use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 71a4b3fba1b..788678a63b7 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -578,7 +578,7 @@ impl Types {
     }
 }
 
-#[allow(clippy::struct_excessive_bools)]
+#[allow(clippy::struct_excessive_bools, clippy::struct_field_names)]
 #[derive(Clone, Copy, Default)]
 struct CheckTyContext {
     is_in_trait_impl: bool,
diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
index 6756df8e716..72569e10f05 100644
--- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
@@ -201,7 +201,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
     let expr = peel_hir_expr_while(expr, |e| {
         if let ExprKind::Block(block, _) = e.kind {
             // Extract the first statement/expression
-            match (block.stmts.get(0).map(|stmt| &stmt.kind), block.expr) {
+            match (block.stmts.first().map(|stmt| &stmt.kind), block.expr) {
                 (None, Some(expr)) => Some(expr),
                 (Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), _) => Some(expr),
                 _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs
index 5aa057580e9..894de0d85c1 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs
@@ -40,7 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
             let (constructor_path, constructor_item) =
                 if let hir::ExprKind::Call(constructor, constructor_args) = recv.kind
                     && let hir::ExprKind::Path(constructor_path) = constructor.kind
-                    && let Some(arg) = constructor_args.get(0)
+                    && let Some(arg) = constructor_args.first()
                 {
                     if constructor.span.from_expansion() || arg.span.from_expansion() {
                         return;
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
                 _ => return,
             }
 
-            if let Some(map_arg) = args.get(0)
+            if let Some(map_arg) = args.first()
                 && let hir::ExprKind::Path(fun) = map_arg.kind
             {
                 if map_arg.span.from_expansion() {
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index bc7c3897a6e..3649f8792ae 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
     }
 
     fn visit_body(&mut self, b: &'tcx Body<'tcx>) {
-        let is_async_block = matches!(b.generator_kind, Some(rustc_hir::GeneratorKind::Async(_)));
+        let is_async_block = matches!(b.coroutine_kind, Some(rustc_hir::CoroutineKind::Async(_)));
 
         if is_async_block {
             self.async_depth += 1;
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 50231d930d0..f10ed4b3d41 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -54,7 +54,6 @@ declare_clippy_lint! {
     "unnecessary structure name repetition whereas `Self` is applicable"
 }
 
-#[derive(Default)]
 pub struct UseSelf {
     msrv: Msrv,
     stack: Vec<StackItem>,
@@ -65,7 +64,7 @@ impl UseSelf {
     pub fn new(msrv: Msrv) -> Self {
         Self {
             msrv,
-            ..Self::default()
+            stack: Vec::new(),
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index f02c33cc674..aecb0c6dbfa 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -268,8 +268,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
     fn qpath(&self, qpath: &Binding<&QPath<'_>>) {
         if let QPath::LangItem(lang_item, ..) = *qpath.value {
             chain!(self, "matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _))");
-        } else {
-            chain!(self, "match_qpath({qpath}, &[{}])", path_to_string(qpath.value));
+        } else if let Ok(path) = path_to_string(qpath.value) {
+            chain!(self, "match_qpath({qpath}, &[{}])", path);
         }
     }
 
@@ -738,8 +738,8 @@ fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
     get_attr(cx.sess(), attrs, "author").count() > 0
 }
 
-fn path_to_string(path: &QPath<'_>) -> String {
-    fn inner(s: &mut String, path: &QPath<'_>) {
+fn path_to_string(path: &QPath<'_>) -> Result<String, ()> {
+    fn inner(s: &mut String, path: &QPath<'_>) -> Result<(), ()> {
         match *path {
             QPath::Resolved(_, path) => {
                 for (i, segment) in path.segments.iter().enumerate() {
@@ -751,16 +751,18 @@ fn path_to_string(path: &QPath<'_>) -> String {
             },
             QPath::TypeRelative(ty, segment) => match &ty.kind {
                 hir::TyKind::Path(inner_path) => {
-                    inner(s, inner_path);
+                    inner(s, inner_path)?;
                     *s += ", ";
                     write!(s, "{:?}", segment.ident.as_str()).unwrap();
                 },
                 other => write!(s, "/* unimplemented: {other:?}*/").unwrap(),
             },
-            QPath::LangItem(..) => panic!("path_to_string: called for lang item qpath"),
+            QPath::LangItem(..) => return Err(()),
         }
+
+        Ok(())
     }
     let mut s = String::new();
-    inner(&mut s, path);
-    s
+    inner(&mut s, path)?;
+    Ok(s)
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 23da1de7730..8829f188fe7 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -8,8 +8,9 @@ use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor};
 use serde::Deserialize;
 use std::fmt::{Debug, Display, Formatter};
 use std::ops::Range;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::str::FromStr;
+use std::sync::OnceLock;
 use std::{cmp, env, fmt, fs, io};
 
 #[rustfmt::skip]
@@ -78,62 +79,35 @@ pub struct TryConf {
 
 impl TryConf {
     fn from_toml_error(file: &SourceFile, error: &toml::de::Error) -> Self {
-        ConfError::from_toml(file, error).into()
-    }
-}
-
-impl From<ConfError> for TryConf {
-    fn from(value: ConfError) -> Self {
         Self {
             conf: Conf::default(),
-            errors: vec![value],
+            errors: vec![ConfError::from_toml(file, error)],
             warnings: vec![],
         }
     }
 }
 
-impl From<io::Error> for TryConf {
-    fn from(value: io::Error) -> Self {
-        ConfError::from(value).into()
-    }
-}
-
 #[derive(Debug)]
 pub struct ConfError {
     pub message: String,
-    pub span: Option<Span>,
+    pub span: Span,
 }
 
 impl ConfError {
     fn from_toml(file: &SourceFile, error: &toml::de::Error) -> Self {
-        if let Some(span) = error.span() {
-            Self::spanned(file, error.message(), span)
-        } else {
-            Self {
-                message: error.message().to_string(),
-                span: None,
-            }
-        }
+        let span = error.span().unwrap_or(0..file.source_len.0 as usize);
+        Self::spanned(file, error.message(), span)
     }
 
     fn spanned(file: &SourceFile, message: impl Into<String>, span: Range<usize>) -> Self {
         Self {
             message: message.into(),
-            span: Some(Span::new(
+            span: Span::new(
                 file.start_pos + BytePos::from_usize(span.start),
                 file.start_pos + BytePos::from_usize(span.end),
                 SyntaxContext::root(),
                 None,
-            )),
-        }
-    }
-}
-
-impl From<io::Error> for ConfError {
-    fn from(value: io::Error) -> Self {
-        Self {
-            message: value.to_string(),
-            span: None,
+            ),
         }
     }
 }
@@ -297,7 +271,7 @@ define_Conf! {
     /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
     ///
     /// The minimum rust version that the project supports
-    (msrv: Option<String> = None),
+    (msrv: crate::Msrv = crate::Msrv::empty()),
     /// DEPRECATED LINT: BLACKLISTED_NAME.
     ///
     /// Use the Disallowed Names lint instead
@@ -360,6 +334,10 @@ define_Conf! {
     ///
     /// The minimum number of enum variants for the lints about variant names to trigger
     (enum_variant_name_threshold: u64 = 3),
+    /// Lint: STRUCT_VARIANT_NAMES.
+    ///
+    /// The minimum number of struct fields for the lints about field names to trigger
+    (struct_field_name_threshold: u64 = 3),
     /// Lint: LARGE_ENUM_VARIANT.
     ///
     /// The maximum size of an enum's variant to avoid box suggestion
@@ -641,15 +619,8 @@ pub fn lookup_conf_file() -> io::Result<(Option<PathBuf>, Vec<String>)> {
     }
 }
 
-/// Read the `toml` configuration file.
-///
-/// In case of error, the function tries to continue as much as possible.
-pub fn read(sess: &Session, path: &Path) -> TryConf {
-    let file = match sess.source_map().load_file(path) {
-        Err(e) => return e.into(),
-        Ok(file) => file,
-    };
-    match toml::de::Deserializer::new(file.src.as_ref().unwrap()).deserialize_map(ConfVisitor(&file)) {
+fn deserialize(file: &SourceFile) -> TryConf {
+    match toml::de::Deserializer::new(file.src.as_ref().unwrap()).deserialize_map(ConfVisitor(file)) {
         Ok(mut conf) => {
             extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
             extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
@@ -662,7 +633,7 @@ pub fn read(sess: &Session, path: &Path) -> TryConf {
 
             conf
         },
-        Err(e) => TryConf::from_toml_error(&file, &e),
+        Err(e) => TryConf::from_toml_error(file, &e),
     }
 }
 
@@ -672,6 +643,60 @@ fn extend_vec_if_indicator_present(vec: &mut Vec<String>, default: &[&str]) {
     }
 }
 
+impl Conf {
+    pub fn read(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> &'static Conf {
+        static CONF: OnceLock<Conf> = OnceLock::new();
+        CONF.get_or_init(|| Conf::read_inner(sess, path))
+    }
+
+    fn read_inner(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
+        match path {
+            Ok((_, warnings)) => {
+                for warning in warnings {
+                    sess.warn(warning.clone());
+                }
+            },
+            Err(error) => {
+                sess.err(format!("error finding Clippy's configuration file: {error}"));
+            },
+        }
+
+        let TryConf {
+            mut conf,
+            errors,
+            warnings,
+        } = match path {
+            Ok((Some(path), _)) => match sess.source_map().load_file(path) {
+                Ok(file) => deserialize(&file),
+                Err(error) => {
+                    sess.err(format!("failed to read `{}`: {error}", path.display()));
+                    TryConf::default()
+                },
+            },
+            _ => TryConf::default(),
+        };
+
+        conf.msrv.read_cargo(sess);
+
+        // all conf errors are non-fatal, we just use the default conf in case of error
+        for error in errors {
+            sess.span_err(
+                error.span,
+                format!("error reading Clippy's configuration file: {}", error.message),
+            );
+        }
+
+        for warning in warnings {
+            sess.span_warn(
+                warning.span,
+                format!("error reading Clippy's configuration file: {}", warning.message),
+            );
+        }
+
+        conf
+    }
+}
+
 const SEPARATOR_WIDTH: usize = 4;
 
 #[derive(Debug)]
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs
index fe2f12fe833..8cdd5ea8903 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs
@@ -30,7 +30,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
                 if_chain_local_span(cx, local, if_chain_span),
                 "`let` expression should be above the `if_chain!`",
             );
-        } else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) {
+        } else if local.span.eq_ctxt(block.span) && is_if_chain_then(after, block.expr, if_chain_span) {
             span_lint(
                 cx,
                 IF_CHAIN_STYLE,
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 82f9d4e41e8..fc9afe5ca8b 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -13,6 +13,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::ConstValue;
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::sym;
 use rustc_span::symbol::Symbol;
 
 use std::borrow::Cow;
@@ -160,12 +161,8 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
 
 impl InterningDefinedSymbol {
     fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> {
-        static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR, &paths::TO_STRING_METHOD];
-        static SYMBOL_STR_PATHS: &[&[&str]] = &[
-            &paths::SYMBOL_AS_STR,
-            &paths::SYMBOL_TO_IDENT_STRING,
-            &paths::TO_STRING_METHOD,
-        ];
+        static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR];
+        static SYMBOL_STR_PATHS: &[&[&str]] = &[&paths::SYMBOL_AS_STR, &paths::SYMBOL_TO_IDENT_STRING];
         let call = if_chain! {
             if let ExprKind::AddrOf(_, _, e) = expr.kind;
             if let ExprKind::Unary(UnOp::Deref, e) = e.kind;
@@ -186,9 +183,19 @@ impl InterningDefinedSymbol {
             };
             // ...which converts it to a string
             let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS };
-            if let Some(path) = paths.iter().find(|path| match_def_path(cx, did, path));
+            if let Some(is_to_owned) = paths
+                .iter()
+                .find_map(|path| if match_def_path(cx, did, path) {
+                    Some(path == &paths::SYMBOL_TO_IDENT_STRING)
+                } else {
+                    None
+                })
+                .or_else(|| if cx.tcx.is_diagnostic_item(sym::to_string_method, did) {
+                    Some(true)
+                } else {
+                    None
+                });
             then {
-                let is_to_owned = path.last().unwrap().ends_with("string");
                 return Some(SymbolStrExpr::Expr {
                     item,
                     is_ident,
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 8522493f67b..90091ca927a 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -9,6 +9,7 @@ arrayvec = { version = "0.7", default-features = false }
 if_chain = "1.0"
 itertools = "0.10.1"
 rustc-semver = "1.1"
+serde = { version = "1.0" }
 
 [features]
 deny-warnings = []
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 0bae7056c4f..79c04c7c7f4 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -504,7 +504,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
             },
             (Some(Constant::Vec(vec)), _) => {
                 if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) {
-                    match vec.get(0) {
+                    match vec.first() {
                         Some(Constant::F32(x)) => Some(Constant::F32(*x)),
                         Some(Constant::F64(x)) => Some(Constant::F64(*x)),
                         _ => None,
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 741f9f54883..edea4b3667f 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -449,7 +449,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
                 } else if name.ident.name == symbol::kw::Default {
                     return Some(VecInitKind::Default);
                 } else if name.ident.name.as_str() == "with_capacity" {
-                    let arg = args.get(0)?;
+                    let arg = args.first()?;
                     return match constant_simple(cx, cx.typeck_results(), arg) {
                         Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)),
                         _ => Some(VecInitKind::WithExprCapacity(arg.hir_id)),
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index c2c97259d38..93b37022822 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2027,48 +2027,88 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use))
 }
 
-/// Checks if an expression represents the identity function
-/// Only examines closures and `std::convert::identity`
-pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    /// Checks if a function's body represents the identity function. Looks for bodies of the form:
-    /// * `|x| x`
-    /// * `|x| return x`
-    /// * `|x| { return x }`
-    /// * `|x| { return x; }`
-    fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
-        let id = if_chain! {
-            if let [param] = func.params;
-            if let PatKind::Binding(_, id, _, _) = param.pat.kind;
-            then {
-                id
-            } else {
-                return false;
-            }
-        };
+/// Checks if a function's body represents the identity function. Looks for bodies of the form:
+/// * `|x| x`
+/// * `|x| return x`
+/// * `|x| { return x }`
+/// * `|x| { return x; }`
+///
+/// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
+fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
+    let id = if_chain! {
+        if let [param] = func.params;
+        if let PatKind::Binding(_, id, _, _) = param.pat.kind;
+        then {
+            id
+        } else {
+            return false;
+        }
+    };
 
-        let mut expr = func.value;
-        loop {
-            match expr.kind {
-                #[rustfmt::skip]
-                ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
-                | ExprKind::Ret(Some(e)) => expr = e,
-                #[rustfmt::skip]
-                ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
-                    if_chain! {
-                        if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
-                        if let ExprKind::Ret(Some(ret_val)) = e.kind;
-                        then {
-                            expr = ret_val;
-                        } else {
-                            return false;
-                        }
-                    }
+    let mut expr = func.value;
+    loop {
+        match expr.kind {
+            ExprKind::Block(
+                &Block {
+                    stmts: [],
+                    expr: Some(e),
+                    ..
                 },
-                _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
-            }
+                _,
+            )
+            | ExprKind::Ret(Some(e)) => expr = e,
+            ExprKind::Block(
+                &Block {
+                    stmts: [stmt],
+                    expr: None,
+                    ..
+                },
+                _,
+            ) => {
+                if_chain! {
+                    if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
+                    if let ExprKind::Ret(Some(ret_val)) = e.kind;
+                    then {
+                        expr = ret_val;
+                    } else {
+                        return false;
+                    }
+                }
+            },
+            _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
         }
     }
+}
 
+/// This is the same as [`is_expr_identity_function`], but does not consider closures
+/// with type annotations for its bindings (or similar) as identity functions:
+/// * `|x: u8| x`
+/// * `std::convert::identity::<u8>`
+pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        ExprKind::Closure(&Closure { body, fn_decl, .. })
+            if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) =>
+        {
+            is_body_identity_function(cx, cx.tcx.hir().body(body))
+        },
+        ExprKind::Path(QPath::Resolved(_, path))
+            if path.segments.iter().all(|seg| seg.infer_args)
+                && let Some(did) = path.res.opt_def_id() => {
+            cx.tcx.is_diagnostic_item(sym::convert_identity, did)
+        },
+        _ => false,
+    }
+}
+
+/// Checks if an expression represents the identity function
+/// Only examines closures and `std::convert::identity`
+///
+/// NOTE: If you want to use this function to find out if a closure is unnecessary, you likely want
+/// to call [`is_expr_untyped_identity_function`] instead, which makes sure that the closure doesn't
+/// have type annotations. This is important because removing a closure with bindings can
+/// remove type information that helped type inference before, which can then lead to compile
+/// errors.
+pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
         _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index df839c2106f..c6a48874e09 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -1,9 +1,7 @@
-use std::sync::OnceLock;
-
 use rustc_ast::Attribute;
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
-use rustc_span::Span;
+use serde::Deserialize;
 
 use crate::attrs::get_unique_attr;
 
@@ -53,65 +51,45 @@ msrv_aliases! {
     1,15,0 { MAYBE_BOUND_IN_WHERE }
 }
 
-fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
-    if let Ok(version) = RustcVersion::parse(msrv) {
-        return Some(version);
-    } else if let Some(sess) = sess {
-        if let Some(span) = span {
-            sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
-        }
-    }
-    None
-}
-
 /// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]`
-#[derive(Debug, Clone, Default)]
+#[derive(Debug, Clone)]
 pub struct Msrv {
     stack: Vec<RustcVersion>,
 }
 
+impl<'de> Deserialize<'de> for Msrv {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let v = String::deserialize(deserializer)?;
+        RustcVersion::parse(&v)
+            .map(|v| Msrv { stack: vec![v] })
+            .map_err(|_| serde::de::Error::custom("not a valid Rust version"))
+    }
+}
+
 impl Msrv {
-    fn new(initial: Option<RustcVersion>) -> Self {
-        Self {
-            stack: Vec::from_iter(initial),
-        }
+    pub fn empty() -> Msrv {
+        Msrv { stack: Vec::new() }
     }
 
-    fn read_inner(conf_msrv: &Option<String>, sess: &Session) -> Self {
+    pub fn read_cargo(&mut self, sess: &Session) {
         let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
             .ok()
-            .and_then(|v| parse_msrv(&v, None, None));
-        let clippy_msrv = conf_msrv.as_ref().and_then(|s| {
-            parse_msrv(s, None, None).or_else(|| {
-                sess.err(format!(
-                    "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
-                ));
-                None
-            })
-        });
-
-        // if both files have an msrv, let's compare them and emit a warning if they differ
-        if let Some(cargo_msrv) = cargo_msrv
-            && let Some(clippy_msrv) = clippy_msrv
-            && clippy_msrv != cargo_msrv
-        {
-            sess.warn(format!(
-                "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
-            ));
+            .and_then(|v| RustcVersion::parse(&v).ok());
+
+        match (self.current(), cargo_msrv) {
+            (None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv],
+            (Some(clippy_msrv), Some(cargo_msrv)) => {
+                if clippy_msrv != cargo_msrv {
+                    sess.warn(format!(
+                        "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
+                    ));
+                }
+            },
+            _ => {},
         }
-
-        Self::new(clippy_msrv.or(cargo_msrv))
-    }
-
-    /// Set the initial MSRV from the Clippy config file or from Cargo due to the `rust-version`
-    /// field in `Cargo.toml`
-    ///
-    /// Returns a `&'static Msrv` as `Copy` types are more easily passed to the
-    /// `register_{late,early}_pass` callbacks
-    pub fn read(conf_msrv: &Option<String>, sess: &Session) -> &'static Self {
-        static PARSED: OnceLock<Msrv> = OnceLock::new();
-
-        PARSED.get_or_init(|| Self::read_inner(conf_msrv, sess))
     }
 
     pub fn current(&self) -> Option<RustcVersion> {
@@ -125,10 +103,14 @@ impl Msrv {
     fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
         if let Some(msrv_attr) = get_unique_attr(sess, attrs, "msrv") {
             if let Some(msrv) = msrv_attr.value_str() {
-                return parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span));
-            }
+                if let Ok(version) = RustcVersion::parse(msrv.as_str()) {
+                    return Some(version);
+                }
 
-            sess.span_err(msrv_attr.span, "bad clippy attribute");
+                sess.span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust version"));
+            } else {
+                sess.span_err(msrv_attr.span, "bad clippy attribute");
+            }
         }
 
         None
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 1f2bb16f459..4a20399e364 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -98,7 +98,6 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol",
 pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 #[cfg(feature = "internal")]
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
-pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 55f9cb27ad4..f6096ea546d 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -305,8 +305,8 @@ fn check_terminator<'tcx>(
             Ok(())
         },
         TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
-        TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
-            Err((span, "const fn generators are unstable".into()))
+        TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => {
+            Err((span, "const fn coroutines are unstable".into()))
         },
         TerminatorKind::Call {
             func,
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
index 03a9d3c25fd..69c25b427e1 100644
--- a/src/tools/clippy/clippy_utils/src/str_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/str_utils.rs
@@ -236,6 +236,59 @@ pub fn count_match_end(str1: &str, str2: &str) -> StrCount {
         })
 }
 
+/// Returns a `snake_case` version of the input
+/// ```
+/// use clippy_utils::str_utils::to_snake_case;
+/// assert_eq!(to_snake_case("AbcDef"), "abc_def");
+/// assert_eq!(to_snake_case("ABCD"), "a_b_c_d");
+/// assert_eq!(to_snake_case("AbcDD"), "abc_d_d");
+/// assert_eq!(to_snake_case("Abc1DD"), "abc1_d_d");
+/// ```
+pub fn to_snake_case(name: &str) -> String {
+    let mut s = String::new();
+    for (i, c) in name.chars().enumerate() {
+        if c.is_uppercase() {
+            // characters without capitalization are considered lowercase
+            if i != 0 {
+                s.push('_');
+            }
+            s.extend(c.to_lowercase());
+        } else {
+            s.push(c);
+        }
+    }
+    s
+}
+/// Returns a `CamelCase` version of the input
+/// ```
+/// use clippy_utils::str_utils::to_camel_case;
+/// assert_eq!(to_camel_case("abc_def"), "AbcDef");
+/// assert_eq!(to_camel_case("a_b_c_d"), "ABCD");
+/// assert_eq!(to_camel_case("abc_d_d"), "AbcDD");
+/// assert_eq!(to_camel_case("abc1_d_d"), "Abc1DD");
+/// ```
+pub fn to_camel_case(item_name: &str) -> String {
+    let mut s = String::new();
+    let mut up = true;
+    for c in item_name.chars() {
+        if c.is_uppercase() {
+            // we only turn snake case text into CamelCase
+            return item_name.to_string();
+        }
+        if c == '_' {
+            up = true;
+            continue;
+        }
+        if up {
+            up = false;
+            s.extend(c.to_uppercase());
+        } else {
+            s.push(c);
+        }
+    }
+    s
+}
+
 #[cfg(test)]
 mod test {
     use super::*;
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index fe2c77ab47f..7c5b5e97a5c 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-10-06"
+channel = "nightly-2023-10-21"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index d47767faed9..0e81419f1fa 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -147,9 +147,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
                 (previous)(sess, lint_store);
             }
 
-            let conf = clippy_lints::read_conf(sess, &conf_path);
-            clippy_lints::register_plugins(lint_store, sess, &conf);
-            clippy_lints::register_pre_expansion_lints(lint_store, sess, &conf);
+            let conf = clippy_lints::Conf::read(sess, &conf_path);
+            clippy_lints::register_plugins(lint_store, sess, conf);
+            clippy_lints::register_pre_expansion_lints(lint_store, conf);
             clippy_lints::register_renamed(lint_store);
         }));
 
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index f340cf5938a..1494c7d3179 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -105,27 +105,20 @@ static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| {
 // whether to run internal tests or not
 const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");
 
-fn canonicalize(path: impl AsRef<Path>) -> PathBuf {
-    let path = path.as_ref();
-    fs::create_dir_all(path).unwrap();
-    fs::canonicalize(path).unwrap_or_else(|err| panic!("{} cannot be canonicalized: {err}", path.display()))
-}
-
 fn base_config(test_dir: &str) -> (Config, Args) {
     let mut args = Args::test().unwrap();
     args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
 
+    let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into()));
     let mut config = Config {
         mode: Mode::Yolo {
             rustfix: ui_test::RustfixMode::Everything,
         },
-        stderr_filters: vec![(Match::PathBackslash, b"/")],
-        stdout_filters: vec![],
         filter_files: env::var("TESTNAME")
             .map(|filters| filters.split(',').map(str::to_string).collect())
             .unwrap_or_default(),
         target: None,
-        out_dir: canonicalize(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())).join("ui_test"),
+        out_dir: target_dir.join("ui_test"),
         ..Config::rustc(Path::new("tests").join(test_dir))
     };
     config.with_args(&args, /* bless by default */ false);
@@ -168,19 +161,13 @@ fn run_ui() {
     config
         .program
         .envs
-        .push(("CLIPPY_CONF_DIR".into(), Some(canonicalize("tests").into())));
-
-    let quiet = args.quiet;
+        .push(("CLIPPY_CONF_DIR".into(), Some("tests".into())));
 
     ui_test::run_tests_generic(
         vec![config],
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
-        if quiet {
-            status_emitter::Text::quiet()
-        } else {
-            status_emitter::Text::verbose()
-        },
+        status_emitter::Text::from(args.format),
     )
     .unwrap();
 }
@@ -194,17 +181,12 @@ fn run_internal_tests() {
     if let OutputConflictHandling::Error(err) = &mut config.output_conflict_handling {
         *err = "cargo uitest --features internal -- -- --bless".into();
     }
-    let quiet = args.quiet;
 
     ui_test::run_tests_generic(
         vec![config],
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
-        if quiet {
-            status_emitter::Text::quiet()
-        } else {
-            status_emitter::Text::verbose()
-        },
+        status_emitter::Text::from(args.format),
     )
     .unwrap();
 }
@@ -212,22 +194,9 @@ fn run_internal_tests() {
 fn run_ui_toml() {
     let (mut config, args) = base_config("ui-toml");
 
-    config.stderr_filters = vec![
-        (
-            Match::Exact(
-                canonicalize("tests")
-                    .parent()
-                    .unwrap()
-                    .to_string_lossy()
-                    .as_bytes()
-                    .to_vec(),
-            ),
-            b"$DIR",
-        ),
-        (Match::Exact(b"\\".to_vec()), b"/"),
-    ];
-
-    let quiet = args.quiet;
+    config
+        .stderr_filters
+        .push((Match::from(env::current_dir().unwrap().as_path()), b"$DIR"));
 
     ui_test::run_tests_generic(
         vec![config],
@@ -238,11 +207,7 @@ fn run_ui_toml() {
                 .envs
                 .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into())));
         },
-        if quiet {
-            status_emitter::Text::quiet()
-        } else {
-            status_emitter::Text::verbose()
-        },
+        status_emitter::Text::from(args.format),
     )
     .unwrap();
 }
@@ -270,22 +235,9 @@ fn run_ui_cargo() {
     });
     config.edition = None;
 
-    config.stderr_filters = vec![
-        (
-            Match::Exact(
-                canonicalize("tests")
-                    .parent()
-                    .unwrap()
-                    .to_string_lossy()
-                    .as_bytes()
-                    .to_vec(),
-            ),
-            b"$DIR",
-        ),
-        (Match::Exact(b"\\".to_vec()), b"/"),
-    ];
-
-    let quiet = args.quiet;
+    config
+        .stderr_filters
+        .push((Match::from(env::current_dir().unwrap().as_path()), b"$DIR"));
 
     let ignored_32bit = |path: &Path| {
         // FIXME: for some reason the modules are linted in a different order for this test
@@ -297,20 +249,8 @@ fn run_ui_cargo() {
         |path, config| {
             path.ends_with("Cargo.toml") && ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)
         },
-        |config, path, _file_contents| {
-            config.out_dir = canonicalize(
-                std::env::current_dir()
-                    .unwrap()
-                    .join("target")
-                    .join("ui_test_cargo/")
-                    .join(path.parent().unwrap()),
-            );
-        },
-        if quiet {
-            status_emitter::Text::quiet()
-        } else {
-            status_emitter::Text::verbose()
-        },
+        |_config, _path, _file_contents| {},
+        status_emitter::Text::from(args.format),
     )
     .unwrap();
 }
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
index 60be2978813..f6abb3cc3d7 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
@@ -12,5 +12,5 @@ fn main() {
     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
 
     // Don't lint, not a diagnostic or language item
-    const OPS_MOD: [&str; 5] = ["core", "ops"];
+    const OPS_MOD: [&str; 2] = ["core", "ops"];
 }
diff --git a/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/clippy.toml b/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/clippy.toml
new file mode 100644
index 00000000000..34a1036e891
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/clippy.toml
@@ -0,0 +1 @@
+ignore-interior-mutability = ["borrow_interior_mutable_const_ignore::Counted"]
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/ignore.rs b/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/ignore.rs
new file mode 100644
index 00000000000..79c7cef6ce1
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/borrow_interior_mutable_const/ignore.rs
@@ -0,0 +1,37 @@
+//@compile-flags: --crate-name borrow_interior_mutable_const_ignore
+
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const)]
+
+use core::cell::Cell;
+use std::cmp::{Eq, PartialEq};
+use std::collections::{HashMap, HashSet};
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+struct Counted<T> {
+    count: AtomicUsize,
+    val: T,
+}
+
+impl<T> Counted<T> {
+    const fn new(val: T) -> Self {
+        Self {
+            count: AtomicUsize::new(0),
+            val,
+        }
+    }
+}
+
+enum OptionalCell {
+    Unfrozen(Counted<bool>),
+    Frozen,
+}
+
+const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Counted::new(true));
+const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+fn main() {
+    let _ = &UNFROZEN_VARIANT;
+}
diff --git a/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/clippy.toml b/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/clippy.toml
new file mode 100644
index 00000000000..71d13212e2a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/clippy.toml
@@ -0,0 +1 @@
+ignore-interior-mutability = ["declare_interior_mutable_const_ignore::Counted"]
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/ignore.rs b/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/ignore.rs
new file mode 100644
index 00000000000..6385cf4f852
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/declare_interior_mutable_const/ignore.rs
@@ -0,0 +1,46 @@
+//@compile-flags: --crate-name declare_interior_mutable_const_ignore
+
+#![warn(clippy::declare_interior_mutable_const)]
+#![allow(clippy::borrow_interior_mutable_const)]
+
+use core::cell::Cell;
+use std::cmp::{Eq, PartialEq};
+use std::collections::{HashMap, HashSet};
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+struct Counted<T> {
+    count: AtomicUsize,
+    val: T,
+}
+
+impl<T> Counted<T> {
+    const fn new(val: T) -> Self {
+        Self {
+            count: AtomicUsize::new(0),
+            val,
+        }
+    }
+}
+
+enum OptionalCell {
+    Unfrozen(Counted<bool>),
+    Frozen,
+}
+
+const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Counted::new(true));
+const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
+
+const fn unfrozen_variant() -> OptionalCell {
+    OptionalCell::Unfrozen(Counted::new(true))
+}
+
+const fn frozen_variant() -> OptionalCell {
+    OptionalCell::Frozen
+}
+
+const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant();
+const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant();
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs
deleted file mode 100644
index 8f4e178ccfe..00000000000
--- a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-enum Foo {
-    AFoo,
-    BFoo,
-    CFoo,
-    DFoo,
-}
-enum Foo2 {
-    //~^ ERROR: all variants have the same postfix
-    AFoo,
-    BFoo,
-    CFoo,
-    DFoo,
-    EFoo,
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr b/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr
deleted file mode 100644
index 11039b1db48..00000000000
--- a/src/tools/clippy/tests/ui-toml/enum_variant_names/enum_variant_names.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: all variants have the same postfix: `Foo`
-  --> $DIR/enum_variant_names.rs:7:1
-   |
-LL | / enum Foo2 {
-LL | |
-LL | |     AFoo,
-LL | |     BFoo,
-...  |
-LL | |     EFoo,
-LL | | }
-   | |_^
-   |
-   = help: remove the postfixes and use full paths to the variants instead of glob imports
-   = note: `-D clippy::enum-variant-names` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::enum_variant_names)]`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui-toml/impl_trait_in_params/clippy.toml b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/clippy.toml
new file mode 100644
index 00000000000..87e1f235741
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/clippy.toml
@@ -0,0 +1 @@
+avoid-breaking-exported-api = false
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs
new file mode 100644
index 00000000000..08fc7edf1c8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.rs
@@ -0,0 +1,16 @@
+//! As avoid-breaking-exported-api is `false`, nothing here should lint
+#![warn(clippy::impl_trait_in_params)]
+#![no_main]
+//@no-rustfix
+
+pub trait Trait {}
+
+trait Private {
+    fn t(_: impl Trait);
+    fn tt<T: Trait>(_: T);
+}
+
+pub trait Public {
+    fn t(_: impl Trait); //~ ERROR: `impl Trait` used as a function parameter
+    fn tt<T: Trait>(_: T);
+}
diff --git a/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr
new file mode 100644
index 00000000000..80c4f5ed4b0
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr
@@ -0,0 +1,15 @@
+error: `impl Trait` used as a function parameter
+  --> $DIR/impl_trait_in_params.rs:14:13
+   |
+LL |     fn t(_: impl Trait);
+   |             ^^^^^^^^^^
+   |
+   = note: `-D clippy::impl-trait-in-params` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::impl_trait_in_params)]`
+help: add a type parameter
+   |
+LL |     fn t<{ /* Generic name */ }: Trait>(_: impl Trait);
+   |         +++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
index 03fa719975b..85e2fb8c797 100644
--- a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
+++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
@@ -1,4 +1,4 @@
-//@error-in-other-file: `invalid.version` is not a valid Rust version
+//@error-in-other-file: not a valid Rust version
 
 #![allow(clippy::redundant_clone)]
 
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr
index e9d8fd2e0f5..f127c2408f9 100644
--- a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr
+++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr
@@ -1,4 +1,8 @@
-error: error reading Clippy's configuration file. `invalid.version` is not a valid Rust version
+error: error reading Clippy's configuration file: not a valid Rust version
+  --> $DIR/$DIR/clippy.toml:1:8
+   |
+LL | msrv = "invalid.version"
+   |        ^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/clippy.toml
index f85aade6ae8..d41edbaf7fa 100644
--- a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/clippy.toml
@@ -1 +1,2 @@
+struct-field-name-threshold = 0
 enum-variant-name-threshold = 0
diff --git a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs
index 6918d7528c1..b633dcbd19e 100644
--- a/src/tools/clippy/tests/ui-toml/enum_variants_threshold0/enum_variants_name_threshold.rs
+++ b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs
@@ -1,3 +1,5 @@
+struct Data {}
+
 enum Actions {}
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/clippy.toml
index 0ad7a979948..028a6279079 100644
--- a/src/tools/clippy/tests/ui-toml/enum_variant_names/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/clippy.toml
@@ -1 +1,2 @@
 enum-variant-name-threshold = 5
+struct-field-name-threshold = 5
diff --git a/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.rs b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.rs
new file mode 100644
index 00000000000..d437311691d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.rs
@@ -0,0 +1,32 @@
+#![warn(clippy::struct_field_names)]
+
+struct Data {
+    a_data: u8,
+    b_data: u8,
+    c_data: u8,
+    d_data: u8,
+}
+struct Data2 {
+    //~^ ERROR: all fields have the same postfix
+    a_data: u8,
+    b_data: u8,
+    c_data: u8,
+    d_data: u8,
+    e_data: u8,
+}
+enum Foo {
+    AFoo,
+    BFoo,
+    CFoo,
+    DFoo,
+}
+enum Foo2 {
+    //~^ ERROR: all variants have the same postfix
+    AFoo,
+    BFoo,
+    CFoo,
+    DFoo,
+    EFoo,
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.stderr b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.stderr
new file mode 100644
index 00000000000..33802c44bf9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/item_name_repetitions/threshold5/item_name_repetitions.stderr
@@ -0,0 +1,34 @@
+error: all fields have the same postfix: `data`
+  --> $DIR/item_name_repetitions.rs:9:1
+   |
+LL | / struct Data2 {
+LL | |
+LL | |     a_data: u8,
+LL | |     b_data: u8,
+...  |
+LL | |     e_data: u8,
+LL | | }
+   | |_^
+   |
+   = help: remove the postfixes
+   = note: `-D clippy::struct-field-names` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::struct_field_names)]`
+
+error: all variants have the same postfix: `Foo`
+  --> $DIR/item_name_repetitions.rs:23:1
+   |
+LL | / enum Foo2 {
+LL | |
+LL | |     AFoo,
+LL | |     BFoo,
+...  |
+LL | |     EFoo,
+LL | | }
+   | |_^
+   |
+   = help: remove the postfixes and use full paths to the variants instead of glob imports
+   = note: `-D clippy::enum-variant-names` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::enum_variant_names)]`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
index 830d71f61dd..cd53f504459 100644
--- a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
@@ -1,5 +1,6 @@
 //! this is crate
 #![allow(missing_docs)]
+#![allow(clippy::struct_field_names)]
 #![warn(clippy::missing_docs_in_private_items)]
 
 /// this is mod
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
index 1ecdabbc03e..2cf20b46049 100644
--- a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
@@ -1,5 +1,5 @@
 error: missing documentation for a function
-  --> $DIR/pub_crate_missing_doc.rs:12:5
+  --> $DIR/pub_crate_missing_doc.rs:13:5
    |
 LL |     pub(crate) fn crate_no_docs() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,25 +8,25 @@ LL |     pub(crate) fn crate_no_docs() {}
    = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]`
 
 error: missing documentation for a function
-  --> $DIR/pub_crate_missing_doc.rs:15:5
+  --> $DIR/pub_crate_missing_doc.rs:16:5
    |
 LL |     pub(super) fn super_no_docs() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/pub_crate_missing_doc.rs:23:9
+  --> $DIR/pub_crate_missing_doc.rs:24:9
    |
 LL |         pub(crate) fn sub_crate_no_docs() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/pub_crate_missing_doc.rs:33:9
+  --> $DIR/pub_crate_missing_doc.rs:34:9
    |
 LL |         pub(crate) crate_field_no_docs: (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
-  --> $DIR/pub_crate_missing_doc.rs:39:5
+  --> $DIR/pub_crate_missing_doc.rs:40:5
    |
 LL | /     pub(crate) struct CrateStructNoDocs {
 LL | |         /// some docs
@@ -38,13 +38,13 @@ LL | |     }
    | |_____^
 
 error: missing documentation for a struct field
-  --> $DIR/pub_crate_missing_doc.rs:42:9
+  --> $DIR/pub_crate_missing_doc.rs:43:9
    |
 LL |         pub(crate) crate_field_no_docs: (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a type alias
-  --> $DIR/pub_crate_missing_doc.rs:51:1
+  --> $DIR/pub_crate_missing_doc.rs:52:1
    |
 LL | type CrateTypedefNoDocs = String;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 4bed5c149f5..2f9eaa5178c 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -53,6 +53,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            single-char-binding-names-threshold
            stack-size-threshold
            standard-macro-braces
+           struct-field-name-threshold
            suppress-restriction-lint-in-const
            third-party
            too-large-for-stack
@@ -126,6 +127,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            single-char-binding-names-threshold
            stack-size-threshold
            standard-macro-braces
+           struct-field-name-threshold
            suppress-restriction-lint-in-const
            third-party
            too-large-for-stack
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.rs b/src/tools/clippy/tests/ui/author/macro_in_closure.rs
new file mode 100644
index 00000000000..444e6a12165
--- /dev/null
+++ b/src/tools/clippy/tests/ui/author/macro_in_closure.rs
@@ -0,0 +1,5 @@
+fn main() {
+    #[clippy::author]
+    let print_text = |x| println!("{}", x);
+    print_text("hello");
+}
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
new file mode 100644
index 00000000000..9ab71986f40
--- /dev/null
+++ b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
@@ -0,0 +1,39 @@
+if let StmtKind::Local(local) = stmt.kind
+    && let Some(init) = local.init
+    && let ExprKind::Closure(CaptureBy::Ref, fn_decl, body_id, _, None) = init.kind
+    && let FnRetTy::DefaultReturn(_) = fn_decl.output
+    && expr = &cx.tcx.hir().body(body_id).value
+    && let ExprKind::Block(block, None) = expr.kind
+    && block.stmts.len() == 1
+    && let StmtKind::Semi(e) = block.stmts[0].kind
+    && let ExprKind::Call(func, args) = e.kind
+    && let ExprKind::Path(ref qpath) = func.kind
+    && match_qpath(qpath, &["$crate", "io", "_print"])
+    && args.len() == 1
+    && let ExprKind::Call(func1, args1) = args[0].kind
+    && let ExprKind::Path(ref qpath1) = func1.kind
+    && args1.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
+    && let ExprKind::Array(elements) = inner.kind
+    && elements.len() == 2
+    && let ExprKind::Lit(ref lit) = elements[0].kind
+    && let LitKind::Str(s, _) = lit.node
+    && s.as_str() == ""
+    && let ExprKind::Lit(ref lit1) = elements[1].kind
+    && let LitKind::Str(s1, _) = lit1.node
+    && s1.as_str() == "\n"
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 1
+    && let ExprKind::Call(func2, args2) = elements1[0].kind
+    && let ExprKind::Path(ref qpath2) = func2.kind
+    && args2.len() == 1
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::Path(ref qpath3) = inner2.kind
+    && match_qpath(qpath3, &["x"])
+    && block.expr.is_none()
+    && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind
+    && name.as_str() == "print_text"
+{
+    // report your lint here
+}
diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.rs b/src/tools/clippy/tests/ui/author/macro_in_loop.rs
new file mode 100644
index 00000000000..8a520501f8d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/author/macro_in_loop.rs
@@ -0,0 +1,8 @@
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+    #[clippy::author]
+    for i in 0..1 {
+        println!("{}", i);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout
new file mode 100644
index 00000000000..bd054b6abc4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout
@@ -0,0 +1,48 @@
+if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
+    && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind
+    && name.as_str() == "i"
+    && let ExprKind::Struct(qpath, fields, None) = arg.kind
+    && matches!(qpath, QPath::LangItem(LangItem::Range, _))
+    && fields.len() == 2
+    && fields[0].ident.as_str() == "start"
+    && let ExprKind::Lit(ref lit) = fields[0].expr.kind
+    && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+    && fields[1].ident.as_str() == "end"
+    && let ExprKind::Lit(ref lit1) = fields[1].expr.kind
+    && let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node
+    && let ExprKind::Block(block, None) = body.kind
+    && block.stmts.len() == 1
+    && let StmtKind::Semi(e) = block.stmts[0].kind
+    && let ExprKind::Block(block1, None) = e.kind
+    && block1.stmts.len() == 1
+    && let StmtKind::Semi(e1) = block1.stmts[0].kind
+    && let ExprKind::Call(func, args) = e1.kind
+    && let ExprKind::Path(ref qpath1) = func.kind
+    && match_qpath(qpath1, &["$crate", "io", "_print"])
+    && args.len() == 1
+    && let ExprKind::Call(func1, args1) = args[0].kind
+    && let ExprKind::Path(ref qpath2) = func1.kind
+    && args1.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
+    && let ExprKind::Array(elements) = inner.kind
+    && elements.len() == 2
+    && let ExprKind::Lit(ref lit2) = elements[0].kind
+    && let LitKind::Str(s, _) = lit2.node
+    && s.as_str() == ""
+    && let ExprKind::Lit(ref lit3) = elements[1].kind
+    && let LitKind::Str(s1, _) = lit3.node
+    && s1.as_str() == "\n"
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 1
+    && let ExprKind::Call(func2, args2) = elements1[0].kind
+    && let ExprKind::Path(ref qpath3) = func2.kind
+    && args2.len() == 1
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::Path(ref qpath4) = inner2.kind
+    && match_qpath(qpath4, &["i"])
+    && block1.expr.is_none()
+    && block.expr.is_none()
+{
+    // report your lint here
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5238.rs b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
index 989eb6d4485..b1fc3fb9d25 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5238.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
@@ -1,6 +1,6 @@
 // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 fn main() {
     let _ = || {
diff --git a/src/tools/clippy/tests/ui/get_first.fixed b/src/tools/clippy/tests/ui/get_first.fixed
index b1a597fc4dd..a7cdd2a93ba 100644
--- a/src/tools/clippy/tests/ui/get_first.fixed
+++ b/src/tools/clippy/tests/ui/get_first.fixed
@@ -14,17 +14,20 @@ impl Bar {
 
 fn main() {
     let x = vec![2, 3, 5];
-    let _ = x.first(); // Use x.first()
+    let _ = x.first();
+    //~^ ERROR: accessing first element with `x.get(0)`
     let _ = x.get(1);
     let _ = x[0];
 
     let y = [2, 3, 5];
-    let _ = y.first(); // Use y.first()
+    let _ = y.first();
+    //~^ ERROR: accessing first element with `y.get(0)`
     let _ = y.get(1);
     let _ = y[0];
 
     let z = &[2, 3, 5];
-    let _ = z.first(); // Use z.first()
+    let _ = z.first();
+    //~^ ERROR: accessing first element with `z.get(0)`
     let _ = z.get(1);
     let _ = z[0];
 
@@ -37,4 +40,8 @@ fn main() {
 
     let bar = Bar { arr: [0, 1, 2] };
     let _ = bar.get(0); // Do not lint, because Bar is struct.
+
+    let non_primitives = [vec![1, 2], vec![3, 4]];
+    let _ = non_primitives.first();
+    //~^ ERROR: accessing first element with `non_primitives.get(0)`
 }
diff --git a/src/tools/clippy/tests/ui/get_first.rs b/src/tools/clippy/tests/ui/get_first.rs
index e27ee4be8c0..cca743c4bf5 100644
--- a/src/tools/clippy/tests/ui/get_first.rs
+++ b/src/tools/clippy/tests/ui/get_first.rs
@@ -14,17 +14,20 @@ impl Bar {
 
 fn main() {
     let x = vec![2, 3, 5];
-    let _ = x.get(0); // Use x.first()
+    let _ = x.get(0);
+    //~^ ERROR: accessing first element with `x.get(0)`
     let _ = x.get(1);
     let _ = x[0];
 
     let y = [2, 3, 5];
-    let _ = y.get(0); // Use y.first()
+    let _ = y.get(0);
+    //~^ ERROR: accessing first element with `y.get(0)`
     let _ = y.get(1);
     let _ = y[0];
 
     let z = &[2, 3, 5];
-    let _ = z.get(0); // Use z.first()
+    let _ = z.get(0);
+    //~^ ERROR: accessing first element with `z.get(0)`
     let _ = z.get(1);
     let _ = z[0];
 
@@ -37,4 +40,8 @@ fn main() {
 
     let bar = Bar { arr: [0, 1, 2] };
     let _ = bar.get(0); // Do not lint, because Bar is struct.
+
+    let non_primitives = [vec![1, 2], vec![3, 4]];
+    let _ = non_primitives.get(0);
+    //~^ ERROR: accessing first element with `non_primitives.get(0)`
 }
diff --git a/src/tools/clippy/tests/ui/get_first.stderr b/src/tools/clippy/tests/ui/get_first.stderr
index 56b4c29a313..8ee66e33cc8 100644
--- a/src/tools/clippy/tests/ui/get_first.stderr
+++ b/src/tools/clippy/tests/ui/get_first.stderr
@@ -1,23 +1,29 @@
 error: accessing first element with `x.get(0)`
   --> $DIR/get_first.rs:17:13
    |
-LL |     let _ = x.get(0); // Use x.first()
+LL |     let _ = x.get(0);
    |             ^^^^^^^^ help: try: `x.first()`
    |
    = note: `-D clippy::get-first` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::get_first)]`
 
 error: accessing first element with `y.get(0)`
-  --> $DIR/get_first.rs:22:13
+  --> $DIR/get_first.rs:23:13
    |
-LL |     let _ = y.get(0); // Use y.first()
+LL |     let _ = y.get(0);
    |             ^^^^^^^^ help: try: `y.first()`
 
 error: accessing first element with `z.get(0)`
-  --> $DIR/get_first.rs:27:13
+  --> $DIR/get_first.rs:29:13
    |
-LL |     let _ = z.get(0); // Use z.first()
+LL |     let _ = z.get(0);
    |             ^^^^^^^^ help: try: `z.first()`
 
-error: aborting due to 3 previous errors
+error: accessing first element with `non_primitives.get(0)`
+  --> $DIR/get_first.rs:45:13
+   |
+LL |     let _ = non_primitives.get(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `non_primitives.first()`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.rs b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
index b652e4a4abe..a6251a370d1 100644
--- a/src/tools/clippy/tests/ui/impl_trait_in_params.rs
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
@@ -1,20 +1,47 @@
 #![allow(unused)]
 #![warn(clippy::impl_trait_in_params)]
+
 //@no-rustfix
 pub trait Trait {}
 pub trait AnotherTrait<T> {}
 
 // Should warn
 pub fn a(_: impl Trait) {}
-//~^ ERROR: '`impl Trait` used as a function parameter'
-//~| NOTE: `-D clippy::impl-trait-in-params` implied by `-D warnings`
+//~^ ERROR: `impl Trait` used as a function parameter
 pub fn c<C: Trait>(_: C, _: impl Trait) {}
-//~^ ERROR: '`impl Trait` used as a function parameter'
-fn d(_: impl AnotherTrait<u32>) {}
+//~^ ERROR: `impl Trait` used as a function parameter
 
 // Shouldn't warn
 
 pub fn b<B: Trait>(_: B) {}
 fn e<T: AnotherTrait<u32>>(_: T) {}
+fn d(_: impl AnotherTrait<u32>) {}
+
+//------ IMPLS
+
+pub trait Public {
+    // See test in ui-toml for a case where avoid-breaking-exported-api is set to false
+    fn t(_: impl Trait);
+    fn tt<T: Trait>(_: T) {}
+}
+
+trait Private {
+    // This shouldn't lint
+    fn t(_: impl Trait);
+    fn tt<T: Trait>(_: T) {}
+}
+
+struct S;
+impl S {
+    pub fn h(_: impl Trait) {} //~ ERROR: `impl Trait` used as a function parameter
+    fn i(_: impl Trait) {}
+    pub fn j<J: Trait>(_: J) {}
+    pub fn k<K: AnotherTrait<u32>>(_: K, _: impl AnotherTrait<u32>) {} //~ ERROR: `impl Trait` used as a function parameter
+}
+
+// Trying with traits
+impl Public for S {
+    fn t(_: impl Trait) {}
+}
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.stderr b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
index 36b4f27e9a4..0ae7a3672d1 100644
--- a/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
@@ -1,5 +1,5 @@
-error: '`impl Trait` used as a function parameter'
-  --> $DIR/impl_trait_in_params.rs:8:13
+error: `impl Trait` used as a function parameter
+  --> $DIR/impl_trait_in_params.rs:9:13
    |
 LL | pub fn a(_: impl Trait) {}
    |             ^^^^^^^^^^
@@ -11,7 +11,7 @@ help: add a type parameter
 LL | pub fn a<{ /* Generic name */ }: Trait>(_: impl Trait) {}
    |         +++++++++++++++++++++++++++++++
 
-error: '`impl Trait` used as a function parameter'
+error: `impl Trait` used as a function parameter
   --> $DIR/impl_trait_in_params.rs:11:29
    |
 LL | pub fn c<C: Trait>(_: C, _: impl Trait) {}
@@ -22,5 +22,27 @@ help: add a type parameter
 LL | pub fn c<C: Trait, { /* Generic name */ }: Trait>(_: C, _: impl Trait) {}
    |                  +++++++++++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: `impl Trait` used as a function parameter
+  --> $DIR/impl_trait_in_params.rs:36:17
+   |
+LL |     pub fn h(_: impl Trait) {}
+   |                 ^^^^^^^^^^
+   |
+help: add a type parameter
+   |
+LL |     pub fn h<{ /* Generic name */ }: Trait>(_: impl Trait) {}
+   |             +++++++++++++++++++++++++++++++
+
+error: `impl Trait` used as a function parameter
+  --> $DIR/impl_trait_in_params.rs:39:45
+   |
+LL |     pub fn k<K: AnotherTrait<u32>>(_: K, _: impl AnotherTrait<u32>) {}
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a type parameter
+   |
+LL |     pub fn k<K: AnotherTrait<u32>, { /* Generic name */ }: AnotherTrait<u32>>(_: K, _: impl AnotherTrait<u32>) {}
+   |                                  +++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.rs b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
index 6be3bb8abdd..e6ff821a8ad 100644
--- a/src/tools/clippy/tests/ui/into_iter_without_iter.rs
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
@@ -122,3 +122,37 @@ fn main() {
         }
     }
 }
+
+fn issue11635() {
+    // A little more involved than the original repro in the issue, but this tests that it correctly
+    // works for more than one deref step
+
+    use std::ops::Deref;
+
+    pub struct Thing(Vec<u8>);
+    pub struct Thing2(Thing);
+
+    impl Deref for Thing {
+        type Target = [u8];
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+
+    impl Deref for Thing2 {
+        type Target = Thing;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+
+    impl<'a> IntoIterator for &'a Thing2 {
+        type Item = &'a u8;
+        type IntoIter = <&'a [u8] as IntoIterator>::IntoIter;
+
+        fn into_iter(self) -> Self::IntoIter {
+            self.0.iter()
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/large_futures.fixed b/src/tools/clippy/tests/ui/large_futures.fixed
index 4c192d1c8d1..aa8c3021b97 100644
--- a/src/tools/clippy/tests/ui/large_futures.fixed
+++ b/src/tools/clippy/tests/ui/large_futures.fixed
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![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 557d89a9cf9..fc6ea458d3d 100644
--- a/src/tools/clippy/tests/ui/large_futures.rs
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 #![warn(clippy::large_futures)]
 #![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.fixed b/src/tools/clippy/tests/ui/manual_filter_map.fixed
index 4de45e39b10..a44c46c145c 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter_map.fixed
@@ -2,6 +2,7 @@
 #![warn(clippy::manual_filter_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
 #![allow(clippy::useless_vec)]
+#![allow(clippy::struct_field_names)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.rs b/src/tools/clippy/tests/ui/manual_filter_map.rs
index 22f316f90b6..e72d0c4305b 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.rs
+++ b/src/tools/clippy/tests/ui/manual_filter_map.rs
@@ -2,6 +2,7 @@
 #![warn(clippy::manual_filter_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
 #![allow(clippy::useless_vec)]
+#![allow(clippy::struct_field_names)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.stderr b/src/tools/clippy/tests/ui/manual_filter_map.stderr
index 0bfc1f5c745..cf64bb25951 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.stderr
+++ b/src/tools/clippy/tests/ui/manual_filter_map.stderr
@@ -1,11 +1,11 @@
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:8:19
+  --> $DIR/manual_filter_map.rs:9:19
    |
 LL |     let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:8:30
+  --> $DIR/manual_filter_map.rs:9:30
    |
 LL |     let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                              ^^^^^^^^^^
@@ -13,31 +13,31 @@ LL |     let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap
    = help: to override `-D warnings` add `#[allow(clippy::manual_filter_map)]`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:11:19
+  --> $DIR/manual_filter_map.rs:12:19
    |
 LL |     let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:11:31
+  --> $DIR/manual_filter_map.rs:12:31
    |
 LL |     let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                               ^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:14:19
+  --> $DIR/manual_filter_map.rs:15:19
    |
 LL |     let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:14:31
+  --> $DIR/manual_filter_map.rs:15:31
    |
 LL |     let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                               ^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:17:10
+  --> $DIR/manual_filter_map.rs:18:10
    |
 LL |           .filter(|&x| to_ref(to_opt(x)).is_some())
    |  __________^
@@ -45,13 +45,13 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:17:22
+  --> $DIR/manual_filter_map.rs:18:22
    |
 LL |         .filter(|&x| to_ref(to_opt(x)).is_some())
    |                      ^^^^^^^^^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:20:10
+  --> $DIR/manual_filter_map.rs:21:10
    |
 LL |           .filter(|x| to_ref(to_opt(*x)).is_some())
    |  __________^
@@ -59,13 +59,13 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:20:21
+  --> $DIR/manual_filter_map.rs:21:21
    |
 LL |         .filter(|x| to_ref(to_opt(*x)).is_some())
    |                     ^^^^^^^^^^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:24:10
+  --> $DIR/manual_filter_map.rs:25:10
    |
 LL |           .filter(|&x| to_ref(to_res(x)).is_ok())
    |  __________^
@@ -73,13 +73,13 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:24:22
+  --> $DIR/manual_filter_map.rs:25:22
    |
 LL |         .filter(|&x| to_ref(to_res(x)).is_ok())
    |                      ^^^^^^^^^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:27:10
+  --> $DIR/manual_filter_map.rs:28:10
    |
 LL |           .filter(|x| to_ref(to_res(*x)).is_ok())
    |  __________^
@@ -87,13 +87,13 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:27:21
+  --> $DIR/manual_filter_map.rs:28:21
    |
 LL |         .filter(|x| to_ref(to_res(*x)).is_ok())
    |                     ^^^^^^^^^^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:33:27
+  --> $DIR/manual_filter_map.rs:34:27
    |
 LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
@@ -102,79 +102,79 @@ LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()
    = help: to override `-D warnings` add `#[allow(clippy::manual_find_map)]`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:34:28
+  --> $DIR/manual_filter_map.rs:35:28
    |
 LL |     iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:35:31
+  --> $DIR/manual_filter_map.rs:36:31
    |
 LL |     iter::<&Option<String>>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:36:31
+  --> $DIR/manual_filter_map.rs:37:31
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:36:41
+  --> $DIR/manual_filter_map.rs:37:41
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                                         ^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:38:30
+  --> $DIR/manual_filter_map.rs:39:30
    |
 LL |     iter::<Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:39:31
+  --> $DIR/manual_filter_map.rs:40:31
    |
 LL |     iter::<&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:40:32
+  --> $DIR/manual_filter_map.rs:41:32
    |
 LL |     iter::<&&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:41:31
+  --> $DIR/manual_filter_map.rs:42:31
    |
 LL |     iter::<Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:42:32
+  --> $DIR/manual_filter_map.rs:43:32
    |
 LL |     iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:43:35
+  --> $DIR/manual_filter_map.rs:44:35
    |
 LL |     iter::<&Result<String, ()>>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:44:35
+  --> $DIR/manual_filter_map.rs:45:35
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_filter_map.rs:44:45
+  --> $DIR/manual_filter_map.rs:45:45
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                             ^^^^^^^^^
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:92:10
+  --> $DIR/manual_filter_map.rs:93:10
    |
 LL |           .filter(|f| f.option_field.is_some())
    |  __________^
@@ -182,7 +182,7 @@ LL | |         .map(|f| f.option_field.clone().unwrap());
    | |_________________________________________________^ help: try: `filter_map(|f| f.option_field.clone())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:97:10
+  --> $DIR/manual_filter_map.rs:98:10
    |
 LL |           .filter(|f| f.ref_field.is_some())
    |  __________^
@@ -190,7 +190,7 @@ LL | |         .map(|f| f.ref_field.cloned().unwrap());
    | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.cloned())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:102:10
+  --> $DIR/manual_filter_map.rs:103:10
    |
 LL |           .filter(|f| f.ref_field.is_some())
    |  __________^
@@ -198,7 +198,7 @@ LL | |         .map(|f| f.ref_field.copied().unwrap());
    | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.copied())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:107:10
+  --> $DIR/manual_filter_map.rs:108:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -206,7 +206,7 @@ LL | |         .map(|f| f.result_field.clone().unwrap());
    | |_________________________________________________^ help: try: `filter_map(|f| f.result_field.clone().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:112:10
+  --> $DIR/manual_filter_map.rs:113:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -214,7 +214,7 @@ LL | |         .map(|f| f.result_field.as_ref().unwrap());
    | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_ref().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:117:10
+  --> $DIR/manual_filter_map.rs:118:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -222,7 +222,7 @@ LL | |         .map(|f| f.result_field.as_deref().unwrap());
    | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:122:10
+  --> $DIR/manual_filter_map.rs:123:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -230,7 +230,7 @@ LL | |         .map(|f| f.result_field.as_mut().unwrap());
    | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_mut().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:127:10
+  --> $DIR/manual_filter_map.rs:128:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -238,7 +238,7 @@ LL | |         .map(|f| f.result_field.as_deref_mut().unwrap());
    | |________________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref_mut().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:132:10
+  --> $DIR/manual_filter_map.rs:133:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -246,7 +246,7 @@ LL | |         .map(|f| f.result_field.to_owned().unwrap());
    | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.to_owned().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:145:27
+  --> $DIR/manual_filter_map.rs:146:27
    |
 LL |       let _x = iter.clone().filter(|x| matches!(x, Enum::A(_))).map(|x| match x {
    |  ___________________________^
@@ -256,7 +256,7 @@ LL | |     });
    | |______^ help: try: `filter_map(|x| match x { Enum::A(s) => Some(s), _ => None })`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:155:10
+  --> $DIR/manual_filter_map.rs:156:10
    |
 LL |           .filter(|x| matches!(x, Enum::A(_)))
    |  __________^
diff --git a/src/tools/clippy/tests/ui/manual_find_map.fixed b/src/tools/clippy/tests/ui/manual_find_map.fixed
index 0e92d25e68f..2d9a356b9bc 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_map.fixed
@@ -2,6 +2,7 @@
 #![warn(clippy::manual_find_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
 #![allow(clippy::useless_vec)]
+#![allow(clippy::struct_field_names)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_find_map.rs b/src/tools/clippy/tests/ui/manual_find_map.rs
index b2568c823eb..7c5cc136695 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.rs
+++ b/src/tools/clippy/tests/ui/manual_find_map.rs
@@ -2,6 +2,7 @@
 #![warn(clippy::manual_find_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
 #![allow(clippy::useless_vec)]
+#![allow(clippy::struct_field_names)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_find_map.stderr b/src/tools/clippy/tests/ui/manual_find_map.stderr
index 0dc9ae1df03..0526382323d 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.stderr
+++ b/src/tools/clippy/tests/ui/manual_find_map.stderr
@@ -1,11 +1,11 @@
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:8:19
+  --> $DIR/manual_find_map.rs:9:19
    |
 LL |     let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:8:28
+  --> $DIR/manual_find_map.rs:9:28
    |
 LL |     let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                            ^^^^^^^^^^
@@ -13,31 +13,31 @@ LL |     let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()
    = help: to override `-D warnings` add `#[allow(clippy::manual_find_map)]`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:11:19
+  --> $DIR/manual_find_map.rs:12:19
    |
 LL |     let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:11:29
+  --> $DIR/manual_find_map.rs:12:29
    |
 LL |     let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                             ^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:14:19
+  --> $DIR/manual_find_map.rs:15:19
    |
 LL |     let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:14:29
+  --> $DIR/manual_find_map.rs:15:29
    |
 LL |     let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                             ^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:17:10
+  --> $DIR/manual_find_map.rs:18:10
    |
 LL |           .find(|&x| to_ref(to_opt(x)).is_some())
    |  __________^
@@ -45,13 +45,13 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:17:20
+  --> $DIR/manual_find_map.rs:18:20
    |
 LL |         .find(|&x| to_ref(to_opt(x)).is_some())
    |                    ^^^^^^^^^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:20:10
+  --> $DIR/manual_find_map.rs:21:10
    |
 LL |           .find(|x| to_ref(to_opt(*x)).is_some())
    |  __________^
@@ -59,13 +59,13 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:20:19
+  --> $DIR/manual_find_map.rs:21:19
    |
 LL |         .find(|x| to_ref(to_opt(*x)).is_some())
    |                   ^^^^^^^^^^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:24:10
+  --> $DIR/manual_find_map.rs:25:10
    |
 LL |           .find(|&x| to_ref(to_res(x)).is_ok())
    |  __________^
@@ -73,13 +73,13 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:24:20
+  --> $DIR/manual_find_map.rs:25:20
    |
 LL |         .find(|&x| to_ref(to_res(x)).is_ok())
    |                    ^^^^^^^^^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:27:10
+  --> $DIR/manual_find_map.rs:28:10
    |
 LL |           .find(|x| to_ref(to_res(*x)).is_ok())
    |  __________^
@@ -87,109 +87,109 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:27:19
+  --> $DIR/manual_find_map.rs:28:19
    |
 LL |         .find(|x| to_ref(to_res(*x)).is_ok())
    |                   ^^^^^^^^^^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:33:26
+  --> $DIR/manual_find_map.rs:34:26
    |
 LL |     iter::<Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:34:27
+  --> $DIR/manual_find_map.rs:35:27
    |
 LL |     iter::<&Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| *x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:35:28
+  --> $DIR/manual_find_map.rs:36:28
    |
 LL |     iter::<&&Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| **x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:36:27
+  --> $DIR/manual_find_map.rs:37:27
    |
 LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:37:28
+  --> $DIR/manual_find_map.rs:38:28
    |
 LL |     iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:38:31
+  --> $DIR/manual_find_map.rs:39:31
    |
 LL |     iter::<&Option<String>>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:39:31
+  --> $DIR/manual_find_map.rs:40:31
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:39:41
+  --> $DIR/manual_find_map.rs:40:41
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                                         ^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:41:30
+  --> $DIR/manual_find_map.rs:42:30
    |
 LL |     iter::<Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:42:31
+  --> $DIR/manual_find_map.rs:43:31
    |
 LL |     iter::<&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:43:32
+  --> $DIR/manual_find_map.rs:44:32
    |
 LL |     iter::<&&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:44:31
+  --> $DIR/manual_find_map.rs:45:31
    |
 LL |     iter::<Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:45:32
+  --> $DIR/manual_find_map.rs:46:32
    |
 LL |     iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:46:35
+  --> $DIR/manual_find_map.rs:47:35
    |
 LL |     iter::<&Result<String, ()>>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:47:35
+  --> $DIR/manual_find_map.rs:48:35
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())`
    |
 note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once
-  --> $DIR/manual_find_map.rs:47:45
+  --> $DIR/manual_find_map.rs:48:45
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                             ^^^^^^^^^
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:95:10
+  --> $DIR/manual_find_map.rs:96:10
    |
 LL |           .find(|f| f.option_field.is_some())
    |  __________^
@@ -197,7 +197,7 @@ LL | |         .map(|f| f.option_field.clone().unwrap());
    | |_________________________________________________^ help: try: `find_map(|f| f.option_field.clone())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:100:10
+  --> $DIR/manual_find_map.rs:101:10
    |
 LL |           .find(|f| f.ref_field.is_some())
    |  __________^
@@ -205,7 +205,7 @@ LL | |         .map(|f| f.ref_field.cloned().unwrap());
    | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:105:10
+  --> $DIR/manual_find_map.rs:106:10
    |
 LL |           .find(|f| f.ref_field.is_some())
    |  __________^
@@ -213,7 +213,7 @@ LL | |         .map(|f| f.ref_field.copied().unwrap());
    | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.copied())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:110:10
+  --> $DIR/manual_find_map.rs:111:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -221,7 +221,7 @@ LL | |         .map(|f| f.result_field.clone().unwrap());
    | |_________________________________________________^ help: try: `find_map(|f| f.result_field.clone().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:115:10
+  --> $DIR/manual_find_map.rs:116:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -229,7 +229,7 @@ LL | |         .map(|f| f.result_field.as_ref().unwrap());
    | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_ref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:120:10
+  --> $DIR/manual_find_map.rs:121:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -237,7 +237,7 @@ LL | |         .map(|f| f.result_field.as_deref().unwrap());
    | |____________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:125:10
+  --> $DIR/manual_find_map.rs:126:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -245,7 +245,7 @@ LL | |         .map(|f| f.result_field.as_mut().unwrap());
    | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_mut().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:130:10
+  --> $DIR/manual_find_map.rs:131:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -253,7 +253,7 @@ LL | |         .map(|f| f.result_field.as_deref_mut().unwrap());
    | |________________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref_mut().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:135:10
+  --> $DIR/manual_find_map.rs:136:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
index 5be2dd280b8..9c4bd335ad8 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
@@ -33,6 +33,7 @@ fn msrv_1_23() {
     assert!(matches!(b'1', b'0'..=b'9'));
     assert!(matches!('X', 'A'..='Z'));
     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
 }
 
 #[clippy::msrv = "1.24"]
@@ -40,14 +41,17 @@ fn msrv_1_24() {
     assert!(b'1'.is_ascii_digit());
     assert!('X'.is_ascii_uppercase());
     assert!('x'.is_ascii_alphabetic());
+    assert!('x'.is_ascii_hexdigit());
 }
 
 #[clippy::msrv = "1.46"]
 fn msrv_1_46() {
     const FOO: bool = matches!('x', '0'..='9');
+    const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
 }
 
 #[clippy::msrv = "1.47"]
 fn msrv_1_47() {
     const FOO: bool = 'x'.is_ascii_digit();
+    const BAR: bool = 'x'.is_ascii_hexdigit();
 }
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
index f9249e22a02..785943cd24d 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
@@ -33,6 +33,7 @@ fn msrv_1_23() {
     assert!(matches!(b'1', b'0'..=b'9'));
     assert!(matches!('X', 'A'..='Z'));
     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
 }
 
 #[clippy::msrv = "1.24"]
@@ -40,14 +41,17 @@ fn msrv_1_24() {
     assert!(matches!(b'1', b'0'..=b'9'));
     assert!(matches!('X', 'A'..='Z'));
     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
 }
 
 #[clippy::msrv = "1.46"]
 fn msrv_1_46() {
     const FOO: bool = matches!('x', '0'..='9');
+    const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
 }
 
 #[clippy::msrv = "1.47"]
 fn msrv_1_47() {
     const FOO: bool = matches!('x', '0'..='9');
+    const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
 }
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
index e0fb46e59fa..f69522c5ff8 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
@@ -98,28 +98,40 @@ LL |     ('A'..='Z').contains(cool_letter);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:40:13
+  --> $DIR/manual_is_ascii_check.rs:41:13
    |
 LL |     assert!(matches!(b'1', b'0'..=b'9'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:41:13
+  --> $DIR/manual_is_ascii_check.rs:42:13
    |
 LL |     assert!(matches!('X', 'A'..='Z'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:42:13
+  --> $DIR/manual_is_ascii_check.rs:43:13
    |
 LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:52:23
+  --> $DIR/manual_is_ascii_check.rs:44:13
+   |
+LL |     assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:55:23
    |
 LL |     const FOO: bool = matches!('x', '0'..='9');
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
 
-error: aborting due to 20 previous errors
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:56:23
+   |
+LL |     const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()`
+
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/map_identity.fixed b/src/tools/clippy/tests/ui/map_identity.fixed
index cc40b162058..e756d9b5935 100644
--- a/src/tools/clippy/tests/ui/map_identity.fixed
+++ b/src/tools/clippy/tests/ui/map_identity.fixed
@@ -17,6 +17,9 @@ fn main() {
     });
     let _: Result<u32, u32> = Ok(1);
     let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
+    // : u32 guides type inference
+    let _ = Ok(1).map_err(|a: u32| a);
+    let _ = Ok(1).map_err(std::convert::identity::<u32>);
 }
 
 fn not_identity(x: &u16) -> u16 {
diff --git a/src/tools/clippy/tests/ui/map_identity.rs b/src/tools/clippy/tests/ui/map_identity.rs
index 97a91aea6dc..74cbaade405 100644
--- a/src/tools/clippy/tests/ui/map_identity.rs
+++ b/src/tools/clippy/tests/ui/map_identity.rs
@@ -19,6 +19,9 @@ fn main() {
     });
     let _: Result<u32, u32> = Ok(1).map_err(|a| a);
     let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42);
+    // : u32 guides type inference
+    let _ = Ok(1).map_err(|a: u32| a);
+    let _ = Ok(1).map_err(std::convert::identity::<u32>);
 }
 
 fn not_identity(x: &u16) -> u16 {
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.rs b/src/tools/clippy/tests/ui/min_ident_chars.rs
index 030863ca0d3..f99c35d5c57 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.rs
+++ b/src/tools/clippy/tests/ui/min_ident_chars.rs
@@ -1,5 +1,6 @@
 //@aux-build:proc_macros.rs
 #![allow(irrefutable_let_patterns, nonstandard_style, unused)]
+#![allow(clippy::struct_field_names)]
 #![warn(clippy::min_ident_chars)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr
index 253636cf91d..e4181157ea2 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.stderr
+++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr
@@ -1,5 +1,5 @@
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:8:8
+  --> $DIR/min_ident_chars.rs:9:8
    |
 LL | struct A {
    |        ^
@@ -8,169 +8,169 @@ LL | struct A {
    = help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]`
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:9:5
+  --> $DIR/min_ident_chars.rs:10:5
    |
 LL |     a: u32,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:11:5
+  --> $DIR/min_ident_chars.rs:12:5
    |
 LL |     A: u32,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:12:5
+  --> $DIR/min_ident_chars.rs:13:5
    |
 LL |     I: u32,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:15:8
+  --> $DIR/min_ident_chars.rs:16:8
    |
 LL | struct B(u32);
    |        ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:17:8
+  --> $DIR/min_ident_chars.rs:18:8
    |
 LL | struct O {
    |        ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:18:5
+  --> $DIR/min_ident_chars.rs:19:5
    |
 LL |     o: u32,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:23:6
+  --> $DIR/min_ident_chars.rs:24:6
    |
 LL | enum C {
    |      ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:24:5
+  --> $DIR/min_ident_chars.rs:25:5
    |
 LL |     D,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:25:5
+  --> $DIR/min_ident_chars.rs:26:5
    |
 LL |     E,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:26:5
+  --> $DIR/min_ident_chars.rs:27:5
    |
 LL |     F,
    |     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:50:9
+  --> $DIR/min_ident_chars.rs:51:9
    |
 LL |     let h = 1;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:51:9
+  --> $DIR/min_ident_chars.rs:52:9
    |
 LL |     let e = 2;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:52:9
+  --> $DIR/min_ident_chars.rs:53:9
    |
 LL |     let l = 3;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:53:9
+  --> $DIR/min_ident_chars.rs:54:9
    |
 LL |     let l = 4;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:54:9
+  --> $DIR/min_ident_chars.rs:55:9
    |
 LL |     let o = 6;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:58:10
+  --> $DIR/min_ident_chars.rs:59:10
    |
 LL |     let (h, o, w) = (1, 2, 3);
    |          ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:58:13
+  --> $DIR/min_ident_chars.rs:59:13
    |
 LL |     let (h, o, w) = (1, 2, 3);
    |             ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:59:10
+  --> $DIR/min_ident_chars.rs:60:10
    |
 LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
    |          ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:59:14
+  --> $DIR/min_ident_chars.rs:60:14
    |
 LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
    |              ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:59:17
+  --> $DIR/min_ident_chars.rs:60:17
    |
 LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
    |                 ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:61:16
+  --> $DIR/min_ident_chars.rs:62:16
    |
 LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
    |                ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:61:19
+  --> $DIR/min_ident_chars.rs:62:19
    |
 LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
    |                   ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:61:29
+  --> $DIR/min_ident_chars.rs:62:29
    |
 LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
    |                             ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:65:9
+  --> $DIR/min_ident_chars.rs:66:9
    |
 LL |     let o = 1;
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:66:9
+  --> $DIR/min_ident_chars.rs:67:9
    |
 LL |     let o = O { o };
    |         ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:80:4
+  --> $DIR/min_ident_chars.rs:81:4
    |
 LL | fn b() {}
    |    ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:81:21
+  --> $DIR/min_ident_chars.rs:82:21
    |
 LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
    |                     ^
 
 error: this ident consists of a single char
-  --> $DIR/min_ident_chars.rs:81:29
+  --> $DIR/min_ident_chars.rs:82:29
    |
 LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
    |                             ^
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.fixed b/src/tools/clippy/tests/ui/misnamed_getters.fixed
index 2a7a2067ee0..70af604b214 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.fixed
+++ b/src/tools/clippy/tests/ui/misnamed_getters.fixed
@@ -1,4 +1,5 @@
 #![allow(unused)]
+#![allow(clippy::struct_field_names)]
 #![warn(clippy::misnamed_getters)]
 
 struct A {
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.rs b/src/tools/clippy/tests/ui/misnamed_getters.rs
index 56ddc46c4d4..23c3e7bc5cf 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.rs
+++ b/src/tools/clippy/tests/ui/misnamed_getters.rs
@@ -1,4 +1,5 @@
 #![allow(unused)]
+#![allow(clippy::struct_field_names)]
 #![warn(clippy::misnamed_getters)]
 
 struct A {
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.stderr b/src/tools/clippy/tests/ui/misnamed_getters.stderr
index aadec654908..120a3f3112e 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.stderr
+++ b/src/tools/clippy/tests/ui/misnamed_getters.stderr
@@ -1,5 +1,5 @@
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:11:5
+  --> $DIR/misnamed_getters.rs:12:5
    |
 LL | /     fn a(&self) -> &u8 {
 LL | |
@@ -13,7 +13,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::misnamed_getters)]`
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:16:5
+  --> $DIR/misnamed_getters.rs:17:5
    |
 LL | /     fn a_mut(&mut self) -> &mut u8 {
 LL | |
@@ -23,7 +23,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:21:5
+  --> $DIR/misnamed_getters.rs:22:5
    |
 LL | /     fn b(self) -> u8 {
 LL | |
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:26:5
+  --> $DIR/misnamed_getters.rs:27:5
    |
 LL | /     fn b_mut(&mut self) -> &mut u8 {
 LL | |
@@ -43,7 +43,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:31:5
+  --> $DIR/misnamed_getters.rs:32:5
    |
 LL | /     fn c(&self) -> &u8 {
 LL | |
@@ -53,7 +53,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:36:5
+  --> $DIR/misnamed_getters.rs:37:5
    |
 LL | /     fn c_mut(&mut self) -> &mut u8 {
 LL | |
@@ -63,7 +63,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:48:5
+  --> $DIR/misnamed_getters.rs:49:5
    |
 LL | /     unsafe fn a(&self) -> &u8 {
 LL | |
@@ -73,7 +73,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:52:5
+  --> $DIR/misnamed_getters.rs:53:5
    |
 LL | /     unsafe fn a_mut(&mut self) -> &mut u8 {
 LL | |
@@ -83,7 +83,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:57:5
+  --> $DIR/misnamed_getters.rs:58:5
    |
 LL | /     unsafe fn b(self) -> u8 {
 LL | |
@@ -93,7 +93,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:62:5
+  --> $DIR/misnamed_getters.rs:63:5
    |
 LL | /     unsafe fn b_mut(&mut self) -> &mut u8 {
 LL | |
@@ -103,7 +103,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:75:5
+  --> $DIR/misnamed_getters.rs:76:5
    |
 LL | /     unsafe fn a_unchecked(&self) -> &u8 {
 LL | |
@@ -113,7 +113,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:79:5
+  --> $DIR/misnamed_getters.rs:80:5
    |
 LL | /     unsafe fn a_unchecked_mut(&mut self) -> &mut u8 {
 LL | |
@@ -123,7 +123,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:84:5
+  --> $DIR/misnamed_getters.rs:85:5
    |
 LL | /     unsafe fn b_unchecked(self) -> u8 {
 LL | |
@@ -133,7 +133,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:89:5
+  --> $DIR/misnamed_getters.rs:90:5
    |
 LL | /     unsafe fn b_unchecked_mut(&mut self) -> &mut u8 {
 LL | |
@@ -143,7 +143,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:122:5
+  --> $DIR/misnamed_getters.rs:123:5
    |
 LL | /     fn a(&self) -> &u8 {
 LL | |
@@ -153,7 +153,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:126:5
+  --> $DIR/misnamed_getters.rs:127:5
    |
 LL | /     fn a_mut(&mut self) -> &mut u8 {
 LL | |
@@ -163,7 +163,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:131:5
+  --> $DIR/misnamed_getters.rs:132:5
    |
 LL | /     fn d(&self) -> &u8 {
 LL | |
@@ -173,7 +173,7 @@ LL | |     }
    | |_____^
 
 error: getter function appears to return the wrong field
-  --> $DIR/misnamed_getters.rs:135:5
+  --> $DIR/misnamed_getters.rs:136:5
    |
 LL | /     fn d_mut(&mut self) -> &mut u8 {
 LL | |
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 4ef6f0ca92f..8afb4df20af 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -147,4 +147,11 @@ fn _field_fn_ptr(x: unsafe fn()) {
     }
 }
 
+// await expands to an unsafe block with several operations, but this is fine.: #11312
+async fn await_desugaring_silent() {
+    async fn helper() {}
+
+    helper().await;
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index c9ea831f8b2..3059de8f89c 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -7,7 +7,8 @@
     clippy::equatable_if_let,
     clippy::needless_if,
     clippy::needless_return,
-    clippy::self_named_constructors
+    clippy::self_named_constructors,
+    clippy::struct_field_names
 )]
 
 use std::cell::Cell;
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index b83d9c3f209..b2cbe86e223 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -7,7 +7,8 @@
     clippy::equatable_if_let,
     clippy::needless_if,
     clippy::needless_return,
-    clippy::self_named_constructors
+    clippy::self_named_constructors,
+    clippy::struct_field_names
 )]
 
 use std::cell::Cell;
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index 2b189c89851..72b0670c95b 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -1,5 +1,5 @@
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:40:5
+  --> $DIR/fixable.rs:41:5
    |
 LL | /     if x {
 LL | |         true
@@ -12,7 +12,7 @@ LL | |     };
    = help: to override `-D warnings` add `#[allow(clippy::needless_bool)]`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:45:5
+  --> $DIR/fixable.rs:46:5
    |
 LL | /     if x {
 LL | |         false
@@ -22,7 +22,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:50:5
+  --> $DIR/fixable.rs:51:5
    |
 LL | /     if x && y {
 LL | |         false
@@ -32,7 +32,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!(x && y)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:58:5
+  --> $DIR/fixable.rs:59:5
    |
 LL | /     if a == b {
 LL | |         false
@@ -42,7 +42,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a != b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:63:5
+  --> $DIR/fixable.rs:64:5
    |
 LL | /     if a != b {
 LL | |         false
@@ -52,7 +52,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a == b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:68:5
+  --> $DIR/fixable.rs:69:5
    |
 LL | /     if a < b {
 LL | |         false
@@ -62,7 +62,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a >= b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:73:5
+  --> $DIR/fixable.rs:74:5
    |
 LL | /     if a <= b {
 LL | |         false
@@ -72,7 +72,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a > b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:78:5
+  --> $DIR/fixable.rs:79:5
    |
 LL | /     if a > b {
 LL | |         false
@@ -82,7 +82,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a <= b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:83:5
+  --> $DIR/fixable.rs:84:5
    |
 LL | /     if a >= b {
 LL | |         false
@@ -92,7 +92,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a < b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:111:5
+  --> $DIR/fixable.rs:112:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -102,7 +102,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:119:5
+  --> $DIR/fixable.rs:120:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -112,7 +112,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:127:5
+  --> $DIR/fixable.rs:128:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -122,7 +122,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:135:5
+  --> $DIR/fixable.rs:136:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -132,7 +132,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:143:8
+  --> $DIR/fixable.rs:144:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -141,25 +141,25 @@ LL |     if x == true {};
    = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:147:8
+  --> $DIR/fixable.rs:148:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:157:8
+  --> $DIR/fixable.rs:158:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:158:8
+  --> $DIR/fixable.rs:159:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:167:12
+  --> $DIR/fixable.rs:168:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
@@ -170,7 +170,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `{ !returns_bool() }`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:180:5
+  --> $DIR/fixable.rs:181:5
    |
 LL | /     if unsafe { no(4) } & 1 != 0 {
 LL | |         true
@@ -180,13 +180,13 @@ LL | |     };
    | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:185:30
+  --> $DIR/fixable.rs:186:30
    |
 LL |     let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:188:9
+  --> $DIR/fixable.rs:189:9
    |
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
index 39d76f99900..ea5e74c4c00 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
@@ -270,6 +270,38 @@ pub async fn closure4(n: &mut usize) {
     })();
 }
 
+// Should not warn.
+async fn _f(v: &mut Vec<()>) {
+    let x = || v.pop();
+    _ = || || x;
+}
+
+struct Data<T: ?Sized> {
+    value: T,
+}
+// Unsafe functions should not warn.
+unsafe fn get_mut_unchecked<T>(ptr: &mut NonNull<Data<T>>) -> &mut T {
+    &mut (*ptr.as_ptr()).value
+}
+// Unsafe blocks should not warn.
+fn get_mut_unchecked2<T>(ptr: &mut NonNull<Data<T>>) -> &mut T {
+    unsafe { &mut (*ptr.as_ptr()).value }
+}
+
+fn set_true(b: &mut bool) {
+    *b = true;
+}
+
+// Should not warn.
+fn true_setter(b: &mut bool) -> impl FnOnce() + '_ {
+    move || set_true(b)
+}
+
+// Should not warn.
+fn filter_copy<T: Copy>(predicate: &mut impl FnMut(T) -> bool) -> impl FnMut(&T) -> bool + '_ {
+    move |&item| predicate(item)
+}
+
 fn main() {
     let mut u = 0;
     let mut v = vec![0];
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index e81db300f15..182d067a5e9 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -117,6 +117,14 @@ fn macros() {
         let x = 1;
         let x = x;
     }
+
+    let x = 10;
+    macro_rules! rebind_outer_macro {
+        ($x:ident) => {
+            let x = x;
+        };
+    }
+    rebind_outer_macro!(y);
 }
 
 struct WithDrop(usize);
diff --git a/src/tools/clippy/tests/ui/redundant_locals.stderr b/src/tools/clippy/tests/ui/redundant_locals.stderr
index d794a87fe7d..30ab4aa2ea9 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.stderr
+++ b/src/tools/clippy/tests/ui/redundant_locals.stderr
@@ -157,13 +157,13 @@ LL |     let x = 1;
    |         ^
 
 error: redundant redefinition of a binding `a`
-  --> $DIR/redundant_locals.rs:144:5
+  --> $DIR/redundant_locals.rs:152:5
    |
 LL |     let a = a;
    |     ^^^^^^^^^^
    |
 help: `a` is initially defined here
-  --> $DIR/redundant_locals.rs:142:9
+  --> $DIR/redundant_locals.rs:150:9
    |
 LL |     let a = WithoutDrop(1);
    |         ^
diff --git a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.rs b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.rs
index e25609f7560..51fe346d092 100644
--- a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.rs
+++ b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::rest_pat_in_fully_bound_structs)]
+#![allow(clippy::struct_field_names)]
 
 struct A {
     a: i32,
diff --git a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
index 2c221b4dbb2..a62f1d0b65f 100644
--- a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
+++ b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
@@ -1,5 +1,5 @@
 error: unnecessary use of `..` pattern in struct binding. All fields were already bound
-  --> $DIR/rest_pat_in_fully_bound_structs.rs:22:9
+  --> $DIR/rest_pat_in_fully_bound_structs.rs:23:9
    |
 LL |         A { a: 5, b: 42, c: "", .. } => {}, // Lint
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |         A { a: 5, b: 42, c: "", .. } => {}, // Lint
    = help: to override `-D warnings` add `#[allow(clippy::rest_pat_in_fully_bound_structs)]`
 
 error: unnecessary use of `..` pattern in struct binding. All fields were already bound
-  --> $DIR/rest_pat_in_fully_bound_structs.rs:24:9
+  --> $DIR/rest_pat_in_fully_bound_structs.rs:25:9
    |
 LL |         A { a: 0, b: 0, c: "", .. } => {}, // Lint
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |         A { a: 0, b: 0, c: "", .. } => {}, // Lint
    = help: consider removing `..` from this binding
 
 error: unnecessary use of `..` pattern in struct binding. All fields were already bound
-  --> $DIR/rest_pat_in_fully_bound_structs.rs:31:9
+  --> $DIR/rest_pat_in_fully_bound_structs.rs:32:9
    |
 LL |         A { a: 0, b: 0, c: "", .. } => {}, // Lint
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/struct_fields.rs b/src/tools/clippy/tests/ui/struct_fields.rs
new file mode 100644
index 00000000000..8b1a1446e3c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/struct_fields.rs
@@ -0,0 +1,331 @@
+//@aux-build:proc_macros.rs
+
+#![warn(clippy::struct_field_names)]
+#![allow(unused)]
+
+#[macro_use]
+extern crate proc_macros;
+
+struct Data1 {
+    field_data1: u8,
+    //~^ ERROR: field name ends with the struct's name
+    another: u8,
+    foo: u8,
+    bar: u8,
+}
+
+struct Data2 {
+    another: u8,
+    foo: u8,
+    data2_field: u8,
+    //~^ ERROR: field name starts with the struct's name
+    bar: u8,
+}
+
+struct StructData {
+    //~^ ERROR: all fields have the same postfix: `data`
+    movable_data: u8,
+    fixed_data: u8,
+    invisible_data: u8,
+}
+
+struct DataStruct {
+    //~^ ERROR: all fields have the same prefix: `data`
+    data_movable: u8,
+    data_fixed: u8,
+    data_invisible: u8,
+}
+
+struct DoublePrefix {
+    //~^ ERROR: all fields have the same prefix: `some_data`
+    some_data_a: bool,
+    some_data_b: bool,
+    some_data_c: bool,
+}
+
+struct DoublePostfix {
+    //~^ ERROR: all fields have the same postfix: `some_data`
+    a_some_data: bool,
+    b_some_data: bool,
+    c_some_data: bool,
+}
+
+#[allow(non_snake_case)]
+struct NotSnakeCase {
+    //~^ ERROR: all fields have the same postfix: `someData`
+    a_someData: bool,
+    b_someData: bool,
+    c_someData: bool,
+}
+#[allow(non_snake_case)]
+struct NotSnakeCase2 {
+    //~^ ERROR: all fields have the same prefix: `someData`
+    someData_c: bool,
+    someData_b: bool,
+    someData_a_b: bool,
+}
+
+// no error, threshold is 3 fiels by default
+struct Fooo {
+    foo: u8,
+    bar: u8,
+}
+
+struct NonCaps {
+    //~^ ERROR: all fields have the same prefix: `prefix`
+    prefix_çš„: u8,
+    prefix_tea: u8,
+    prefix_cake: u8,
+}
+
+// should not lint
+#[allow(clippy::struct_field_names)]
+pub mod allowed {
+    pub struct PubAllowed {
+        some_this: u8,
+        some_that: u8,
+        some_other_what: u8,
+    }
+}
+
+// should not lint
+struct SomeData {
+    foo: u8,
+    bar: bool,
+    path: u8,
+    answer: u8,
+}
+
+// should not lint
+pub struct NetworkLayer {
+    layer1: Vec<u8>,
+    layer2: Vec<u8>,
+    layer3: Vec<u8>,
+    layer4: Vec<u8>,
+}
+
+//should not lint
+struct North {
+    normal: u8,
+    no_left: u8,
+    no_right: u8,
+}
+
+mod issue8324_from_enum_variant_names {
+    // 8324: enum_variant_names warns even if removing the suffix would leave an empty string
+    struct Phase {
+        pre_lookup: u8,
+        lookup: u8,
+        post_lookup: u8,
+    }
+}
+
+mod issue9018_from_enum_variant_names {
+    struct DoLint {
+        //~^ ERROR: all fields have the same prefix: `_type`
+        _type_create: u8,
+        _type_read: u8,
+        _type_update: u8,
+        _type_destroy: u8,
+    }
+
+    struct DoLint2 {
+        //~^ ERROR: all fields have the same prefix: `__type`
+        __type_create: u8,
+        __type_read: u8,
+        __type_update: u8,
+        __type_destroy: u8,
+    }
+
+    struct DoLint3 {
+        //~^ ERROR: all fields have the same prefix: `___type`
+        ___type_create: u8,
+        ___type_read: u8,
+        ___type_update: u8,
+        ___type_destroy: u8,
+    }
+
+    struct DoLint4 {
+        //~^ ERROR: all fields have the same postfix: `_`
+        create_: u8,
+        read_: u8,
+        update_: u8,
+        destroy_: u8,
+    }
+
+    struct DoLint5 {
+        //~^ ERROR: all fields have the same postfix: `__`
+        create__: u8,
+        read__: u8,
+        update__: u8,
+        destroy__: u8,
+    }
+
+    struct DoLint6 {
+        //~^ ERROR: all fields have the same postfix: `___`
+        create___: u8,
+        read___: u8,
+        update___: u8,
+        destroy___: u8,
+    }
+
+    struct DoLintToo {
+        //~^ ERROR: all fields have the same postfix: `type`
+        _create_type: u8,
+        _update_type: u8,
+        _delete_type: u8,
+    }
+
+    struct DoNotLint {
+        _foo: u8,
+        _bar: u8,
+        _baz: u8,
+    }
+
+    struct DoNotLint2 {
+        __foo: u8,
+        __bar: u8,
+        __baz: u8,
+    }
+}
+
+mod allow_attributes_on_fields {
+    struct Struct {
+        #[allow(clippy::struct_field_names)]
+        struct_starts_with: u8,
+        #[allow(clippy::struct_field_names)]
+        ends_with_struct: u8,
+        foo: u8,
+    }
+}
+
+// food field should not lint
+struct Foo {
+    food: i32,
+    a: i32,
+    b: i32,
+}
+
+struct Proxy {
+    proxy: i32,
+    //~^ ERROR: field name starts with the struct's name
+    unrelated1: bool,
+    unrelated2: bool,
+}
+
+// should not lint
+pub struct RegexT {
+    __buffer: i32,
+    __allocated: i32,
+    __used: i32,
+}
+
+mod macro_tests {
+    macro_rules! mk_struct {
+        () => {
+            struct MacroStruct {
+                some_a: i32,
+                some_b: i32,
+                some_c: i32,
+            }
+        };
+    }
+    mk_struct!();
+    //~^ ERROR: all fields have the same prefix: `some`
+
+    macro_rules! mk_struct2 {
+        () => {
+            struct Macrobaz {
+                macrobaz_a: i32,
+                some_b: i32,
+                some_c: i32,
+            }
+        };
+    }
+    mk_struct2!();
+    //~^ ERROR: field name starts with the struct's name
+
+    macro_rules! mk_struct_with_names {
+        ($struct_name:ident, $field:ident) => {
+            struct $struct_name {
+                $field: i32,
+                other_something: i32,
+                other_field: i32,
+            }
+        };
+    }
+    // expands to `struct Foo { foo: i32, ... }`
+    mk_struct_with_names!(Foo, foo);
+    //~^ ERROR: field name starts with the struct's name
+
+    // expands to a struct with all fields starting with `other` but should not
+    // be linted because some fields come from the macro definition and the other from the input
+    mk_struct_with_names!(Some, other_data);
+
+    // should not lint when names come from different places
+    macro_rules! mk_struct_with_field_name {
+        ($field_name:ident) => {
+            struct Baz {
+                one: i32,
+                two: i32,
+                $field_name: i32,
+            }
+        };
+    }
+    mk_struct_with_field_name!(baz_three);
+
+    // should not lint when names come from different places
+    macro_rules! mk_struct_with_field_name {
+        ($field_name:ident) => {
+            struct Bazilisk {
+                baz_one: i32,
+                baz_two: i32,
+                $field_name: i32,
+            }
+        };
+    }
+    mk_struct_with_field_name!(baz_three);
+
+    macro_rules! mk_struct_full_def {
+        ($struct_name:ident, $field1:ident, $field2:ident, $field3:ident) => {
+            struct $struct_name {
+                $field1: i32,
+                $field2: i32,
+                $field3: i32,
+            }
+        };
+    }
+    mk_struct_full_def!(PrefixData, some_data, some_meta, some_other);
+    //~^ ERROR: all fields have the same prefix: `some`
+}
+
+// should not lint on external code
+external! {
+    struct DataExternal {
+        field_data1: u8,
+        another: u8,
+        foo: u8,
+        bar: u8,
+    }
+
+    struct NotSnakeCaseExternal {
+        someData_c: bool,
+        someData_b: bool,
+        someData_a_b: bool,
+    }
+
+    struct DoublePrefixExternal {
+        some_data_a: bool,
+        some_data_b: bool,
+        some_data_c: bool,
+    }
+
+    struct StructDataExternal {
+        movable_data: u8,
+        fixed_data: u8,
+        invisible_data: u8,
+    }
+
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/struct_fields.stderr b/src/tools/clippy/tests/ui/struct_fields.stderr
new file mode 100644
index 00000000000..4ca57715b18
--- /dev/null
+++ b/src/tools/clippy/tests/ui/struct_fields.stderr
@@ -0,0 +1,265 @@
+error: field name ends with the struct's name
+  --> $DIR/struct_fields.rs:10:5
+   |
+LL |     field_data1: u8,
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::struct-field-names` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::struct_field_names)]`
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:20:5
+   |
+LL |     data2_field: u8,
+   |     ^^^^^^^^^^^^^^^
+
+error: all fields have the same postfix: `data`
+  --> $DIR/struct_fields.rs:25:1
+   |
+LL | / struct StructData {
+LL | |
+LL | |     movable_data: u8,
+LL | |     fixed_data: u8,
+LL | |     invisible_data: u8,
+LL | | }
+   | |_^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same prefix: `data`
+  --> $DIR/struct_fields.rs:32:1
+   |
+LL | / struct DataStruct {
+LL | |
+LL | |     data_movable: u8,
+LL | |     data_fixed: u8,
+LL | |     data_invisible: u8,
+LL | | }
+   | |_^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same prefix: `some_data`
+  --> $DIR/struct_fields.rs:39:1
+   |
+LL | / struct DoublePrefix {
+LL | |
+LL | |     some_data_a: bool,
+LL | |     some_data_b: bool,
+LL | |     some_data_c: bool,
+LL | | }
+   | |_^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same postfix: `some_data`
+  --> $DIR/struct_fields.rs:46:1
+   |
+LL | / struct DoublePostfix {
+LL | |
+LL | |     a_some_data: bool,
+LL | |     b_some_data: bool,
+LL | |     c_some_data: bool,
+LL | | }
+   | |_^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same postfix: `someData`
+  --> $DIR/struct_fields.rs:54:1
+   |
+LL | / struct NotSnakeCase {
+LL | |
+LL | |     a_someData: bool,
+LL | |     b_someData: bool,
+LL | |     c_someData: bool,
+LL | | }
+   | |_^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same prefix: `someData`
+  --> $DIR/struct_fields.rs:61:1
+   |
+LL | / struct NotSnakeCase2 {
+LL | |
+LL | |     someData_c: bool,
+LL | |     someData_b: bool,
+LL | |     someData_a_b: bool,
+LL | | }
+   | |_^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same prefix: `prefix`
+  --> $DIR/struct_fields.rs:74:1
+   |
+LL | / struct NonCaps {
+LL | |
+LL | |     prefix_çš„: u8,
+LL | |     prefix_tea: u8,
+LL | |     prefix_cake: u8,
+LL | | }
+   | |_^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same prefix: `_type`
+  --> $DIR/struct_fields.rs:124:5
+   |
+LL | /     struct DoLint {
+LL | |
+LL | |         _type_create: u8,
+LL | |         _type_read: u8,
+LL | |         _type_update: u8,
+LL | |         _type_destroy: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same prefix: `__type`
+  --> $DIR/struct_fields.rs:132:5
+   |
+LL | /     struct DoLint2 {
+LL | |
+LL | |         __type_create: u8,
+LL | |         __type_read: u8,
+LL | |         __type_update: u8,
+LL | |         __type_destroy: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same prefix: `___type`
+  --> $DIR/struct_fields.rs:140:5
+   |
+LL | /     struct DoLint3 {
+LL | |
+LL | |         ___type_create: u8,
+LL | |         ___type_read: u8,
+LL | |         ___type_update: u8,
+LL | |         ___type_destroy: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the prefixes
+
+error: all fields have the same postfix: `_`
+  --> $DIR/struct_fields.rs:148:5
+   |
+LL | /     struct DoLint4 {
+LL | |
+LL | |         create_: u8,
+LL | |         read_: u8,
+LL | |         update_: u8,
+LL | |         destroy_: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same postfix: `__`
+  --> $DIR/struct_fields.rs:156:5
+   |
+LL | /     struct DoLint5 {
+LL | |
+LL | |         create__: u8,
+LL | |         read__: u8,
+LL | |         update__: u8,
+LL | |         destroy__: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same postfix: `___`
+  --> $DIR/struct_fields.rs:164:5
+   |
+LL | /     struct DoLint6 {
+LL | |
+LL | |         create___: u8,
+LL | |         read___: u8,
+LL | |         update___: u8,
+LL | |         destroy___: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the postfixes
+
+error: all fields have the same postfix: `type`
+  --> $DIR/struct_fields.rs:172:5
+   |
+LL | /     struct DoLintToo {
+LL | |
+LL | |         _create_type: u8,
+LL | |         _update_type: u8,
+LL | |         _delete_type: u8,
+LL | |     }
+   | |_____^
+   |
+   = help: remove the postfixes
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:210:5
+   |
+LL |     proxy: i32,
+   |     ^^^^^^^^^^
+
+error: all fields have the same prefix: `some`
+  --> $DIR/struct_fields.rs:226:13
+   |
+LL | /             struct MacroStruct {
+LL | |                 some_a: i32,
+LL | |                 some_b: i32,
+LL | |                 some_c: i32,
+LL | |             }
+   | |_____________^
+...
+LL |       mk_struct!();
+   |       ------------ in this macro invocation
+   |
+   = help: remove the prefixes
+   = note: this error originates in the macro `mk_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:239:17
+   |
+LL |                 macrobaz_a: i32,
+   |                 ^^^^^^^^^^^^^^^
+...
+LL |     mk_struct2!();
+   |     ------------- in this macro invocation
+   |
+   = note: this error originates in the macro `mk_struct2` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:251:17
+   |
+LL |                 $field: i32,
+   |                 ^^^^^^^^^^^
+...
+LL |     mk_struct_with_names!(Foo, foo);
+   |     ------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `mk_struct_with_names` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: all fields have the same prefix: `some`
+  --> $DIR/struct_fields.rs:291:13
+   |
+LL | /             struct $struct_name {
+LL | |                 $field1: i32,
+LL | |                 $field2: i32,
+LL | |                 $field3: i32,
+LL | |             }
+   | |_____________^
+...
+LL |       mk_struct_full_def!(PrefixData, some_data, some_meta, some_other);
+   |       ----------------------------------------------------------------- in this macro invocation
+   |
+   = help: remove the prefixes
+   = note: this error originates in the macro `mk_struct_full_def` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 21 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index 304e7b7fd7f..4778eaefdbd 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -5,6 +5,7 @@
 #![allow(clippy::map_identity)]
 #![allow(clippy::needless_borrow)]
 #![allow(clippy::unnecessary_literal_unwrap)]
+#![allow(clippy::unit_arg)]
 
 use std::ops::Deref;
 
@@ -76,6 +77,8 @@ fn main() {
     let _ = opt.ok_or(2);
     let _ = nested_tuple_opt.unwrap_or(Some((1, 2)));
     let _ = cond.then_some(astronomers_pi);
+    let _ = true.then_some({});
+    let _ = true.then_some({});
 
     // Should lint - Builtin deref
     let r = &1;
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index ddfa6bb3ef6..d4b7fd31b1b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -5,6 +5,7 @@
 #![allow(clippy::map_identity)]
 #![allow(clippy::needless_borrow)]
 #![allow(clippy::unnecessary_literal_unwrap)]
+#![allow(clippy::unit_arg)]
 
 use std::ops::Deref;
 
@@ -76,6 +77,8 @@ fn main() {
     let _ = opt.ok_or_else(|| 2);
     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
     let _ = cond.then(|| astronomers_pi);
+    let _ = true.then(|| -> _ {});
+    let _ = true.then(|| {});
 
     // Should lint - Builtin deref
     let r = &1;
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
index 4f1ca374872..1b0db4759bb 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:68:13
+  --> $DIR/unnecessary_lazy_eval.rs:69:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
    |             ^^^^--------------------
@@ -10,7 +10,7 @@ LL |     let _ = opt.unwrap_or_else(|| 2);
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:69:13
+  --> $DIR/unnecessary_lazy_eval.rs:70:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |             ^^^^---------------------------------
@@ -18,7 +18,7 @@ LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:70:13
+  --> $DIR/unnecessary_lazy_eval.rs:71:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |             ^^^^-------------------------------------
@@ -26,7 +26,7 @@ LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:72:13
+  --> $DIR/unnecessary_lazy_eval.rs:73:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
    |             ^^^^---------------------
@@ -34,7 +34,7 @@ LL |     let _ = opt.and_then(|_| ext_opt);
    |                 help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:73:13
+  --> $DIR/unnecessary_lazy_eval.rs:74:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
    |             ^^^^-------------------
@@ -42,7 +42,7 @@ LL |     let _ = opt.or_else(|| ext_opt);
    |                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:74:13
+  --> $DIR/unnecessary_lazy_eval.rs:75:13
    |
 LL |     let _ = opt.or_else(|| None);
    |             ^^^^----------------
@@ -50,7 +50,7 @@ LL |     let _ = opt.or_else(|| None);
    |                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:75:13
+  --> $DIR/unnecessary_lazy_eval.rs:76:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
    |             ^^^^------------------------
@@ -58,7 +58,7 @@ LL |     let _ = opt.get_or_insert_with(|| 2);
    |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:76:13
+  --> $DIR/unnecessary_lazy_eval.rs:77:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
    |             ^^^^----------------
@@ -66,7 +66,7 @@ LL |     let _ = opt.ok_or_else(|| 2);
    |                 help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:77:13
+  --> $DIR/unnecessary_lazy_eval.rs:78:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |             ^^^^^^^^^^^^^^^^^-------------------------------
@@ -74,15 +74,31 @@ LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:78:13
+  --> $DIR/unnecessary_lazy_eval.rs:79:13
    |
 LL |     let _ = cond.then(|| astronomers_pi);
    |             ^^^^^-----------------------
    |                  |
    |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
 
+error: unnecessary closure used with `bool::then`
+  --> $DIR/unnecessary_lazy_eval.rs:80:13
+   |
+LL |     let _ = true.then(|| -> _ {});
+   |             ^^^^^----------------
+   |                  |
+   |                  help: use `then_some(..)` instead: `then_some({})`
+
+error: unnecessary closure used with `bool::then`
+  --> $DIR/unnecessary_lazy_eval.rs:81:13
+   |
+LL |     let _ = true.then(|| {});
+   |             ^^^^^-----------
+   |                  |
+   |                  help: use `then_some(..)` instead: `then_some({})`
+
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:82:13
+  --> $DIR/unnecessary_lazy_eval.rs:85:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *r);
    |             ^^^^^^^^---------------------
@@ -90,7 +106,7 @@ LL |     let _ = Some(1).unwrap_or_else(|| *r);
    |                     help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:84:13
+  --> $DIR/unnecessary_lazy_eval.rs:87:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *b);
    |             ^^^^^^^^---------------------
@@ -98,7 +114,7 @@ LL |     let _ = Some(1).unwrap_or_else(|| *b);
    |                     help: use `unwrap_or(..)` instead: `unwrap_or(*b)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:86:13
+  --> $DIR/unnecessary_lazy_eval.rs:89:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
    |             ^^^^^^^^^^^^^^^^^---------------------
@@ -106,7 +122,7 @@ LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:87:13
+  --> $DIR/unnecessary_lazy_eval.rs:90:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
    |             ^^^^^^^^^^^^^^^^^---------------------
@@ -114,7 +130,7 @@ LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:90:13
+  --> $DIR/unnecessary_lazy_eval.rs:93:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |             ^^^^^^^^^--------------------
@@ -122,7 +138,7 @@ LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:91:13
+  --> $DIR/unnecessary_lazy_eval.rs:94:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
    |             ^^^^^^^^^---------------------
@@ -130,7 +146,7 @@ LL |     let _ = Some(10).and_then(|_| ext_opt);
    |                      help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:92:28
+  --> $DIR/unnecessary_lazy_eval.rs:95:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                            ^^^^^-------------------
@@ -138,7 +154,7 @@ LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:93:13
+  --> $DIR/unnecessary_lazy_eval.rs:96:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
    |             ^^^^^------------------------
@@ -146,7 +162,7 @@ LL |     let _ = None.get_or_insert_with(|| 2);
    |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:94:35
+  --> $DIR/unnecessary_lazy_eval.rs:97:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                   ^^^^^----------------
@@ -154,7 +170,7 @@ LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                        help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:95:28
+  --> $DIR/unnecessary_lazy_eval.rs:98:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
    |                            ^^^^^----------------
@@ -162,7 +178,7 @@ LL |     let _: Option<usize> = None.or_else(|| None);
    |                                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:98:13
+  --> $DIR/unnecessary_lazy_eval.rs:101:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |             ^^^^^^^--------------------
@@ -170,7 +186,7 @@ LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:99:13
+  --> $DIR/unnecessary_lazy_eval.rs:102:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
    |             ^^^^^^^---------------------
@@ -178,7 +194,7 @@ LL |     let _ = deep.0.and_then(|_| ext_opt);
    |                    help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:100:13
+  --> $DIR/unnecessary_lazy_eval.rs:103:13
    |
 LL |     let _ = deep.0.or_else(|| None);
    |             ^^^^^^^----------------
@@ -186,7 +202,7 @@ LL |     let _ = deep.0.or_else(|| None);
    |                    help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:101:13
+  --> $DIR/unnecessary_lazy_eval.rs:104:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |             ^^^^^^^------------------------
@@ -194,7 +210,7 @@ LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:102:13
+  --> $DIR/unnecessary_lazy_eval.rs:105:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
    |             ^^^^^^^----------------
@@ -202,7 +218,7 @@ LL |     let _ = deep.0.ok_or_else(|| 2);
    |                    help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:132:28
+  --> $DIR/unnecessary_lazy_eval.rs:135:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                            ^^^^^-------------------
@@ -210,7 +226,7 @@ LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:133:13
+  --> $DIR/unnecessary_lazy_eval.rs:136:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
    |             ^^^^^^^-------------------
@@ -218,7 +234,7 @@ LL |     let _ = deep.0.or_else(|| Some(3));
    |                    help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:134:13
+  --> $DIR/unnecessary_lazy_eval.rs:137:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
    |             ^^^^-------------------
@@ -226,7 +242,7 @@ LL |     let _ = opt.or_else(|| Some(3));
    |                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:140:13
+  --> $DIR/unnecessary_lazy_eval.rs:143:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
    |             ^^^^^---------------------
@@ -234,7 +250,7 @@ LL |     let _ = res2.unwrap_or_else(|_| 2);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:141:13
+  --> $DIR/unnecessary_lazy_eval.rs:144:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |             ^^^^^----------------------------------
@@ -242,7 +258,7 @@ LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:142:13
+  --> $DIR/unnecessary_lazy_eval.rs:145:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |             ^^^^^--------------------------------------
@@ -250,7 +266,7 @@ LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:164:35
+  --> $DIR/unnecessary_lazy_eval.rs:167:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                   ^^^^--------------------
@@ -258,7 +274,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                       help: use `and(..)` instead: `and(Err(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:165:35
+  --> $DIR/unnecessary_lazy_eval.rs:168:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                   ^^^^---------------------------------
@@ -266,7 +282,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:166:35
+  --> $DIR/unnecessary_lazy_eval.rs:169:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
    |                                   ^^^^-------------------------------------
@@ -274,7 +290,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
    |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:168:35
+  --> $DIR/unnecessary_lazy_eval.rs:171:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                   ^^^^------------------
@@ -282,7 +298,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                       help: use `or(..)` instead: `or(Ok(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:169:35
+  --> $DIR/unnecessary_lazy_eval.rs:172:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                   ^^^^-------------------------------
@@ -290,7 +306,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:170:35
+  --> $DIR/unnecessary_lazy_eval.rs:173:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                   ^^^^-----------------------------------
@@ -298,7 +314,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:171:35
+  --> $DIR/unnecessary_lazy_eval.rs:174:35
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^
@@ -312,5 +328,5 @@ LL | |     or_else(|_| Ok(ext_str.some_field));
    |       |
    |       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
-error: aborting due to 38 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
index 33685bfb738..412d4aaafb4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
@@ -25,3 +25,8 @@ fn main() {
     let arr = [(Some(1),)];
     Some(&0).and_then(|&i| arr[i].0);
 }
+
+fn issue11672() {
+    // Return type annotation helps type inference and removing it can break code
+    let _ = true.then(|| -> &[u8] { &[] });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
index 27fa560d4d7..95b02be91ca 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
@@ -25,5 +25,13 @@ LL |     let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2);
    |                   |
    |                   help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
-error: aborting due to 3 previous errors
+error: unnecessary closure used with `bool::then`
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:31:13
+   |
+LL |     let _ = true.then(|| -> &[u8] { &[] });
+   |             ^^^^^-------------------------
+   |                  |
+   |                  help: use `then_some(..)` instead: `then_some({ &[] })`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 6856bb0ab37..419b3c30deb 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -11,6 +11,8 @@ allow-unauthenticated = [
 
 # Have rustbot inform users about the *No Merge Policy*
 [no-merges]
+exclude_titles = ["Rustup"] # exclude syncs from rust-lang/rust
+labels = ["has-merge-commits", "S-waiting-on-author"]
 
 [autolabel."S-waiting-on-review"]
 new_pr = true
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index f026b7fd104..67b48a3742d 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -188,7 +188,7 @@ jobs:
         with:
           fetch-depth: 256 # get a bit more of the history
       - name: install josh-proxy
-        run: cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
+        run: RUSTFLAGS="--cap-lints warn" cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
       - name: setup bot git name and email
         run: |
           git config --global user.name 'The Miri Conjob Bot'
@@ -208,7 +208,7 @@ jobs:
           git push -u origin $BRANCH
       - name: Create Pull Request
         run: |
-          PR=$(gh pr create -B master --title 'Automatic sync from rustc' --body '')
+          PR=$(gh pr create -B master --title 'Automatic Rustup' --body '')
           ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
             --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \
             --message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience."
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index e654932255a..62370206956 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -18,6 +18,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
+name = "aes"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
 name = "aho-corasick"
 version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -143,6 +154,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
 name = "color-eyre"
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -200,6 +221,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "cpufeatures"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
 name = "crossbeam-channel"
 version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,6 +249,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
 name = "ctrlc"
 version = "3.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -285,6 +325,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
 
 [[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
 name = "getrandom"
 version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -333,6 +383,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
 name = "instant"
 version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -469,6 +528,7 @@ dependencies = [
 name = "miri"
 version = "0.1.0"
 dependencies = [
+ "aes",
  "colored",
  "ctrlc",
  "env_logger",
@@ -726,9 +786,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.17"
+version = "0.38.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7"
+checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
 dependencies = [
  "bitflags 2.4.0",
  "errno",
@@ -910,6 +970,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
 name = "ui_test"
 version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -955,6 +1021,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index c911a153c13..f8e507a11b0 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -23,6 +23,7 @@ env_logger = "0.10"
 log = "0.4"
 rand = "0.8"
 smallvec = "1.7"
+aes = { version = "0.8.3", features = ["hazmat"] }
 
 measureme = "10.0.0"
 ctrlc = "3.2.5"
diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock
index c37a5ca8875..8f442b3de13 100644
--- a/src/tools/miri/cargo-miri/Cargo.lock
+++ b/src/tools/miri/cargo-miri/Cargo.lock
@@ -238,9 +238,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.17"
+version = "0.38.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7"
+checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
 dependencies = [
  "bitflags 2.4.0",
  "errno",
diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock
index 6f8dd973fdd..ea306ed838a 100644
--- a/src/tools/miri/miri-script/Cargo.lock
+++ b/src/tools/miri/miri-script/Cargo.lock
@@ -213,9 +213,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.17"
+version = "0.38.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7"
+checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
 dependencies = [
  "bitflags 2.4.0",
  "errno",
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 8f0a0a045ab..bc3882bcf2b 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-4ea5190026dbc1302b644d938e68bc6843cb8b24
+249624b5043013d18c00f0401ca431c1a6baa8cd
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 32d4d96b069..e902939290a 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -206,11 +206,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         // Make sure the new permission makes sense as the initial permission of a fresh tag.
         assert!(new_perm.initial_state.is_initial());
         // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
-        this.check_ptr_access(
-            place.ptr(),
-            ptr_size,
-            CheckInAllocMsg::InboundsTest,
-        )?;
+        this.check_ptr_access(place.ptr(), ptr_size, CheckInAllocMsg::InboundsTest)?;
 
         // It is crucial that this gets called on all code paths, to ensure we track tag creation.
         let log_creation = |this: &MiriInterpCx<'mir, 'tcx>,
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index f3a8f1c25d7..bec2972c50d 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -1017,10 +1017,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must
         // be 8-aligned).
         let align = Align::from_bytes(place.layout.size.bytes()).unwrap();
-        this.check_ptr_align(
-            place.ptr(),
-            align,
-        )?;
+        this.check_ptr_align(place.ptr(), align)?;
         // Ensure the allocation is mutable. Even failing (read-only) compare_exchange need mutable
         // memory on many targets (i.e., they segfault if taht memory is mapped read-only), and
         // atomic loads can be implemented via compare_exchange on some targets. There could
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 0dc472bc486..965cd534d1e 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -492,7 +492,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     // `Variants::Multiple`.
                     match v.layout.variants {
                         Variants::Multiple { .. } => {
-                            // A multi-variant enum, or generator, or so.
+                            // A multi-variant enum, or coroutine, or so.
                             // Treat this like a union: without reading from memory,
                             // we cannot determine the variant we are in. Reading from
                             // memory would be subject to Stacked Borrows rules, leading
@@ -868,9 +868,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let size2 = Size::from_bytes(2);
         let this = self.eval_context_mut();
         this.check_ptr_align(ptr, Align::from_bytes(2).unwrap())?;
-        let mut alloc = this
-            .get_ptr_alloc_mut(ptr, size2 * string_length)?
-            .unwrap(); // not a ZST, so we will get a result
+        let mut alloc = this.get_ptr_alloc_mut(ptr, size2 * string_length)?.unwrap(); // not a ZST, so we will get a result
         for (offset, wchar) in wide_str.iter().copied().chain(iter::once(0x0000)).enumerate() {
             let offset = u64::try_from(offset).unwrap();
             alloc.write_scalar(alloc_range(size2 * offset, size2), Scalar::from_u16(wchar))?;
diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs
index 154d86375ca..ab6a256f714 100644
--- a/src/tools/miri/src/intptrcast.rs
+++ b/src/tools/miri/src/intptrcast.rs
@@ -26,8 +26,10 @@ pub type GlobalState = RefCell<GlobalStateInner>;
 
 #[derive(Clone, Debug)]
 pub struct GlobalStateInner {
-    /// This is used as a map between the address of each allocation and its `AllocId`.
-    /// It is always sorted
+    /// This is used as a map between the address of each allocation and its `AllocId`. It is always
+    /// sorted. We cannot use a `HashMap` since we can be given an address that is offset from the
+    /// base address, and we need to find the `AllocId` it belongs to.
+    /// This is not the *full* inverse of `base_addr`; dead allocations have been removed.
     int_to_ptr_map: Vec<(u64, AllocId)>,
     /// The base address for each allocation.  We cannot put that into
     /// `AllocExtra` because function pointers also have a base address, and
@@ -62,10 +64,21 @@ impl GlobalStateInner {
     }
 }
 
-impl<'mir, 'tcx> GlobalStateInner {
+/// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
+/// of `align` that is larger or equal to `addr`
+fn align_addr(addr: u64, align: u64) -> u64 {
+    match addr % align {
+        0 => addr,
+        rem => addr.checked_add(align).unwrap() - rem,
+    }
+}
+
+impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     // Returns the exposed `AllocId` that corresponds to the specified addr,
     // or `None` if the addr is out of bounds
-    fn alloc_id_from_addr(ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64) -> Option<AllocId> {
+    fn alloc_id_from_addr(&self, addr: u64) -> Option<AllocId> {
+        let ecx = self.eval_context_ref();
         let global_state = ecx.machine.intptrcast.borrow();
         assert!(global_state.provenance_mode != ProvenanceMode::Strict);
 
@@ -82,94 +95,40 @@ impl<'mir, 'tcx> GlobalStateInner {
                 let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
                 // This never overflows because `addr >= glb`
                 let offset = addr - glb;
-                // If the offset exceeds the size of the allocation, don't use this `alloc_id`.
+                // We require this to be strict in-bounds of the allocation. This arm is only
+                // entered for addresses that are not the base address, so even zero-sized
+                // allocations will get recognized at their base address -- but all other
+                // allocations will *not* be recognized at their "end" address.
                 let size = ecx.get_alloc_info(alloc_id).0;
-                if offset <= size.bytes() { Some(alloc_id) } else { None }
+                if offset < size.bytes() { Some(alloc_id) } else { None }
             }
         }?;
 
-        // We only use this provenance if it has been exposed, *and* is still live.
+        // We only use this provenance if it has been exposed.
         if global_state.exposed.contains(&alloc_id) {
-            let (_size, _align, kind) = ecx.get_alloc_info(alloc_id);
-            match kind {
-                AllocKind::LiveData | AllocKind::Function | AllocKind::VTable => {
-                    return Some(alloc_id);
-                }
-                AllocKind::Dead => {}
-            }
-        }
-
-        None
-    }
-
-    pub fn expose_ptr(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
-        alloc_id: AllocId,
-        tag: BorTag,
-    ) -> InterpResult<'tcx> {
-        let global_state = ecx.machine.intptrcast.get_mut();
-        // In strict mode, we don't need this, so we can save some cycles by not tracking it.
-        if global_state.provenance_mode != ProvenanceMode::Strict {
-            trace!("Exposing allocation id {alloc_id:?}");
-            global_state.exposed.insert(alloc_id);
-            if ecx.machine.borrow_tracker.is_some() {
-                ecx.expose_tag(alloc_id, tag)?;
-            }
-        }
-        Ok(())
-    }
-
-    pub fn ptr_from_addr_cast(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
-        addr: u64,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
-        trace!("Casting {:#x} to a pointer", addr);
-
-        // Potentially emit a warning.
-        let global_state = ecx.machine.intptrcast.borrow();
-        match global_state.provenance_mode {
-            ProvenanceMode::Default => {
-                // The first time this happens at a particular location, print a warning.
-                thread_local! {
-                    // `Span` is non-`Send`, so we use a thread-local instead.
-                    static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
-                }
-                PAST_WARNINGS.with_borrow_mut(|past_warnings| {
-                    let first = past_warnings.is_empty();
-                    if past_warnings.insert(ecx.cur_span()) {
-                        // Newly inserted, so first time we see this span.
-                        ecx.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
-                    }
-                });
-            }
-            ProvenanceMode::Strict => {
-                throw_machine_stop!(TerminationInfo::Int2PtrWithStrictProvenance);
-            }
-            ProvenanceMode::Permissive => {}
+            // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
+            debug_assert!(!matches!(ecx.get_alloc_info(alloc_id).2, AllocKind::Dead));
+            Some(alloc_id)
+        } else {
+            None
         }
-
-        // We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is
-        // completely legal to do a cast and then `wrapping_offset` to another allocation and only
-        // *then* do a memory access. So the allocation that the pointer happens to point to on a
-        // cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that
-        // *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed)
-        // allocation it might be referencing.
-        Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
     }
 
-    fn alloc_base_addr(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
-        alloc_id: AllocId,
-    ) -> InterpResult<'tcx, u64> {
+    fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> {
+        let ecx = self.eval_context_ref();
         let mut global_state = ecx.machine.intptrcast.borrow_mut();
         let global_state = &mut *global_state;
 
         Ok(match global_state.base_addr.entry(alloc_id) {
             Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
-                // There is nothing wrong with a raw pointer being cast to an integer only after
-                // it became dangling.  Hence we allow dead allocations.
-                let (size, align, _kind) = ecx.get_alloc_info(alloc_id);
+                let (size, align, kind) = ecx.get_alloc_info(alloc_id);
+                // This is either called immediately after allocation (and then cached), or when
+                // adjusting `tcx` pointers (which never get freed). So assert that we are looking
+                // at a live allocation. This also ensures that we never re-assign an address to an
+                // allocation that previously had an address, but then was freed and the address
+                // information was removed.
+                assert!(!matches!(kind, AllocKind::Dead));
 
                 // This allocation does not have a base address yet, pick one.
                 // Leave some space to the previous allocation, to give it some chance to be less aligned.
@@ -183,7 +142,7 @@ impl<'mir, 'tcx> GlobalStateInner {
                     .next_base_addr
                     .checked_add(slack)
                     .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
-                let base_addr = Self::align_addr(base_addr, align.bytes());
+                let base_addr = align_addr(base_addr, align.bytes());
                 entry.insert(base_addr);
                 trace!(
                     "Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})",
@@ -205,6 +164,7 @@ impl<'mir, 'tcx> GlobalStateInner {
                 if global_state.next_base_addr > ecx.target_usize_max() {
                     throw_exhaust!(AddressSpaceFull);
                 }
+                // Also maintain the opposite mapping in `int_to_ptr_map`.
                 // Given that `next_base_addr` increases in each allocation, pushing the
                 // corresponding tuple keeps `int_to_ptr_map` sorted
                 global_state.int_to_ptr_map.push((base_addr, alloc_id));
@@ -213,43 +173,95 @@ impl<'mir, 'tcx> GlobalStateInner {
             }
         })
     }
+}
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let ecx = self.eval_context_mut();
+        let global_state = ecx.machine.intptrcast.get_mut();
+        // In strict mode, we don't need this, so we can save some cycles by not tracking it.
+        if global_state.provenance_mode != ProvenanceMode::Strict {
+            trace!("Exposing allocation id {alloc_id:?}");
+            global_state.exposed.insert(alloc_id);
+            if ecx.machine.borrow_tracker.is_some() {
+                ecx.expose_tag(alloc_id, tag)?;
+            }
+        }
+        Ok(())
+    }
+
+    fn ptr_from_addr_cast(&self, addr: u64) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+        trace!("Casting {:#x} to a pointer", addr);
+
+        let ecx = self.eval_context_ref();
+        let global_state = ecx.machine.intptrcast.borrow();
+
+        // Potentially emit a warning.
+        match global_state.provenance_mode {
+            ProvenanceMode::Default => {
+                // The first time this happens at a particular location, print a warning.
+                thread_local! {
+                    // `Span` is non-`Send`, so we use a thread-local instead.
+                    static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
+                }
+                PAST_WARNINGS.with_borrow_mut(|past_warnings| {
+                    let first = past_warnings.is_empty();
+                    if past_warnings.insert(ecx.cur_span()) {
+                        // Newly inserted, so first time we see this span.
+                        ecx.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
+                    }
+                });
+            }
+            ProvenanceMode::Strict => {
+                throw_machine_stop!(TerminationInfo::Int2PtrWithStrictProvenance);
+            }
+            ProvenanceMode::Permissive => {}
+        }
+
+        // We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is
+        // completely legal to do a cast and then `wrapping_offset` to another allocation and only
+        // *then* do a memory access. So the allocation that the pointer happens to point to on a
+        // cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that
+        // *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed)
+        // allocation it might be referencing.
+        Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
+    }
 
     /// Convert a relative (tcx) pointer to a Miri pointer.
-    pub fn ptr_from_rel_ptr(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+    fn ptr_from_rel_ptr(
+        &self,
         ptr: Pointer<AllocId>,
         tag: BorTag,
     ) -> InterpResult<'tcx, Pointer<Provenance>> {
+        let ecx = self.eval_context_ref();
+
         let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
-        let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?;
+        let base_addr = ecx.addr_from_alloc_id(alloc_id)?;
 
         // Add offset with the right kind of pointer-overflowing arithmetic.
         let dl = ecx.data_layout();
         let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0;
-        Ok(Pointer::new(
-            Provenance::Concrete { alloc_id, tag },
-            Size::from_bytes(absolute_addr),
-        ))
+        Ok(Pointer::new(Provenance::Concrete { alloc_id, tag }, Size::from_bytes(absolute_addr)))
     }
 
     /// When a pointer is used for a memory access, this computes where in which allocation the
     /// access is going.
-    pub fn ptr_get_alloc(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
-        ptr: Pointer<Provenance>,
-    ) -> Option<(AllocId, Size)> {
+    fn ptr_get_alloc(&self, ptr: Pointer<Provenance>) -> Option<(AllocId, Size)> {
+        let ecx = self.eval_context_ref();
+
         let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
 
         let alloc_id = if let Provenance::Concrete { alloc_id, .. } = tag {
             alloc_id
         } else {
             // A wildcard pointer.
-            GlobalStateInner::alloc_id_from_addr(ecx, addr.bytes())?
+            ecx.alloc_id_from_addr(addr.bytes())?
         };
 
         // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr
-        // must have been called in the past.
-        let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap();
+        // must have been called in the past, so we can just look up the address in the map.
+        let base_addr = ecx.addr_from_alloc_id(alloc_id).unwrap();
 
         // Wrapping "addr - base_addr"
         #[allow(clippy::cast_possible_wrap)] // we want to wrap here
@@ -259,14 +271,24 @@ impl<'mir, 'tcx> GlobalStateInner {
             Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
         ))
     }
+}
 
-    /// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
-    /// of `align` that is larger or equal to `addr`
-    fn align_addr(addr: u64, align: u64) -> u64 {
-        match addr % align {
-            0 => addr,
-            rem => addr.checked_add(align).unwrap() - rem,
-        }
+impl GlobalStateInner {
+    pub fn free_alloc_id(&mut self, dead_id: AllocId) {
+        // We can *not* remove this from `base_addr`, since the interpreter design requires that we
+        // be able to retrieve an AllocId + offset for any memory access *before* we check if the
+        // access is valid. Specifically, `ptr_get_alloc` is called on each attempt at a memory
+        // access to determine the allocation ID and offset -- and there can still be pointers with
+        // `dead_id` that one can attempt to use for a memory access. `ptr_get_alloc` may return
+        // `None` only if the pointer truly has no provenance (this ensures consistent error
+        // messages).
+        // However, we *can* remove it from `int_to_ptr_map`, since any wildcard pointers that exist
+        // can no longer actually be accessing that address. This ensures `alloc_id_from_addr` never
+        // returns a dead allocation.
+        self.int_to_ptr_map.retain(|&(_, id)| id != dead_id);
+        // We can also remove it from `exposed`, since this allocation can anyway not be returned by
+        // `alloc_id_from_addr` any more.
+        self.exposed.remove(&dead_id);
     }
 }
 
@@ -276,7 +298,7 @@ mod tests {
 
     #[test]
     fn test_align_addr() {
-        assert_eq!(GlobalStateInner::align_addr(37, 4), 40);
-        assert_eq!(GlobalStateInner::align_addr(44, 4), 44);
+        assert_eq!(align_addr(37, 4), 40);
+        assert_eq!(align_addr(44, 4), 44);
     }
 }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f1d8ce01bc2..68b9164dec0 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -117,7 +117,7 @@ pub use crate::eval::{
     create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
 };
 pub use crate::helpers::EvalContextExt as _;
-pub use crate::intptrcast::ProvenanceMode;
+pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode};
 pub use crate::machine::{
     AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
     PrimitiveLayouts, Provenance, ProvenanceExtra,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 1073db6f1a0..d5775912eab 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1006,7 +1006,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn generate_nan<F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>, F2: rustc_apfloat::Float>(
+    fn generate_nan<
+        F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>,
+        F2: rustc_apfloat::Float,
+    >(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         inputs: &[F1],
     ) -> F2 {
@@ -1146,7 +1149,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             // Value does not matter, SB is disabled
             BorTag::default()
         };
-        intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag)
+        ecx.ptr_from_rel_ptr(ptr, tag)
     }
 
     /// Called on `usize as ptr` casts.
@@ -1155,7 +1158,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &MiriInterpCx<'mir, 'tcx>,
         addr: u64,
     ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>> {
-        intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr)
+        ecx.ptr_from_addr_cast(addr)
     }
 
     /// Called on `ptr as usize` casts.
@@ -1166,8 +1169,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } =>
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+            Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
@@ -1188,7 +1190,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &MiriInterpCx<'mir, 'tcx>,
         ptr: Pointer<Self::Provenance>,
     ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
-        let rel = intptrcast::GlobalStateInner::ptr_get_alloc(ecx, ptr);
+        let rel = ecx.ptr_get_alloc(ptr);
 
         rel.map(|(alloc_id, size)| {
             let tag = match ptr.provenance {
@@ -1260,6 +1262,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         {
             *deallocated_at = Some(machine.current_span());
         }
+        machine.intptrcast.get_mut().free_alloc_id(alloc_id);
         Ok(())
     }
 
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 0f4be5e154a..2d5df303745 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -805,12 +805,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.ptr_get_alloc_id(ptr_dest)?;
                 this.ptr_get_alloc_id(ptr_src)?;
 
-                this.mem_copy(
-                    ptr_src,
-                    ptr_dest,
-                    Size::from_bytes(n),
-                    true,
-                )?;
+                this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?;
                 this.write_pointer(ptr_dest, dest)?;
             }
             "strcpy" => {
@@ -826,12 +821,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // reason to have `strcpy` destroy pointer provenance.
                 // This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
                 let n = this.read_c_str(ptr_src)?.len().checked_add(1).unwrap();
-                this.mem_copy(
-                    ptr_src,
-                    ptr_dest,
-                    Size::from_bytes(n),
-                    true,
-                )?;
+                this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?;
                 this.write_pointer(ptr_dest, dest)?;
             }
 
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index b0592b68a9e..062623a7f6a 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -756,11 +756,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         trace!("Reading from FD {}, size {}", fd, count);
 
         // Check that the *entire* buffer is actually valid memory.
-        this.check_ptr_access(
-            buf,
-            Size::from_bytes(count),
-            CheckInAllocMsg::MemoryAccessTest,
-        )?;
+        this.check_ptr_access(buf, Size::from_bytes(count), CheckInAllocMsg::MemoryAccessTest)?;
 
         // We cap the number of read bytes to the largest value that we are able to fit in both the
         // host's and target's `isize`. This saves us from having to handle overflows later.
@@ -809,11 +805,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Isolation check is done via `FileDescriptor` trait.
 
         // Check that the *entire* buffer is actually valid memory.
-        this.check_ptr_access(
-            buf,
-            Size::from_bytes(count),
-            CheckInAllocMsg::MemoryAccessTest,
-        )?;
+        this.check_ptr_access(buf, Size::from_bytes(count), CheckInAllocMsg::MemoryAccessTest)?;
 
         // We cap the number of written bytes to the largest value that we are able to fit in both the
         // host's and target's `isize`. This saves us from having to handle overflows later.
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 17803b52baf..ff25b8120b1 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -85,10 +85,7 @@ pub fn futex<'tcx>(
                 return Ok(());
             }
 
-            let timeout = this.deref_pointer_as(
-                &args[3],
-                this.libc_ty_layout("timespec"),
-            )?;
+            let timeout = this.deref_pointer_as(&args[3], this.libc_ty_layout("timespec"))?;
             let timeout_time = if this.ptr_is_null(timeout.ptr())? {
                 None
             } else {
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index 5e46404e7f1..2c9603097c8 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -321,8 +321,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         this.atomic_fence(AtomicFenceOrd::SeqCst)?;
 
         let layout = this.machine.layouts.uint(size).unwrap();
-        let futex_val = this
-            .read_scalar_atomic(&this.ptr_to_mplace(ptr, layout), AtomicReadOrd::Relaxed)?;
+        let futex_val =
+            this.read_scalar_atomic(&this.ptr_to_mplace(ptr, layout), AtomicReadOrd::Relaxed)?;
         let compare_val = this.read_scalar(&this.ptr_to_mplace(compare, layout))?;
 
         if futex_val == compare_val {
diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs
new file mode 100644
index 00000000000..aef930595b2
--- /dev/null
+++ b/src/tools/miri/src/shims/x86/aesni.rs
@@ -0,0 +1,168 @@
+use rustc_middle::ty::layout::LayoutOf as _;
+use rustc_middle::ty::Ty;
+use rustc_span::Symbol;
+use rustc_target::spec::abi::Abi;
+
+use crate::*;
+use shims::foreign_items::EmulateForeignItemResult;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
+    crate::MiriInterpCxExt<'mir, 'tcx>
+{
+    fn emulate_x86_aesni_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: Abi,
+        args: &[OpTy<'tcx, Provenance>],
+        dest: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.aesni.").unwrap();
+
+        match unprefixed_name {
+            // Used to implement the _mm_aesdec_si128, _mm256_aesdec_epi128
+            // and _mm512_aesdec_epi128 functions.
+            // Performs one round of an AES decryption on each 128-bit word of
+            // `state` with the corresponding 128-bit key of `key`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128
+            "aesdec" | "aesdec.256" | "aesdec.512" => {
+                let [state, key] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                aes_round(this, state, key, dest, |state, key| {
+                    let key = aes::Block::from(key.to_le_bytes());
+                    let mut state = aes::Block::from(state.to_le_bytes());
+                    // `aes::hazmat::equiv_inv_cipher_round` documentation states that
+                    // it performs the same operation as the x86 aesdec instruction.
+                    aes::hazmat::equiv_inv_cipher_round(&mut state, &key);
+                    u128::from_le_bytes(state.into())
+                })?;
+            }
+            // Used to implement the _mm_aesdeclast_si128, _mm256_aesdeclast_epi128
+            // and _mm512_aesdeclast_epi128 functions.
+            // Performs last round of an AES decryption on each 128-bit word of
+            // `state` with the corresponding 128-bit key of `key`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128
+            "aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => {
+                let [state, key] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                aes_round(this, state, key, dest, |state, key| {
+                    let mut state = aes::Block::from(state.to_le_bytes());
+                    // `aes::hazmat::equiv_inv_cipher_round` does the following operations:
+                    // state = InvShiftRows(state)
+                    // state = InvSubBytes(state)
+                    // state = InvMixColumns(state)
+                    // state = state ^ key
+                    // But we need to skip the InvMixColumns.
+                    // First, use a zeroed key to skip the XOR.
+                    aes::hazmat::equiv_inv_cipher_round(&mut state, &aes::Block::from([0; 16]));
+                    // Then, undo the InvMixColumns with MixColumns.
+                    aes::hazmat::mix_columns(&mut state);
+                    // Finally, do the XOR.
+                    u128::from_le_bytes(state.into()) ^ key
+                })?;
+            }
+            // Used to implement the _mm_aesenc_si128, _mm256_aesenc_epi128
+            // and _mm512_aesenc_epi128 functions.
+            // Performs one round of an AES encryption on each 128-bit word of
+            // `state` with the corresponding 128-bit key of `key`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128
+            "aesenc" | "aesenc.256" | "aesenc.512" => {
+                let [state, key] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                aes_round(this, state, key, dest, |state, key| {
+                    let key = aes::Block::from(key.to_le_bytes());
+                    let mut state = aes::Block::from(state.to_le_bytes());
+                    // `aes::hazmat::cipher_round` documentation states that
+                    // it performs the same operation as the x86 aesenc instruction.
+                    aes::hazmat::cipher_round(&mut state, &key);
+                    u128::from_le_bytes(state.into())
+                })?;
+            }
+            // Used to implement the _mm_aesenclast_si128, _mm256_aesenclast_epi128
+            // and _mm512_aesenclast_epi128 functions.
+            // Performs last round of an AES encryption on each 128-bit word of
+            // `state` with the corresponding 128-bit key of `key`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128
+            "aesenclast" | "aesenclast.256" | "aesenclast.512" => {
+                let [state, key] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                aes_round(this, state, key, dest, |state, key| {
+                    let mut state = aes::Block::from(state.to_le_bytes());
+                    // `aes::hazmat::cipher_round` does the following operations:
+                    // state = ShiftRows(state)
+                    // state = SubBytes(state)
+                    // state = MixColumns(state)
+                    // state = state ^ key
+                    // But we need to skip the MixColumns.
+                    // First, use a zeroed key to skip the XOR.
+                    aes::hazmat::cipher_round(&mut state, &aes::Block::from([0; 16]));
+                    // Then, undo the MixColumns with InvMixColumns.
+                    aes::hazmat::inv_mix_columns(&mut state);
+                    // Finally, do the XOR.
+                    u128::from_le_bytes(state.into()) ^ key
+                })?;
+            }
+            // Used to implement the _mm_aesimc_si128 function.
+            // Performs the AES InvMixColumns operation on `op`
+            "aesimc" => {
+                let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                // Transmute to `u128`
+                let op = op.transmute(this.machine.layouts.u128, this)?;
+                let dest = dest.transmute(this.machine.layouts.u128, this)?;
+
+                let state = this.read_scalar(&op)?.to_u128()?;
+                let mut state = aes::Block::from(state.to_le_bytes());
+                aes::hazmat::inv_mix_columns(&mut state);
+
+                this.write_scalar(Scalar::from_u128(u128::from_le_bytes(state.into())), &dest)?;
+            }
+            // TODO: Implement the `llvm.x86.aesni.aeskeygenassist` when possible
+            // with an external crate.
+            _ => return Ok(EmulateForeignItemResult::NotSupported),
+        }
+        Ok(EmulateForeignItemResult::NeedsJumping)
+    }
+}
+
+// Performs an AES round (given by `f`) on each 128-bit word of
+// `state` with the corresponding 128-bit key of `key`.
+fn aes_round<'tcx>(
+    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    state: &OpTy<'tcx, Provenance>,
+    key: &OpTy<'tcx, Provenance>,
+    dest: &PlaceTy<'tcx, Provenance>,
+    f: impl Fn(u128, u128) -> u128,
+) -> InterpResult<'tcx, ()> {
+    assert_eq!(dest.layout.size, state.layout.size);
+    assert_eq!(dest.layout.size, key.layout.size);
+
+    // Transmute arguments to arrays of `u128`.
+    assert_eq!(dest.layout.size.bytes() % 16, 0);
+    let len = dest.layout.size.bytes() / 16;
+
+    let u128_array_layout =
+        this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u128, len))?;
+
+    let state = state.transmute(u128_array_layout, this)?;
+    let key = key.transmute(u128_array_layout, this)?;
+    let dest = dest.transmute(u128_array_layout, this)?;
+
+    for i in 0..len {
+        let state = this.read_scalar(&this.project_index(&state, i)?)?.to_u128()?;
+        let key = this.read_scalar(&this.project_index(&key, i)?)?.to_u128()?;
+        let dest = this.project_index(&dest, i)?;
+
+        let res = f(state, key);
+
+        this.write_scalar(Scalar::from_u128(res), &dest)?;
+    }
+
+    Ok(())
+}
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 53a4a1ef28a..d88a3127ecc 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -7,9 +7,11 @@ use crate::*;
 use helpers::bool_to_simd_element;
 use shims::foreign_items::EmulateForeignItemResult;
 
+mod aesni;
 mod sse;
 mod sse2;
 mod sse3;
+mod sse41;
 mod ssse3;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -100,6 +102,17 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this, link_name, abi, args, dest,
                 );
             }
+            name if name.starts_with("sse41.") => {
+                return sse41::EvalContextExt::emulate_x86_sse41_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
+            name if name.starts_with("aesni.") => {
+                return aesni::EvalContextExt::emulate_x86_aesni_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
+
             _ => return Ok(EmulateForeignItemResult::NotSupported),
         }
         Ok(EmulateForeignItemResult::NeedsJumping)
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
index 252384a0aa9..246e9e9c6cb 100644
--- a/src/tools/miri/src/shims/x86/sse3.rs
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -73,12 +73,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let src_ptr = this.read_pointer(src_ptr)?;
                 let dest = dest.force_mplace(this)?;
 
-                this.mem_copy(
-                    src_ptr,
-                    dest.ptr(),
-                    dest.layout.size,
-                    /*nonoverlapping*/ true,
-                )?;
+                this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?;
             }
             _ => return Ok(EmulateForeignItemResult::NotSupported),
         }
diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs
new file mode 100644
index 00000000000..cfa06ded6e6
--- /dev/null
+++ b/src/tools/miri/src/shims/x86/sse41.rs
@@ -0,0 +1,319 @@
+use rustc_middle::mir;
+use rustc_span::Symbol;
+use rustc_target::abi::Size;
+use rustc_target::spec::abi::Abi;
+
+use crate::*;
+use shims::foreign_items::EmulateForeignItemResult;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
+    crate::MiriInterpCxExt<'mir, 'tcx>
+{
+    fn emulate_x86_sse41_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: Abi,
+        args: &[OpTy<'tcx, Provenance>],
+        dest: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, EmulateForeignItemResult> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse41.").unwrap();
+
+        match unprefixed_name {
+            // Used to implement the _mm_insert_ps function.
+            // Takes one element of `right` and inserts it into `left` and
+            // optionally zero some elements. Source index is specified
+            // in bits `6..=7` of `imm`, destination index is specified in
+            // bits `4..=5` if `imm`, and `i`th bit specifies whether element
+            // `i` is zeroed.
+            "insertps" => {
+                let [left, right, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, left_len);
+                assert_eq!(dest_len, right_len);
+                assert!(dest_len <= 4);
+
+                let imm = this.read_scalar(imm)?.to_u8()?;
+                let src_index = u64::from((imm >> 6) & 0b11);
+                let dst_index = u64::from((imm >> 4) & 0b11);
+
+                let src_value = this.read_immediate(&this.project_index(&right, src_index)?)?;
+
+                for i in 0..dest_len {
+                    let dest = this.project_index(&dest, i)?;
+
+                    if imm & (1 << i) != 0 {
+                        // zeroed
+                        this.write_scalar(Scalar::from_u32(0), &dest)?;
+                    } else if i == dst_index {
+                        // copy from `right` at specified index
+                        this.write_immediate(*src_value, &dest)?;
+                    } else {
+                        // copy from `left`
+                        this.copy_op(
+                            &this.project_index(&left, i)?,
+                            &dest,
+                            /*allow_transmute*/ false,
+                        )?;
+                    }
+                }
+            }
+            // Used to implement the _mm_packus_epi32 function.
+            // Concatenates two 32-bit signed integer vectors and converts
+            // the result to a 16-bit unsigned integer vector with saturation.
+            "packusdw" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(left_len, right_len);
+                assert_eq!(dest_len, left_len.checked_mul(2).unwrap());
+
+                for i in 0..left_len {
+                    let left = this.read_scalar(&this.project_index(&left, i)?)?.to_i32()?;
+                    let right = this.read_scalar(&this.project_index(&right, i)?)?.to_i32()?;
+                    let left_dest = this.project_index(&dest, i)?;
+                    let right_dest = this.project_index(&dest, i.checked_add(left_len).unwrap())?;
+
+                    let left_res =
+                        u16::try_from(left).unwrap_or(if left < 0 { 0 } else { u16::MAX });
+                    let right_res =
+                        u16::try_from(right).unwrap_or(if right < 0 { 0 } else { u16::MAX });
+
+                    this.write_scalar(Scalar::from_u16(left_res), &left_dest)?;
+                    this.write_scalar(Scalar::from_u16(right_res), &right_dest)?;
+                }
+            }
+            // Used to implement the _mm_dp_ps and _mm_dp_pd functions.
+            // Conditionally multiplies the packed floating-point elements in
+            // `left` and `right` using the high 4 bits in `imm`, sums the four
+            // products, and conditionally stores the sum in `dest` using the low
+            // 4 bits of `imm`.
+            "dpps" | "dppd" => {
+                let [left, right, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(left_len, right_len);
+                assert!(dest_len <= 4);
+
+                let imm = this.read_scalar(imm)?.to_u8()?;
+
+                let element_layout = left.layout.field(this, 0);
+
+                // Calculate dot product
+                // Elements are floating point numbers, but we can use `from_int`
+                // because the representation of 0.0 is all zero bits.
+                let mut sum = ImmTy::from_int(0u8, element_layout);
+                for i in 0..left_len {
+                    if imm & (1 << i.checked_add(4).unwrap()) != 0 {
+                        let left = this.read_immediate(&this.project_index(&left, i)?)?;
+                        let right = this.read_immediate(&this.project_index(&right, i)?)?;
+
+                        let mul = this.wrapping_binary_op(mir::BinOp::Mul, &left, &right)?;
+                        sum = this.wrapping_binary_op(mir::BinOp::Add, &sum, &mul)?;
+                    }
+                }
+
+                // Write to destination (conditioned to imm)
+                for i in 0..dest_len {
+                    let dest = this.project_index(&dest, i)?;
+
+                    if imm & (1 << i) != 0 {
+                        this.write_immediate(*sum, &dest)?;
+                    } else {
+                        this.write_scalar(Scalar::from_int(0u8, element_layout.size), &dest)?;
+                    }
+                }
+            }
+            // Used to implement the _mm_floor_ss, _mm_ceil_ss and _mm_round_ss
+            // functions. Rounds the first element of `right` according to `rounding`
+            // and copies the remaining elements from `left`.
+            "round.ss" => {
+                let [left, right, rounding] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                round_first::<rustc_apfloat::ieee::Single>(this, left, right, rounding, dest)?;
+            }
+            // Used to implement the _mm_floor_sd, _mm_ceil_sd and _mm_round_sd
+            // functions. Rounds the first element of `right` according to `rounding`
+            // and copies the remaining elements from `left`.
+            "round.sd" => {
+                let [left, right, rounding] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                round_first::<rustc_apfloat::ieee::Double>(this, left, right, rounding, dest)?;
+            }
+            // Used to implement the _mm_minpos_epu16 function.
+            // Find the minimum unsinged 16-bit integer in `op` and
+            // returns its value and position.
+            "phminposuw" => {
+                let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (op, op_len) = this.operand_to_simd(op)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                // Find minimum
+                let mut min_value = u16::MAX;
+                let mut min_index = 0;
+                for i in 0..op_len {
+                    let op = this.read_scalar(&this.project_index(&op, i)?)?.to_u16()?;
+                    if op < min_value {
+                        min_value = op;
+                        min_index = i;
+                    }
+                }
+
+                // Write value and index
+                this.write_scalar(Scalar::from_u16(min_value), &this.project_index(&dest, 0)?)?;
+                this.write_scalar(
+                    Scalar::from_u16(min_index.try_into().unwrap()),
+                    &this.project_index(&dest, 1)?,
+                )?;
+                // Fill remaining with zeros
+                for i in 2..dest_len {
+                    this.write_scalar(Scalar::from_u16(0), &this.project_index(&dest, i)?)?;
+                }
+            }
+            // Used to implement the _mm_mpsadbw_epu8 function.
+            // Compute the sum of absolute differences of quadruplets of unsigned
+            // 8-bit integers in `left` and `right`, and store the 16-bit results
+            // in `right`. Quadruplets are selected from `left` and `right` with
+            // offsets specified in `imm`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8
+            "mpsadbw" => {
+                let [left, right, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(left_len, right_len);
+                assert_eq!(left_len, dest_len.checked_mul(2).unwrap());
+
+                let imm = this.read_scalar(imm)?.to_u8()?;
+                // Bit 2 of `imm` specifies the offset for indices of `left`.
+                // The offset is 0 when the bit is 0 or 4 when the bit is 1.
+                let left_offset = u64::from((imm >> 2) & 1).checked_mul(4).unwrap();
+                // Bits 0..=1 of `imm` specify the offset for indices of
+                // `right` in blocks of 4 elements.
+                let right_offset = u64::from(imm & 0b11).checked_mul(4).unwrap();
+
+                for i in 0..dest_len {
+                    let left_offset = left_offset.checked_add(i).unwrap();
+                    let mut res: u16 = 0;
+                    for j in 0..4 {
+                        let left = this
+                            .read_scalar(
+                                &this.project_index(&left, left_offset.checked_add(j).unwrap())?,
+                            )?
+                            .to_u8()?;
+                        let right = this
+                            .read_scalar(
+                                &this
+                                    .project_index(&right, right_offset.checked_add(j).unwrap())?,
+                            )?
+                            .to_u8()?;
+                        res = res.checked_add(left.abs_diff(right).into()).unwrap();
+                    }
+                    this.write_scalar(Scalar::from_u16(res), &this.project_index(&dest, i)?)?;
+                }
+            }
+            // Used to implement the _mm_testz_si128, _mm_testc_si128
+            // and _mm_testnzc_si128 functions.
+            // Tests `op & mask == 0`, `op & mask == mask` or
+            // `op & mask != 0 && op & mask != mask`
+            "ptestz" | "ptestc" | "ptestnzc" => {
+                let [op, mask] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (op, op_len) = this.operand_to_simd(op)?;
+                let (mask, mask_len) = this.operand_to_simd(mask)?;
+
+                assert_eq!(op_len, mask_len);
+
+                let f = match unprefixed_name {
+                    "ptestz" => |op, mask| op & mask == 0,
+                    "ptestc" => |op, mask| op & mask == mask,
+                    "ptestnzc" => |op, mask| op & mask != 0 && op & mask != mask,
+                    _ => unreachable!(),
+                };
+
+                let mut all_zero = true;
+                for i in 0..op_len {
+                    let op = this.read_scalar(&this.project_index(&op, i)?)?.to_u64()?;
+                    let mask = this.read_scalar(&this.project_index(&mask, i)?)?.to_u64()?;
+                    all_zero &= f(op, mask);
+                }
+
+                this.write_scalar(Scalar::from_i32(all_zero.into()), dest)?;
+            }
+            _ => return Ok(EmulateForeignItemResult::NotSupported),
+        }
+        Ok(EmulateForeignItemResult::NeedsJumping)
+    }
+}
+
+// Rounds the first element of `right` according to `rounding`
+// and copies the remaining elements from `left`.
+fn round_first<'tcx, F: rustc_apfloat::Float>(
+    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    left: &OpTy<'tcx, Provenance>,
+    right: &OpTy<'tcx, Provenance>,
+    rounding: &OpTy<'tcx, Provenance>,
+    dest: &PlaceTy<'tcx, Provenance>,
+) -> InterpResult<'tcx, ()> {
+    let (left, left_len) = this.operand_to_simd(left)?;
+    let (right, right_len) = this.operand_to_simd(right)?;
+    let (dest, dest_len) = this.place_to_simd(dest)?;
+
+    assert_eq!(dest_len, left_len);
+    assert_eq!(dest_len, right_len);
+
+    // The fourth bit of `rounding` only affects the SSE status
+    // register, which cannot be accessed from Miri (or from Rust,
+    // for that matter), so we can ignore it.
+    let rounding = match this.read_scalar(rounding)?.to_i32()? & !0b1000 {
+        // When the third bit is 0, the rounding mode is determined by the
+        // first two bits.
+        0b000 => rustc_apfloat::Round::NearestTiesToEven,
+        0b001 => rustc_apfloat::Round::TowardNegative,
+        0b010 => rustc_apfloat::Round::TowardPositive,
+        0b011 => rustc_apfloat::Round::TowardZero,
+        // When the third bit is 1, the rounding mode is determined by the
+        // SSE status register. Since we do not support modifying it from
+        // Miri (or Rust), we assume it to be at its default mode (round-to-nearest).
+        0b100..=0b111 => rustc_apfloat::Round::NearestTiesToEven,
+        rounding => throw_unsup_format!("unsupported rounding mode 0x{rounding:02x}"),
+    };
+
+    let op0: F = this.read_scalar(&this.project_index(&right, 0)?)?.to_float()?;
+    let res = op0.round_to_integral(rounding).value;
+    this.write_scalar(
+        Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)),
+        &this.project_index(&dest, 0)?,
+    )?;
+
+    for i in 1..dest_len {
+        this.copy_op(
+            &this.project_index(&left, i)?,
+            &this.project_index(&dest, i)?,
+            /*allow_transmute*/ false,
+        )?;
+    }
+
+    Ok(())
+}
diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
new file mode 100644
index 00000000000..005ae7e9132
--- /dev/null
+++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
@@ -0,0 +1,46 @@
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
+#![feature(coroutines, coroutine_trait)]
+
+use std::{
+    ops::{Coroutine, CoroutineState},
+    pin::Pin,
+};
+
+fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
+    static move || {
+        let mut num = 0;
+        let num = &mut num;
+        *num += 0;
+
+        yield *num;
+        *num += 1; //~ERROR: has been freed
+    }
+}
+
+struct CoroutineIteratorAdapter<G>(G);
+
+impl<G> Iterator for CoroutineIteratorAdapter<G>
+where
+    G: Coroutine<Return = ()>,
+{
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let me = unsafe { Pin::new_unchecked(&mut self.0) };
+        match me.resume(()) {
+            CoroutineState::Yielded(x) => Some(x),
+            CoroutineState::Complete(_) => None,
+        }
+    }
+}
+
+fn main() {
+    let mut coroutine_iterator_2 = {
+        let mut coroutine_iterator = Box::new(CoroutineIteratorAdapter(firstn()));
+        coroutine_iterator.next(); // pin it
+
+        Box::new(*coroutine_iterator) // move it
+    }; // *deallocate* coroutine_iterator
+
+    coroutine_iterator_2.next(); // and use moved value
+}
diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.stderr b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr
index 8ad0ce8cc32..919fa87f9d7 100644
--- a/src/tools/miri/tests/fail/generator-pinned-moved.stderr
+++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr
@@ -1,5 +1,5 @@
 error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
-  --> $DIR/generator-pinned-moved.rs:LL:CC
+  --> $DIR/coroutine-pinned-moved.rs:LL:CC
    |
 LL |         *num += 1;
    |         ^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
@@ -7,27 +7,27 @@ LL |         *num += 1;
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
 help: ALLOC was allocated here:
-  --> $DIR/generator-pinned-moved.rs:LL:CC
+  --> $DIR/coroutine-pinned-moved.rs:LL:CC
    |
-LL |         let mut generator_iterator = Box::new(GeneratorIteratorAdapter(firstn()));
+LL |         let mut coroutine_iterator = Box::new(CoroutineIteratorAdapter(firstn()));
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: ALLOC was deallocated here:
-  --> $DIR/generator-pinned-moved.rs:LL:CC
+  --> $DIR/coroutine-pinned-moved.rs:LL:CC
    |
-LL |     }; // *deallocate* generator_iterator
+LL |     }; // *deallocate* coroutine_iterator
    |     ^
    = note: BACKTRACE (of the first span):
-   = note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
-note: inside `<GeneratorIteratorAdapter<{static generator@$DIR/generator-pinned-moved.rs:LL:CC}> as std::iter::Iterator>::next`
-  --> $DIR/generator-pinned-moved.rs:LL:CC
+   = note: inside closure at $DIR/coroutine-pinned-moved.rs:LL:CC
+note: inside `<CoroutineIteratorAdapter<{static coroutine@$DIR/coroutine-pinned-moved.rs:LL:CC}> as std::iter::Iterator>::next`
+  --> $DIR/coroutine-pinned-moved.rs:LL:CC
    |
 LL |         match me.resume(()) {
    |               ^^^^^^^^^^^^^
-   = note: inside `<std::boxed::Box<GeneratorIteratorAdapter<{static generator@$DIR/generator-pinned-moved.rs:LL:CC}>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
+   = note: inside `<std::boxed::Box<CoroutineIteratorAdapter<{static coroutine@$DIR/coroutine-pinned-moved.rs:LL:CC}>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside `main`
-  --> $DIR/generator-pinned-moved.rs:LL:CC
+  --> $DIR/coroutine-pinned-moved.rs:LL:CC
    |
-LL |     generator_iterator_2.next(); // and use moved value
+LL |     coroutine_iterator_2.next(); // and use moved value
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs
index 0d4506115c7..d2823672ade 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs
@@ -1,7 +1,7 @@
 // Should be caught even without retagging
 //@compile-flags: -Zmiri-disable-stacked-borrows
 #![feature(strict_provenance)]
-use std::ptr::{addr_of_mut, self};
+use std::ptr::{self, addr_of_mut};
 
 // Deref'ing a dangling raw pointer is fine, but for a dangling box it is not.
 // We do this behind a pointer indirection to potentially fool validity checking.
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs
index 37da2e96758..b62e041d70c 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs
@@ -1,7 +1,7 @@
 // Should be caught even without retagging
 //@compile-flags: -Zmiri-disable-stacked-borrows
 #![feature(strict_provenance)]
-use std::ptr::{addr_of_mut, self};
+use std::ptr::{self, addr_of_mut};
 
 // Deref'ing a dangling raw pointer is fine, but for a dangling reference it is not.
 // We do this behind a pointer indirection to potentially fool validity checking.
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
index 9d53faccd1e..c1bbc748e1a 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
@@ -1,4 +1,6 @@
-//@compile-flags: -Zmiri-tree-borrows
+// This does need an aliasing model.
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(raw_ref_op)]
 #![feature(core_intrinsics)]
 #![feature(custom_mir)]
@@ -25,6 +27,7 @@ pub fn main() {
 fn myfun(ptr: *mut i32) -> i32 {
     // This overwrites the return place, which shouldn't be possible through another pointer.
     unsafe { ptr.write(0) };
-    //~^ ERROR: /write access .* forbidden/
+    //~[stack]^ ERROR: tag does not exist in the borrow stack
+    //~[tree]| ERROR: /write access .* forbidden/
     13
 }
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr
new file mode 100644
index 00000000000..0666db34fec
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr
@@ -0,0 +1,40 @@
+error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
+  --> $DIR/return_pointer_aliasing2.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(0) };
+   |              ^^^^^^^^^^^^
+   |              |
+   |              attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
+   |              this error occurs as part of an access at ALLOC[0x0..0x4]
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
+  --> $DIR/return_pointer_aliasing2.rs:LL:CC
+   |
+LL | /     mir! {
+LL | |         {
+LL | |             let _x = 0;
+LL | |             let ptr = &raw mut _x;
+...  |
+LL | |         }
+LL | |     }
+   | |_____^
+help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
+  --> $DIR/return_pointer_aliasing2.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(0) };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `myfun` at $DIR/return_pointer_aliasing2.rs:LL:CC
+note: inside `main`
+  --> $DIR/return_pointer_aliasing2.rs:LL:CC
+   |
+LL |             Call(_x = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr
index e1b40a6bc18..e1b40a6bc18 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs
new file mode 100644
index 00000000000..79e29b79d6a
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs
@@ -0,0 +1,55 @@
+// Doesn't need an aliasing model.
+//@compile-flags: -Zmiri-disable-stacked-borrows
+#![feature(raw_ref_op)]
+#![feature(core_intrinsics)]
+#![feature(custom_mir)]
+
+use std::intrinsics::mir::*;
+use std::panic;
+
+#[repr(C)]
+struct S(i32, [u8; 128]);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn docall(out: &mut S) {
+    mir! {
+        {
+            Call(*out = callee(), after_call)
+        }
+
+        after_call = {
+            Return()
+        }
+    }
+}
+
+fn startpanic() -> () {
+    panic!()
+}
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn callee() -> S {
+    mir! {
+        type RET = S;
+        let _unit: ();
+        {
+            // We test whether changes done to RET before unwinding
+            // become visible to the outside. In codegen we can see them
+            // but Miri should detect this as UB!
+            RET.0 = 42;
+            Call(_unit = startpanic(), after_call)
+        }
+
+        after_call = {
+            Return()
+        }
+    }
+}
+
+fn main() {
+    let mut x = S(0, [0; 128]);
+    panic::catch_unwind(panic::AssertUnwindSafe(|| docall(&mut x))).unwrap_err();
+    // The return place got de-initialized before the call and assigning to RET
+    // does not propagate if we do not reach the `Return`.
+    dbg!(x.0); //~ERROR: uninitialized
+}
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
new file mode 100644
index 00000000000..ecd9a111840
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
@@ -0,0 +1,19 @@
+thread 'main' panicked at $DIR/return_pointer_on_unwind.rs:LL:CC:
+explicit panic
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/return_pointer_on_unwind.rs:LL:CC
+   |
+LL |     dbg!(x.0);
+   |     ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.rs b/src/tools/miri/tests/fail/generator-pinned-moved.rs
deleted file mode 100644
index 33348ace9c4..00000000000
--- a/src/tools/miri/tests/fail/generator-pinned-moved.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
-#![feature(generators, generator_trait)]
-
-use std::{
-    ops::{Generator, GeneratorState},
-    pin::Pin,
-};
-
-fn firstn() -> impl Generator<Yield = u64, Return = ()> {
-    static move || {
-        let mut num = 0;
-        let num = &mut num;
-        *num += 0;
-
-        yield *num;
-        *num += 1; //~ERROR: has been freed
-    }
-}
-
-struct GeneratorIteratorAdapter<G>(G);
-
-impl<G> Iterator for GeneratorIteratorAdapter<G>
-where
-    G: Generator<Return = ()>,
-{
-    type Item = G::Yield;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let me = unsafe { Pin::new_unchecked(&mut self.0) };
-        match me.resume(()) {
-            GeneratorState::Yielded(x) => Some(x),
-            GeneratorState::Complete(_) => None,
-        }
-    }
-}
-
-fn main() {
-    let mut generator_iterator_2 = {
-        let mut generator_iterator = Box::new(GeneratorIteratorAdapter(firstn()));
-        generator_iterator.next(); // pin it
-
-        Box::new(*generator_iterator) // move it
-    }; // *deallocate* generator_iterator
-
-    generator_iterator_2.next(); // and use moved value
-}
diff --git a/src/tools/miri/tests/pass/calls.rs b/src/tools/miri/tests/pass/calls.rs
index 014d1d3acab..8db3d3590cc 100644
--- a/src/tools/miri/tests/pass/calls.rs
+++ b/src/tools/miri/tests/pass/calls.rs
@@ -34,10 +34,26 @@ fn const_fn_call() -> i64 {
     x
 }
 
+fn call_return_into_passed_reference() {
+    pub fn func<T>(v: &mut T, f: fn(&T) -> T) {
+        // MIR building will introduce a temporary, so this becomes
+        // `let temp = f(v); *v = temp;`.
+        // If this got optimized to `*v = f(v)` on the MIR level we'd have UB
+        // since the return place may not be observed while the function runs!
+        *v = f(v);
+    }
+
+    let mut x = 0;
+    func(&mut x, |v| v + 1);
+    assert_eq!(x, 1);
+}
+
 fn main() {
     assert_eq!(call(), 2);
     assert_eq!(factorial_recursive(), 3628800);
     assert_eq!(call_generic(), (42, true));
     assert_eq!(cross_crate_fn_call(), 1);
     assert_eq!(const_fn_call(), 11);
+
+    call_return_into_passed_reference();
 }
diff --git a/src/tools/miri/tests/pass/generator.rs b/src/tools/miri/tests/pass/coroutine.rs
index 20099603455..49bfa92a052 100644
--- a/src/tools/miri/tests/pass/generator.rs
+++ b/src/tools/miri/tests/pass/coroutine.rs
@@ -1,12 +1,12 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(generators, generator_trait, never_type)]
+#![feature(coroutines, coroutine_trait, never_type)]
 
 use std::fmt::Debug;
 use std::mem::ManuallyDrop;
 use std::ops::{
-    Generator,
-    GeneratorState::{self, *},
+    Coroutine,
+    CoroutineState::{self, *},
 };
 use std::pin::Pin;
 use std::ptr;
@@ -15,22 +15,22 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 fn basic() {
     fn finish<T>(mut amt: usize, self_referential: bool, mut t: T) -> T::Return
     where
-        T: Generator<Yield = usize>,
+        T: Coroutine<Yield = usize>,
     {
         // We are not moving the `t` around until it gets dropped, so this is okay.
         let mut t = unsafe { Pin::new_unchecked(&mut t) };
         loop {
             let state = t.as_mut().resume(());
-            // Test if the generator is valid (according to type invariants).
-            // For self-referential generators however this is UB!
+            // Test if the coroutine is valid (according to type invariants).
+            // For self-referential coroutines however this is UB!
             if !self_referential {
                 let _ = unsafe { ManuallyDrop::new(ptr::read(t.as_mut().get_unchecked_mut())) };
             }
             match state {
-                GeneratorState::Yielded(y) => {
+                CoroutineState::Yielded(y) => {
                     amt -= y;
                 }
-                GeneratorState::Complete(ret) => {
+                CoroutineState::Complete(ret) => {
                     assert_eq!(amt, 0);
                     return ret;
                 }
@@ -86,7 +86,7 @@ fn basic() {
         yield 1;
     });
 
-    // also test self-referential generators
+    // also test self-referential coroutines
     assert_eq!(
         finish(5, true, static || {
             let mut x = 5;
@@ -134,9 +134,9 @@ fn basic() {
 }
 
 fn smoke_resume_arg() {
-    fn drain<G: Generator<R, Yield = Y> + Unpin, R, Y>(
+    fn drain<G: Coroutine<R, Yield = Y> + Unpin, R, Y>(
         gen: &mut G,
-        inout: Vec<(R, GeneratorState<Y, G::Return>)>,
+        inout: Vec<(R, CoroutineState<Y, G::Return>)>,
     ) where
         Y: Debug + PartialEq,
         G::Return: Debug + PartialEq,
@@ -145,7 +145,7 @@ fn smoke_resume_arg() {
 
         for (input, out) in inout {
             assert_eq!(gen.as_mut().resume(input), out);
-            // Test if the generator is valid (according to type invariants).
+            // Test if the coroutine is valid (according to type invariants).
             let _ = unsafe { ManuallyDrop::new(ptr::read(gen.as_mut().get_unchecked_mut())) };
         }
     }
diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs
index 698aa447e26..9b0a40c41b9 100644
--- a/src/tools/miri/tests/pass/float_nan.rs
+++ b/src/tools/miri/tests/pass/float_nan.rs
@@ -345,10 +345,7 @@ fn test_casts() {
     );
     // Check that the low bits are gone (not the high bits).
     check_all_outcomes(
-        HashSet::from_iter([
-            F32::nan(Pos, Quiet, 0),
-            F32::nan(Neg, Quiet, 0),
-        ]),
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
         || F32::from(F64::nan(Pos, Quiet, 1).as_f64() as f32),
     );
     check_all_outcomes(
@@ -358,7 +355,7 @@ fn test_casts() {
             F32::nan(Pos, Quiet, 1),
             F32::nan(Neg, Quiet, 1),
         ]),
-        || F32::from(F64::nan(Pos, Quiet, 1 << (51-22)).as_f64() as f32),
+        || F32::from(F64::nan(Pos, Quiet, 1 << (51 - 22)).as_f64() as f32),
     );
     check_all_outcomes(
         HashSet::from_iter([
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs
new file mode 100644
index 00000000000..090b1db0af0
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs
@@ -0,0 +1,291 @@
+// Ignore everything except x86 and x86_64
+// Any additional target are added to CI should be ignored here
+// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
+//@ignore-target-aarch64
+//@ignore-target-arm
+//@ignore-target-avr
+//@ignore-target-s390x
+//@ignore-target-thumbv7em
+//@ignore-target-wasm32
+//@compile-flags: -C target-feature=+aes,+vaes,+avx512f
+
+#![feature(avx512_target_feature, stdsimd)]
+
+use core::mem::transmute;
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+fn main() {
+    assert!(is_x86_feature_detected!("aes"));
+    assert!(is_x86_feature_detected!("vaes"));
+    assert!(is_x86_feature_detected!("avx512f"));
+
+    unsafe {
+        test_aes();
+        test_vaes();
+    }
+}
+
+// The constants in the tests below are just bit patterns. They should not
+// be interpreted as integers; signedness does not make sense for them, but
+// __m128i happens to be defined in terms of signed integers.
+#[allow(overflowing_literals)]
+#[target_feature(enable = "aes")]
+unsafe fn test_aes() {
+    // Mostly copied from library/stdarch/crates/core_arch/src/x86/aes.rs
+
+    #[target_feature(enable = "aes")]
+    unsafe fn test_mm_aesdec_si128() {
+        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
+        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+        let e = _mm_set_epi64x(0x044e4f5176fec48f, 0xb57ecfa381da39ee);
+        let r = _mm_aesdec_si128(a, k);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_aesdec_si128();
+
+    #[target_feature(enable = "aes")]
+    unsafe fn test_mm_aesdeclast_si128() {
+        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
+        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+        let e = _mm_set_epi64x(0x36cad57d9072bf9e, 0xf210dd981fa4a493);
+        let r = _mm_aesdeclast_si128(a, k);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_aesdeclast_si128();
+
+    #[target_feature(enable = "aes")]
+    unsafe fn test_mm_aesenc_si128() {
+        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
+        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+        let e = _mm_set_epi64x(0x16ab0e57dfc442ed, 0x28e4ee1884504333);
+        let r = _mm_aesenc_si128(a, k);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_aesenc_si128();
+
+    #[target_feature(enable = "aes")]
+    unsafe fn test_mm_aesenclast_si128() {
+        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
+        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+        let e = _mm_set_epi64x(0xb6dd7df25d7ab320, 0x4b04f98cf4c860f8);
+        let r = _mm_aesenclast_si128(a, k);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_aesenclast_si128();
+
+    #[target_feature(enable = "aes")]
+    unsafe fn test_mm_aesimc_si128() {
+        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714195.aspx.
+        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+        let e = _mm_set_epi64x(0xc66c82284ee40aa0, 0x6633441122770055);
+        let r = _mm_aesimc_si128(a);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_aesimc_si128();
+}
+
+// The constants in the tests below are just bit patterns. They should not
+// be interpreted as integers; signedness does not make sense for them, but
+// __m128i happens to be defined in terms of signed integers.
+#[allow(overflowing_literals)]
+#[target_feature(enable = "vaes,avx512f")]
+unsafe fn test_vaes() {
+    #[target_feature(enable = "avx")]
+    unsafe fn get_a256() -> __m256i {
+        // Constants are random
+        _mm256_set_epi64x(
+            0xb89f43a558d3cd51,
+            0x57b3e81e369bd603,
+            0xf177a1a626933fd6,
+            0x50d8adbed1a2f9d7,
+        )
+    }
+    #[target_feature(enable = "avx")]
+    unsafe fn get_k256() -> __m256i {
+        // Constants are random
+        _mm256_set_epi64x(
+            0x503ff704588b5627,
+            0xe23d882ed9c3c146,
+            0x2785e5b670155b3c,
+            0xa750718e183549ff,
+        )
+    }
+
+    #[target_feature(enable = "vaes")]
+    unsafe fn test_mm256_aesdec_epi128() {
+        let a = get_a256();
+        let k = get_k256();
+        let r = _mm256_aesdec_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 2] = transmute(a);
+        let k: [u128; 2] = transmute(k);
+        let r: [u128; 2] = transmute(r);
+        for i in 0..2 {
+            let e: u128 = transmute(_mm_aesdec_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm256_aesdec_epi128();
+
+    #[target_feature(enable = "vaes")]
+    unsafe fn test_mm256_aesdeclast_epi128() {
+        let a = get_a256();
+        let k = get_k256();
+        let r = _mm256_aesdeclast_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 2] = transmute(a);
+        let k: [u128; 2] = transmute(k);
+        let r: [u128; 2] = transmute(r);
+        for i in 0..2 {
+            let e: u128 = transmute(_mm_aesdeclast_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm256_aesdeclast_epi128();
+
+    #[target_feature(enable = "vaes")]
+    unsafe fn test_mm256_aesenc_epi128() {
+        let a = get_a256();
+        let k = get_k256();
+        let r = _mm256_aesenc_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 2] = transmute(a);
+        let k: [u128; 2] = transmute(k);
+        let r: [u128; 2] = transmute(r);
+        for i in 0..2 {
+            let e: u128 = transmute(_mm_aesenc_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm256_aesenc_epi128();
+
+    #[target_feature(enable = "vaes")]
+    unsafe fn test_mm256_aesenclast_epi128() {
+        let a = get_a256();
+        let k = get_k256();
+        let r = _mm256_aesenclast_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 2] = transmute(a);
+        let k: [u128; 2] = transmute(k);
+        let r: [u128; 2] = transmute(r);
+        for i in 0..2 {
+            let e: u128 = transmute(_mm_aesenclast_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm256_aesenclast_epi128();
+
+    #[target_feature(enable = "avx512f")]
+    unsafe fn get_a512() -> __m512i {
+        // Constants are random
+        _mm512_set_epi64(
+            0xb89f43a558d3cd51,
+            0x57b3e81e369bd603,
+            0xf177a1a626933fd6,
+            0x50d8adbed1a2f9d7,
+            0xfbfee3116629db78,
+            0x6aef4a91f2ad50f4,
+            0x4258bb51ff1d476d,
+            0x31da65761c8016cf,
+        )
+    }
+    #[target_feature(enable = "avx512f")]
+    unsafe fn get_k512() -> __m512i {
+        // Constants are random
+        _mm512_set_epi64(
+            0x503ff704588b5627,
+            0xe23d882ed9c3c146,
+            0x2785e5b670155b3c,
+            0xa750718e183549ff,
+            0xdfb408830a65d3d9,
+            0x0de3d92adac81b0a,
+            0xed2741fe12877cae,
+            0x3251ddb5404e0974,
+        )
+    }
+
+    #[target_feature(enable = "vaes,avx512f")]
+    unsafe fn test_mm512_aesdec_epi128() {
+        let a = get_a512();
+        let k = get_k512();
+        let r = _mm512_aesdec_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 4] = transmute(a);
+        let k: [u128; 4] = transmute(k);
+        let r: [u128; 4] = transmute(r);
+        for i in 0..4 {
+            let e: u128 = transmute(_mm_aesdec_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm512_aesdec_epi128();
+
+    #[target_feature(enable = "vaes,avx512f")]
+    unsafe fn test_mm512_aesdeclast_epi128() {
+        let a = get_a512();
+        let k = get_k512();
+        let r = _mm512_aesdeclast_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 4] = transmute(a);
+        let k: [u128; 4] = transmute(k);
+        let r: [u128; 4] = transmute(r);
+        for i in 0..4 {
+            let e: u128 = transmute(_mm_aesdeclast_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm512_aesdeclast_epi128();
+
+    #[target_feature(enable = "vaes,avx512f")]
+    unsafe fn test_mm512_aesenc_epi128() {
+        let a = get_a512();
+        let k = get_k512();
+        let r = _mm512_aesenc_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 4] = transmute(a);
+        let k: [u128; 4] = transmute(k);
+        let r: [u128; 4] = transmute(r);
+        for i in 0..4 {
+            let e: u128 = transmute(_mm_aesenc_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm512_aesenc_epi128();
+
+    #[target_feature(enable = "vaes,avx512f")]
+    unsafe fn test_mm512_aesenclast_epi128() {
+        let a = get_a512();
+        let k = get_k512();
+        let r = _mm512_aesenclast_epi128(a, k);
+
+        // Check results.
+        let a: [u128; 4] = transmute(a);
+        let k: [u128; 4] = transmute(k);
+        let r: [u128; 4] = transmute(r);
+        for i in 0..4 {
+            let e: u128 = transmute(_mm_aesenclast_si128(transmute(a[i]), transmute(k[i])));
+            assert_eq!(r[i], e);
+        }
+    }
+    test_mm512_aesenclast_epi128();
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) {
+    assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b))
+}
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs
new file mode 100644
index 00000000000..d5489ffaf4b
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs
@@ -0,0 +1,315 @@
+// Ignore everything except x86 and x86_64
+// Any additional target are added to CI should be ignored here
+// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
+//@ignore-target-aarch64
+//@ignore-target-arm
+//@ignore-target-avr
+//@ignore-target-s390x
+//@ignore-target-thumbv7em
+//@ignore-target-wasm32
+//@compile-flags: -C target-feature=+sse4.1
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+use std::mem::transmute;
+
+fn main() {
+    assert!(is_x86_feature_detected!("sse4.1"));
+
+    unsafe {
+        test_sse41();
+    }
+}
+
+#[target_feature(enable = "sse4.1")]
+unsafe fn test_sse41() {
+    // Mostly copied from library/stdarch/crates/core_arch/src/x86/sse41.rs
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_insert_ps() {
+        let a = _mm_set1_ps(1.0);
+        let b = _mm_setr_ps(1.0, 2.0, 3.0, 4.0);
+        let r = _mm_insert_ps::<0b11_00_1100>(a, b);
+        let e = _mm_setr_ps(4.0, 1.0, 0.0, 0.0);
+        assert_eq_m128(r, e);
+
+        // Zeroing takes precedence over copied value
+        let a = _mm_set1_ps(1.0);
+        let b = _mm_setr_ps(1.0, 2.0, 3.0, 4.0);
+        let r = _mm_insert_ps::<0b11_00_0001>(a, b);
+        let e = _mm_setr_ps(0.0, 1.0, 1.0, 1.0);
+        assert_eq_m128(r, e);
+    }
+    test_mm_insert_ps();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_packus_epi32() {
+        let a = _mm_setr_epi32(1, 2, 3, 4);
+        let b = _mm_setr_epi32(-1, -2, -3, -4);
+        let r = _mm_packus_epi32(a, b);
+        let e = _mm_setr_epi16(1, 2, 3, 4, 0, 0, 0, 0);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_packus_epi32();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_dp_pd() {
+        let a = _mm_setr_pd(2.0, 3.0);
+        let b = _mm_setr_pd(1.0, 4.0);
+        let e = _mm_setr_pd(14.0, 0.0);
+        assert_eq_m128d(_mm_dp_pd::<0b00110001>(a, b), e);
+    }
+    test_mm_dp_pd();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_dp_ps() {
+        let a = _mm_setr_ps(2.0, 3.0, 1.0, 10.0);
+        let b = _mm_setr_ps(1.0, 4.0, 0.5, 10.0);
+        let e = _mm_setr_ps(14.5, 0.0, 14.5, 0.0);
+        assert_eq_m128(_mm_dp_ps::<0b01110101>(a, b), e);
+    }
+    test_mm_dp_ps();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_floor_sd() {
+        let a = _mm_setr_pd(2.5, 4.5);
+        let b = _mm_setr_pd(-1.5, -3.5);
+        let r = _mm_floor_sd(a, b);
+        let e = _mm_setr_pd(-2.0, 4.5);
+        assert_eq_m128d(r, e);
+    }
+    test_mm_floor_sd();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_floor_ss() {
+        let a = _mm_setr_ps(2.5, 4.5, 8.5, 16.5);
+        let b = _mm_setr_ps(-1.5, -3.5, -7.5, -15.5);
+        let r = _mm_floor_ss(a, b);
+        let e = _mm_setr_ps(-2.0, 4.5, 8.5, 16.5);
+        assert_eq_m128(r, e);
+    }
+    test_mm_floor_ss();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_ceil_sd() {
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_ceil_sd(a, b);
+        let e = _mm_setr_pd(-2.0, 3.5);
+        assert_eq_m128d(r, e);
+    }
+    test_mm_ceil_sd();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_ceil_ss() {
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-2.5, -4.5, -8.5, -16.5);
+        let r = _mm_ceil_ss(a, b);
+        let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+    }
+    test_mm_ceil_ss();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_round_sd() {
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_round_sd::<_MM_FROUND_TO_NEAREST_INT>(a, b);
+        let e = _mm_setr_pd(-2.0, 3.5);
+        assert_eq_m128d(r, e);
+
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_round_sd::<_MM_FROUND_TO_NEG_INF>(a, b);
+        let e = _mm_setr_pd(-3.0, 3.5);
+        assert_eq_m128d(r, e);
+
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_round_sd::<_MM_FROUND_TO_POS_INF>(a, b);
+        let e = _mm_setr_pd(-2.0, 3.5);
+        assert_eq_m128d(r, e);
+
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_round_sd::<_MM_FROUND_TO_ZERO>(a, b);
+        let e = _mm_setr_pd(-2.0, 3.5);
+        assert_eq_m128d(r, e);
+
+        // Assume round-to-nearest by default
+        let a = _mm_setr_pd(1.5, 3.5);
+        let b = _mm_setr_pd(-2.5, -4.5);
+        let r = _mm_round_sd::<_MM_FROUND_CUR_DIRECTION>(a, b);
+        let e = _mm_setr_pd(-2.0, 3.5);
+        assert_eq_m128d(r, e);
+    }
+    test_mm_round_sd();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_round_ss() {
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5);
+        let r = _mm_round_ss::<_MM_FROUND_TO_NEAREST_INT>(a, b);
+        let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5);
+        let r = _mm_round_ss::<_MM_FROUND_TO_NEG_INF>(a, b);
+        let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5);
+        let r = _mm_round_ss::<_MM_FROUND_TO_POS_INF>(a, b);
+        let e = _mm_setr_ps(-1.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5);
+        let r = _mm_round_ss::<_MM_FROUND_TO_ZERO>(a, b);
+        let e = _mm_setr_ps(-1.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+
+        // Assume round-to-nearest by default
+        let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5);
+        let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5);
+        let r = _mm_round_ss::<_MM_FROUND_CUR_DIRECTION>(a, b);
+        let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5);
+        assert_eq_m128(r, e);
+    }
+    test_mm_round_ss();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_minpos_epu16() {
+        let a = _mm_setr_epi16(23, 18, 44, 97, 50, 13, 67, 66);
+        let r = _mm_minpos_epu16(a);
+        let e = _mm_setr_epi16(13, 5, 0, 0, 0, 0, 0, 0);
+        assert_eq_m128i(r, e);
+
+        let a = _mm_setr_epi16(0, 18, 44, 97, 50, 13, 67, 66);
+        let r = _mm_minpos_epu16(a);
+        let e = _mm_setr_epi16(0, 0, 0, 0, 0, 0, 0, 0);
+        assert_eq_m128i(r, e);
+
+        // Case where the minimum value is repeated
+        let a = _mm_setr_epi16(23, 18, 44, 97, 50, 13, 67, 13);
+        let r = _mm_minpos_epu16(a);
+        let e = _mm_setr_epi16(13, 5, 0, 0, 0, 0, 0, 0);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_minpos_epu16();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_mpsadbw_epu8() {
+        let a = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+
+        let r = _mm_mpsadbw_epu8::<0b000>(a, a);
+        let e = _mm_setr_epi16(0, 4, 8, 12, 16, 20, 24, 28);
+        assert_eq_m128i(r, e);
+
+        let r = _mm_mpsadbw_epu8::<0b001>(a, a);
+        let e = _mm_setr_epi16(16, 12, 8, 4, 0, 4, 8, 12);
+        assert_eq_m128i(r, e);
+
+        let r = _mm_mpsadbw_epu8::<0b100>(a, a);
+        let e = _mm_setr_epi16(16, 20, 24, 28, 32, 36, 40, 44);
+        assert_eq_m128i(r, e);
+
+        let r = _mm_mpsadbw_epu8::<0b101>(a, a);
+        let e = _mm_setr_epi16(0, 4, 8, 12, 16, 20, 24, 28);
+        assert_eq_m128i(r, e);
+
+        let r = _mm_mpsadbw_epu8::<0b111>(a, a);
+        let e = _mm_setr_epi16(32, 28, 24, 20, 16, 12, 8, 4);
+        assert_eq_m128i(r, e);
+    }
+    test_mm_mpsadbw_epu8();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_testz_si128() {
+        let a = _mm_set1_epi8(1);
+        let mask = _mm_set1_epi8(0);
+        let r = _mm_testz_si128(a, mask);
+        assert_eq!(r, 1);
+
+        let a = _mm_set1_epi8(0b101);
+        let mask = _mm_set1_epi8(0b110);
+        let r = _mm_testz_si128(a, mask);
+        assert_eq!(r, 0);
+
+        let a = _mm_set1_epi8(0b011);
+        let mask = _mm_set1_epi8(0b100);
+        let r = _mm_testz_si128(a, mask);
+        assert_eq!(r, 1);
+    }
+    test_mm_testz_si128();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_testc_si128() {
+        let a = _mm_set1_epi8(-1);
+        let mask = _mm_set1_epi8(0);
+        let r = _mm_testc_si128(a, mask);
+        assert_eq!(r, 1);
+
+        let a = _mm_set1_epi8(0b101);
+        let mask = _mm_set1_epi8(0b110);
+        let r = _mm_testc_si128(a, mask);
+        assert_eq!(r, 0);
+
+        let a = _mm_set1_epi8(0b101);
+        let mask = _mm_set1_epi8(0b100);
+        let r = _mm_testc_si128(a, mask);
+        assert_eq!(r, 1);
+    }
+    test_mm_testc_si128();
+
+    #[target_feature(enable = "sse4.1")]
+    unsafe fn test_mm_testnzc_si128() {
+        let a = _mm_set1_epi8(0);
+        let mask = _mm_set1_epi8(1);
+        let r = _mm_testnzc_si128(a, mask);
+        assert_eq!(r, 0);
+
+        let a = _mm_set1_epi8(-1);
+        let mask = _mm_set1_epi8(0);
+        let r = _mm_testnzc_si128(a, mask);
+        assert_eq!(r, 0);
+
+        let a = _mm_set1_epi8(0b101);
+        let mask = _mm_set1_epi8(0b110);
+        let r = _mm_testnzc_si128(a, mask);
+        assert_eq!(r, 1);
+
+        let a = _mm_set1_epi8(0b101);
+        let mask = _mm_set1_epi8(0b101);
+        let r = _mm_testnzc_si128(a, mask);
+        assert_eq!(r, 0);
+    }
+    test_mm_testnzc_si128();
+}
+
+#[track_caller]
+#[target_feature(enable = "sse")]
+unsafe fn assert_eq_m128(a: __m128, b: __m128) {
+    let r = _mm_cmpeq_ps(a, b);
+    if _mm_movemask_ps(r) != 0b1111 {
+        panic!("{:?} != {:?}", a, b);
+    }
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
+    if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
+        panic!("{:?} != {:?}", a, b);
+    }
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+pub unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) {
+    assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b))
+}
diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs
index 489fae66ffb..5990d66fbdd 100644
--- a/src/tools/miri/tests/pass/move-data-across-await-point.rs
+++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs
@@ -15,7 +15,7 @@ async fn data_moved_async() {
         // `raw_pointer` points to the original location where the Vec was stored in the caller.
         // `data` is where that Vec (to be precise, its ptr+capacity+len on-stack data)
         // got moved to. Those will usually not be the same since the Vec got moved twice
-        // (into the function call, and then into the generator upvar).
+        // (into the function call, and then into the coroutine upvar).
         assert_ne!(raw_pointer, raw_pointer2);
         unsafe {
             // This writes into the `x` in `data_moved_async`, re-initializing it.
diff --git a/src/tools/miri/tests/pass/panic/catch_panic.rs b/src/tools/miri/tests/pass/panic/catch_panic.rs
index e4a7f8e3481..f5b4eaf685d 100644
--- a/src/tools/miri/tests/pass/panic/catch_panic.rs
+++ b/src/tools/miri/tests/pass/panic/catch_panic.rs
@@ -5,6 +5,7 @@
 
 use std::cell::Cell;
 use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::process;
 
 thread_local! {
     static MY_COUNTER: Cell<usize> = Cell::new(0);
@@ -62,26 +63,26 @@ fn main() {
     // Built-in panics; also make sure the message is right.
     test(Some("index out of bounds: the len is 3 but the index is 4"), |_old_val| {
         let _val = [0, 1, 2][4];
-        loop {}
+        process::abort()
     });
     test(Some("attempt to divide by zero"), |_old_val| {
         let _val = 1 / 0;
-        loop {}
+        process::abort()
     });
 
     test(Some("align_offset: align is not a power-of-two"), |_old_val| {
         let _ = std::ptr::null::<u8>().align_offset(3);
-        loop {}
+        process::abort()
     });
 
     // Assertion and debug assertion
     test(None, |_old_val| {
         assert!(false);
-        loop {}
+        process::abort()
     });
     test(None, |_old_val| {
         debug_assert!(false);
-        loop {}
+        process::abort()
     });
 
     eprintln!("Success!"); // Make sure we get this in stderr
diff --git a/src/tools/miri/tests/pass/ptr_raw.rs b/src/tools/miri/tests/pass/ptr_raw.rs
index 9743278961b..11c3455a9ca 100644
--- a/src/tools/miri/tests/pass/ptr_raw.rs
+++ b/src/tools/miri/tests/pass/ptr_raw.rs
@@ -1,6 +1,6 @@
 #![feature(strict_provenance)]
-use std::ptr::{self, addr_of};
 use std::mem;
+use std::ptr::{self, addr_of};
 
 fn basic_raw() {
     let mut x = 12;
diff --git a/src/tools/miri/tests/pass/stacked-borrows/generators-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
index b71912882dd..c4b15c8758b 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/generators-self-referential.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
@@ -1,13 +1,13 @@
 // See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
 // this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::{
-    ops::{Generator, GeneratorState},
+    ops::{Coroutine, CoroutineState},
     pin::Pin,
 };
 
-fn firstn() -> impl Generator<Yield = u64, Return = ()> {
+fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
     static move || {
         let mut num = 0;
         let num = &mut num;
@@ -24,10 +24,10 @@ fn firstn() -> impl Generator<Yield = u64, Return = ()> {
 }
 
 fn main() {
-    let mut generator_iterator = firstn();
-    let mut pin = unsafe { Pin::new_unchecked(&mut generator_iterator) };
+    let mut coroutine_iterator = firstn();
+    let mut pin = unsafe { Pin::new_unchecked(&mut coroutine_iterator) };
     let mut sum = 0;
-    while let GeneratorState::Yielded(x) = pin.as_mut().resume(()) {
+    while let CoroutineState::Yielded(x) = pin.as_mut().resume(()) {
         sum += x;
     }
     assert_eq!(sum, 3);
diff --git a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
index d2ba1841844..dd3ee36f988 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
@@ -223,7 +223,7 @@ fn wide_raw_ptr_in_tuple() {
 fn not_unpin_not_protected() {
     // `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also
     // don't add protectors. (We could, but until we have a better idea for where we want to go with
-    // the self-referential-generator situation, it does not seem worth the potential trouble.)
+    // the self-referential-coroutine situation, it does not seem worth the potential trouble.)
     use std::marker::PhantomPinned;
 
     pub struct NotUnpin(i32, PhantomPinned);
diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs
index 1b0226e61b5..d88bcc98858 100644
--- a/src/tools/miri/tests/pass/track-caller-attribute.rs
+++ b/src/tools/miri/tests/pass/track-caller-attribute.rs
@@ -1,10 +1,10 @@
 #![feature(core_intrinsics)]
 #![feature(stmt_expr_attributes)]
 #![feature(closure_track_caller)]
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::panic::Location;
 use std::pin::Pin;
 
@@ -210,55 +210,55 @@ fn test_closure() {
     assert_eq!(non_tracked_loc.column(), 33);
 }
 
-fn test_generator() {
+fn test_coroutine() {
     #[track_caller]
-    fn mono_generator<F: Generator<String, Yield = (&'static str, String, Loc), Return = ()>>(
+    fn mono_coroutine<F: Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>(
         val: Pin<&mut F>,
     ) -> (&'static str, String, Loc) {
         match val.resume("Mono".to_string()) {
-            GeneratorState::Yielded(val) => val,
+            CoroutineState::Yielded(val) => val,
             _ => unreachable!(),
         }
     }
 
     #[track_caller]
-    fn dyn_generator(
-        val: Pin<&mut dyn Generator<String, Yield = (&'static str, String, Loc), Return = ()>>,
+    fn dyn_coroutine(
+        val: Pin<&mut dyn Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>,
     ) -> (&'static str, String, Loc) {
         match val.resume("Dyn".to_string()) {
-            GeneratorState::Yielded(val) => val,
+            CoroutineState::Yielded(val) => val,
             _ => unreachable!(),
         }
     }
 
     #[rustfmt::skip]
-    let generator = #[track_caller] |arg: String| {
+    let coroutine = #[track_caller] |arg: String| {
         yield ("first", arg.clone(), Location::caller());
         yield ("second", arg.clone(), Location::caller());
     };
 
-    let mut pinned = Box::pin(generator);
-    let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut());
+    let mut pinned = Box::pin(coroutine);
+    let (dyn_ret, dyn_arg, dyn_loc) = dyn_coroutine(pinned.as_mut());
     assert_eq!(dyn_ret, "first");
     assert_eq!(dyn_arg, "Dyn".to_string());
-    // The `Generator` trait does not have `#[track_caller]` on `resume`, so
+    // The `Coroutine` trait does not have `#[track_caller]` on `resume`, so
     // this will not match.
     assert_ne!(dyn_loc.file(), file!());
 
-    let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut());
+    let (mono_ret, mono_arg, mono_loc) = mono_coroutine(pinned.as_mut());
     let mono_line = line!() - 1;
     assert_eq!(mono_ret, "second");
-    // The generator ignores the argument to the second `resume` call
+    // The coroutine ignores the argument to the second `resume` call
     assert_eq!(mono_arg, "Dyn".to_string());
     assert_eq!(mono_loc.file(), file!());
     assert_eq!(mono_loc.line(), mono_line);
     assert_eq!(mono_loc.column(), 42);
 
     #[rustfmt::skip]
-    let non_tracked_generator = || { yield Location::caller(); };
-    let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller
-    let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) {
-        GeneratorState::Yielded(val) => val,
+    let non_tracked_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,
         _ => unreachable!(),
     };
     assert_eq!(non_tracked_loc.file(), file!());
@@ -272,5 +272,5 @@ fn main() {
     test_trait_obj();
     test_trait_obj2();
     test_closure();
-    test_generator();
+    test_coroutine();
 }
diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs
index 89752bffe9f..d45be91afcc 100644
--- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs
+++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs
@@ -315,7 +315,7 @@ fn wide_raw_ptr_in_tuple() {
 fn not_unpin_not_protected() {
     // `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also
     // don't add protectors. (We could, but until we have a better idea for where we want to go with
-    // the self-referential-generator situation, it does not seem worth the potential trouble.)
+    // the self-referential-coroutine situation, it does not seem worth the potential trouble.)
     use std::marker::PhantomPinned;
 
     pub struct NotUnpin(i32, PhantomPinned);
diff --git a/src/tools/miri/triagebot.toml b/src/tools/miri/triagebot.toml
index 1c520a9c779..3b767b3e62f 100644
--- a/src/tools/miri/triagebot.toml
+++ b/src/tools/miri/triagebot.toml
@@ -10,6 +10,5 @@ allow-unauthenticated = [
 # Gives us the commands 'ready', 'author', 'blocked'
 [shortcut]
 
-# disabled until https://github.com/rust-lang/triagebot/pull/1720 lands
-#[no-merges]
-#exclude_titles = ["Rollup of", "sync from rustc"]
+[no-merges]
+exclude_titles = ["Rustup"]
diff --git a/src/tools/rustfmt/tests/source/immovable_generators.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
index c57a1e14483..3b94af0c96c 100644
--- a/src/tools/rustfmt/tests/source/immovable_generators.rs
+++ b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 unsafe fn foo() {
     let mut ga = static || { 
diff --git a/src/tools/rustfmt/tests/target/immovable_generators.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
index 0bf7a2d91ba..f52cfa00f97 100644
--- a/src/tools/rustfmt/tests/target/immovable_generators.rs
+++ b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 unsafe fn foo() {
     let mut ga = static || {
diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs
index d3734e90b7f..ea8fa3b73d2 100644
--- a/src/tools/rustfmt/tests/target/issue_4110.rs
+++ b/src/tools/rustfmt/tests/target/issue_4110.rs
@@ -12,7 +12,7 @@ fn bindings() {
                 span,
                 ..
             },
-        ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+        ) if borrow_spans.for_coroutine() | borrow_spans.for_closure() => self
             .report_escaping_closure_capture(
                 borrow_spans,
                 borrow_span,
diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs
index 29defe68f8b..03cc46cdcde 100644
--- a/tests/codegen/async-fn-debug-awaitee-field.rs
+++ b/tests/codegen/async-fn-debug-awaitee-field.rs
@@ -1,4 +1,4 @@
-// This test makes sure that the generator field capturing the awaitee in a `.await` expression
+// This test makes sure that the coroutine field capturing the awaitee in a `.await` expression
 // is called "__awaitee" in debuginfo. This name must not be changed since debuggers and debugger
 // extensions rely on the field having this name.
 
diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs
index 73c652c9dd1..707a0d27740 100644
--- a/tests/codegen/async-fn-debug-msvc.rs
+++ b/tests/codegen/async-fn-debug-msvc.rs
@@ -1,4 +1,4 @@
-// Verify debuginfo for generators:
+// Verify debuginfo for coroutines:
 //  - Each variant points to the file and line of its yield point
 //  - The discriminants are marked artificial
 //  - Other fields are not marked artificial
diff --git a/tests/codegen/generator-debug-msvc.rs b/tests/codegen/coroutine-debug-msvc.rs
index 9d70ccdef03..6d16e7576c1 100644
--- a/tests/codegen/generator-debug-msvc.rs
+++ b/tests/codegen/coroutine-debug-msvc.rs
@@ -1,4 +1,4 @@
-// Verify debuginfo for generators:
+// Verify debuginfo for coroutines:
 //  - Each variant points to the file and line of its yield point
 //  - The discriminants are marked artificial
 //  - Other fields are not marked artificial
@@ -7,10 +7,10 @@
 // compile-flags: -C debuginfo=2
 // only-msvc
 
-#![feature(generators, generator_trait)]
-use std::ops::Generator;
+#![feature(coroutines, coroutine_trait)]
+use std::ops::Coroutine;
 
-fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
+fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
     || {
         yield 0;
         let s = String::from("foo");
@@ -20,7 +20,7 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 
 // FIXME: No way to reliably check the filename.
 
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<generator_debug_msvc::generator_test::generator_env$0>"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<coroutine_debug_msvc::coroutine_test::coroutine_env$0>"
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
@@ -55,5 +55,5 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // CHECK-NOT: flags: DIFlagArtificial
 
 fn main() {
-    let _dummy = generator_test();
+    let _dummy = coroutine_test();
 }
diff --git a/tests/codegen/generator-debug.rs b/tests/codegen/coroutine-debug.rs
index 3ec860f2cbc..b060f3bfac7 100644
--- a/tests/codegen/generator-debug.rs
+++ b/tests/codegen/coroutine-debug.rs
@@ -1,4 +1,4 @@
-// Verify debuginfo for generators:
+// Verify debuginfo for coroutines:
 //  - Each variant points to the file and line of its yield point
 //  - The discriminants are marked artificial
 //  - Other fields are not marked artificial
@@ -7,10 +7,10 @@
 // compile-flags: -C debuginfo=2 --edition=2018
 // ignore-msvc
 
-#![feature(generators, generator_trait)]
-use std::ops::Generator;
+#![feature(coroutines, coroutine_trait)]
+use std::ops::Coroutine;
 
-fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
+fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
     || {
         yield 0;
         let s = String::from("foo");
@@ -20,8 +20,8 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 
 // FIXME: No way to reliably check the filename.
 
-// CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator_env#0}", scope: [[GEN_FN]]
+// CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "coroutine_test"
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{coroutine_env#0}", scope: [[GEN_FN]]
 // CHECK:      [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: discriminator: [[DISC:![0-9]*]]
@@ -58,5 +58,5 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // CHECK-SAME: flags: DIFlagArtificial
 
 fn main() {
-    let _dummy = generator_test();
+    let _dummy = coroutine_test();
 }
diff --git a/tests/coverage-map/fn_sig_into_try.cov-map b/tests/coverage-map/fn_sig_into_try.cov-map
new file mode 100644
index 00000000000..4672e7c1ce9
--- /dev/null
+++ b/tests/coverage-map/fn_sig_into_try.cov-map
@@ -0,0 +1,53 @@
+Function name: fn_sig_into_try::a
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 04, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 10, 1) to (start + 4, 2)
+
+Function name: fn_sig_into_try::b
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 10, 01, 02, 0f, 00, 02, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15)
+- Code(Zero) at (prev + 2, 15) to (start + 0, 16)
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
+    = (c1 + (c0 - c1))
+
+Function name: fn_sig_into_try::c
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 16, 01, 02, 17, 00, 02, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 23)
+- Code(Zero) at (prev + 2, 23) to (start + 0, 24)
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
+    = (c1 + (c0 - c1))
+
+Function name: fn_sig_into_try::d
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 1c, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 4
+- Code(Counter(0)) at (prev + 28, 1) to (start + 3, 15)
+- Code(Zero) at (prev + 3, 15) to (start + 0, 16)
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
+    = (c1 + (c0 - c1))
+
diff --git a/tests/coverage-map/fn_sig_into_try.rs b/tests/coverage-map/fn_sig_into_try.rs
new file mode 100644
index 00000000000..92850c8a188
--- /dev/null
+++ b/tests/coverage-map/fn_sig_into_try.rs
@@ -0,0 +1,41 @@
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// Regression test for inconsistent handling of function signature spans that
+// are followed by code using the `?` operator.
+//
+// For each of these similar functions, the line containing the function
+// signature should be handled in the same way.
+
+fn a() -> Option<i32>
+{
+    Some(7i32);
+    Some(0)
+}
+
+fn b() -> Option<i32>
+{
+    Some(7i32)?;
+    Some(0)
+}
+
+fn c() -> Option<i32>
+{
+    let _ = Some(7i32)?;
+    Some(0)
+}
+
+fn d() -> Option<i32>
+{
+    let _: () = ();
+    Some(7i32)?;
+    Some(0)
+}
+
+#[coverage(off)]
+fn main() {
+    a();
+    b();
+    c();
+    d();
+}
diff --git a/tests/coverage-map/status-quo/generator.cov-map b/tests/coverage-map/status-quo/coroutine.cov-map
index 75704bcc223..2f4936d9ab8 100644
--- a/tests/coverage-map/status-quo/generator.cov-map
+++ b/tests/coverage-map/status-quo/coroutine.cov-map
@@ -1,4 +1,4 @@
-Function name: generator::get_u32
+Function name: coroutine::get_u32
 Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 01, 0e, 00, 13, 02, 00, 1d, 00, 3c, 07, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
@@ -13,7 +13,7 @@ Number of file 0 mappings: 4
 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
     = (c1 + (c0 - c1))
 
-Function name: generator::main
+Function name: coroutine::main
 Raw bytes (65): 0x[01, 01, 08, 05, 07, 09, 0d, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
@@ -42,7 +42,7 @@ Number of file 0 mappings: 9
 - Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2)
     = ((c4 - c5) - c6)
 
-Function name: generator::main::{closure#0}
+Function name: coroutine::main::{closure#0}
 Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06]
 Number of files: 1
 - file 0 => global file 1
diff --git a/tests/coverage-map/status-quo/generator.rs b/tests/coverage-map/status-quo/coroutine.rs
index 4319991021e..86d19af6f4f 100644
--- a/tests/coverage-map/status-quo/generator.rs
+++ b/tests/coverage-map/status-quo/coroutine.rs
@@ -1,11 +1,11 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 // The following implementation of a function called from a `yield` statement
 // (apparently requiring the Result and the `String` type or constructor)
-// creates conditions where the `generator::StateTransform` MIR transform will
+// creates conditions where the `coroutine::StateTransform` MIR transform will
 // drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
 // to handle this condition, and still report dead block coverage.
 fn get_u32(val: bool) -> Result<u32, String> {
@@ -14,17 +14,17 @@ fn get_u32(val: bool) -> Result<u32, String> {
 
 fn main() {
     let is_true = std::env::args().len() == 1;
-    let mut generator = || {
+    let mut coroutine = || {
         yield get_u32(is_true);
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(Ok(1)) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(Ok(1)) => {}
         _ => panic!("unexpected return from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
         _ => panic!("unexpected return from resume"),
     }
 }
diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage-map/status-quo/inline-dead.cov-map
index 483f7ef79c6..06b64da5723 100644
--- a/tests/coverage-map/status-quo/inline-dead.cov-map
+++ b/tests/coverage-map/status-quo/inline-dead.cov-map
@@ -31,13 +31,15 @@ Number of file 0 mappings: 2
 - Code(Counter(0)) at (prev + 7, 6) to (start + 2, 2)
 
 Function name: inline_dead::main::{closure#0}
-Raw bytes (16): 0x[01, 01, 01, 01, 05, 02, 00, 09, 0d, 00, 0e, 03, 02, 05, 00, 06]
+Raw bytes (23): 0x[01, 01, 02, 09, 06, 01, 05, 03, 01, 07, 17, 00, 18, 00, 02, 0d, 00, 0e, 03, 02, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 1
-- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-Number of file 0 mappings: 2
-- Code(Zero) at (prev + 9, 13) to (start + 0, 14)
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(2), rhs = Expression(1, Sub)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
+Number of file 0 mappings: 3
+- Code(Counter(0)) at (prev + 7, 23) to (start + 0, 24)
+- Code(Zero) at (prev + 2, 13) to (start + 0, 14)
 - Code(Expression(0, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = (c0 + c1)
+    = (c2 + (c0 - c1))
 
diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage-map/status-quo/issue-84561.cov-map
index 01fa7ec573c..76340b1a78c 100644
--- a/tests/coverage-map/status-quo/issue-84561.cov-map
+++ b/tests/coverage-map/status-quo/issue-84561.cov-map
@@ -7,15 +7,15 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19)
 
 Function name: <issue_84561::Foo as core::fmt::Debug>::fmt
-Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 89, 01, 09, 00, 25, 05, 00, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06]
+Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 88, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 137, 9) to (start + 0, 37)
-- Code(Counter(1)) at (prev + 0, 37) to (start + 0, 38)
+- Code(Counter(0)) at (prev + 136, 5) to (start + 1, 37)
+- Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38)
 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Expression(1, Add)) at (prev + 1, 5) to (start + 0, 6)
diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage-map/status-quo/yield.rs
index 361275c9215..b7e2ba31b59 100644
--- a/tests/coverage-map/status-quo/yield.rs
+++ b/tests/coverage-map/status-quo/yield.rs
@@ -1,37 +1,37 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![allow(unused_assignments)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut generator = || {
+    let mut coroutine = || {
         yield 1;
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
         _ => panic!("unexpected value from resume"),
     }
 
-    let mut generator = || {
+    let mut coroutine = || {
         yield 1;
         yield 2;
         yield 3;
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(2) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(2) => {}
         _ => panic!("unexpected value from resume"),
     }
 }
diff --git a/tests/debuginfo/generator-locals.rs b/tests/debuginfo/coroutine-locals.rs
index fd46c1a8b4d..e5eb1022ff4 100644
--- a/tests/debuginfo/generator-locals.rs
+++ b/tests/debuginfo/coroutine-locals.rs
@@ -54,10 +54,10 @@
 // lldbg-check:(int) $7 = 6
 // lldbr-check:(int) c = 6
 
-#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
 #![omit_gdb_pretty_printer_section]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/debuginfo/generator-objects.rs b/tests/debuginfo/coroutine-objects.rs
index 11c4ae2f659..3e658b2136e 100644
--- a/tests/debuginfo/generator-objects.rs
+++ b/tests/debuginfo/coroutine-objects.rs
@@ -2,7 +2,7 @@
 // min-gdb-version: 8.2
 
 // LLDB without native Rust support cannot read DW_TAG_variant_part,
-// so it prints nothing for generators. But those tests are kept to
+// so it prints nothing for coroutines. But those tests are kept to
 // ensure that LLDB won't crash at least (like #57822).
 
 // compile-flags:-g
@@ -11,62 +11,62 @@
 
 // gdb-command:run
 // gdb-command:print b
-// gdb-check:$1 = generator_objects::main::{generator_env#0}::Unresumed{_ref__a: 0x[...]}
+// gdb-check:$1 = coroutine_objects::main::{coroutine_env#0}::Unresumed{_ref__a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$2 = generator_objects::main::{generator_env#0}::Suspend0{c: 6, d: 7, _ref__a: 0x[...]}
+// gdb-check:$2 = coroutine_objects::main::{coroutine_env#0}::Suspend0{c: 6, d: 7, _ref__a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$3 = generator_objects::main::{generator_env#0}::Suspend1{c: 7, d: 8, _ref__a: 0x[...]}
+// gdb-check:$3 = coroutine_objects::main::{coroutine_env#0}::Suspend1{c: 7, d: 8, _ref__a: 0x[...]}
 // gdb-command:continue
 // gdb-command:print b
-// gdb-check:$4 = generator_objects::main::{generator_env#0}::Returned{_ref__a: 0x[...]}
+// gdb-check:$4 = coroutine_objects::main::{coroutine_env#0}::Returned{_ref__a: 0x[...]}
 
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::{generator_env#0}) $0 =
+// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) $0 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::{generator_env#0}) $1 =
+// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) $1 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::{generator_env#0}) $2 =
+// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) $2 =
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::{generator_env#0}) $3 =
+// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) $3 =
 
 // === CDB TESTS ===================================================================================
 
 // cdb-command: g
 // cdb-command: dx b
-// cdb-check: b                : Unresumed [Type: enum2$<generator_objects::main::generator_env$0>]
+// cdb-check: b                : Unresumed [Type: enum2$<coroutine_objects::main::coroutine_env$0>]
 // cdb-check:    [+0x[...]] _ref__a          : 0x[...] : 5 [Type: int *]
 
 // cdb-command: g
 // cdb-command: dx b
-// cdb-check: b                : Suspend0 [Type: enum2$<generator_objects::main::generator_env$0>]
+// cdb-check: b                : Suspend0 [Type: enum2$<coroutine_objects::main::coroutine_env$0>]
 // cdb-check:    [+0x[...]] c                : 6 [Type: int]
 // cdb-check:    [+0x[...]] d                : 7 [Type: int]
 // cdb-check:    [+0x[...]] _ref__a          : 0x[...] : 5 [Type: int *]
 
 // cdb-command: g
 // cdb-command: dx b
-// cdb-check: b                : Suspend1 [Type: enum2$<generator_objects::main::generator_env$0>]
+// cdb-check: b                : Suspend1 [Type: enum2$<coroutine_objects::main::coroutine_env$0>]
 // cdb-check:    [+0x[...]] c                : 7 [Type: int]
 // cdb-check:    [+0x[...]] d                : 8 [Type: int]
 // cdb-check:    [+0x[...]] _ref__a          : 0x[...] : 6 [Type: int *]
 
 // cdb-command: g
 // cdb-command: dx b
-// cdb-check: b                : Returned [Type: enum2$<generator_objects::main::generator_env$0>]
+// 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, generators, generator_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
 #![omit_gdb_pretty_printer_section]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs
index d9aa03fee62..d29b3ea76b7 100644
--- a/tests/debuginfo/function-names.rs
+++ b/tests/debuginfo/function-names.rs
@@ -31,8 +31,8 @@
 // gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure_env#0});
 // gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}<i32, i32>(*mut function_names::{impl#2}::impl_function::{closure_env#0}<i32, i32>);
 
-// Generator
-// Generators don't seem to appear in GDB's symbol table.
+// Coroutine
+// Coroutines don't seem to appear in GDB's symbol table.
 
 // Const generic parameter
 // gdb-command:info functions -q function_names::const_generic_fn.*
@@ -69,9 +69,9 @@
 // cdb-check:[...] a!function_names::main::closure$0 (void)
 // cdb-check:[...] a!function_names::generic_func::closure$0<i32> (void)
 
-// Generator
-// cdb-command:x a!function_names::*::generator*
-// cdb-check:[...] a!function_names::main::generator$1 (void)
+// Coroutine
+// cdb-command:x a!function_names::*::coroutine*
+// cdb-check:[...] a!function_names::main::coroutine$1 (void)
 
 // Const generic parameter
 // cdb-command:x a!function_names::const_generic_fn*
@@ -83,10 +83,10 @@
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
-#![feature(adt_const_params, generators, generator_trait)]
+#![feature(adt_const_params, coroutines, coroutine_trait)]
 #![allow(incomplete_features)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 use Mod1::TestTrait2;
 
@@ -110,12 +110,12 @@ fn main() {
     let closure = || TestStruct1;
     closure();
 
-    // Generator
-    let mut generator = || {
+    // Coroutine
+    let mut coroutine = || {
         yield;
         return;
     };
-    Pin::new(&mut generator).resume(());
+    Pin::new(&mut coroutine).resume(());
 
     // Const generic functions
     const_generic_fn_bool::<false>();
diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs
index 62e7eb13c2d..a12a562a033 100644
--- a/tests/debuginfo/issue-57822.rs
+++ b/tests/debuginfo/issue-57822.rs
@@ -1,5 +1,5 @@
 // This test makes sure that the LLDB pretty printer does not throw an exception
-// for nested closures and generators.
+// for nested closures and coroutines.
 
 // Require a gdb that can read DW_TAG_variant_part.
 // min-gdb-version: 8.2
@@ -14,7 +14,7 @@
 // gdb-check:$1 = issue_57822::main::{closure_env#1} {f: issue_57822::main::{closure_env#0} {x: 1}}
 
 // gdb-command:print b
-// gdb-check:$2 = issue_57822::main::{generator_env#3}::Unresumed{a: issue_57822::main::{generator_env#2}::Unresumed{y: 2}}
+// gdb-check:$2 = issue_57822::main::{coroutine_env#3}::Unresumed{a: issue_57822::main::{coroutine_env#2}::Unresumed{y: 2}}
 
 // === LLDB TESTS ==================================================================================
 
@@ -24,12 +24,12 @@
 // lldbg-check:(issue_57822::main::{closure_env#1}) $0 = { f = { x = 1 } }
 
 // lldb-command:print b
-// lldbg-check:(issue_57822::main::{generator_env#3}) $1 =
+// lldbg-check:(issue_57822::main::{coroutine_env#3}) $1 =
 
-#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
+#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
 #![omit_gdb_pretty_printer_section]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
index bc4ca06c113..8b22743d2b0 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
@@ -1,5 +1,5 @@
-// MIR for `a::{closure#0}` 0 generator_resume
-/* generator_layout = GeneratorLayout {
+// MIR for `a::{closure#0}` 0 coroutine_resume
+/* coroutine_layout = CoroutineLayout {
     field_tys: {},
     variant_fields: {
         Unresumed(0): [],
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index 4a60e353bf2..f64b540c3a5 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -1,14 +1,14 @@
-// MIR for `b::{closure#0}` 0 generator_resume
-/* generator_layout = GeneratorLayout {
+// MIR for `b::{closure#0}` 0 coroutine_resume
+/* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: GeneratorSavedTy {
-            ty: Generator(
+        _0: CoroutineSavedTy {
+            ty: Coroutine(
                 DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
                 [
                 std::future::ResumeTy,
                 (),
                 (),
-                GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
+                CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
                 (),
                 ],
                 Static,
@@ -19,14 +19,14 @@
             },
             ignore_for_traits: false,
         },
-        _1: GeneratorSavedTy {
-            ty: Generator(
+        _1: CoroutineSavedTy {
+            ty: Coroutine(
                 DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
                 [
                 std::future::ResumeTy,
                 (),
                 (),
-                GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
+                CoroutineWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []),
                 (),
                 ],
                 Static,
diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs
index 74b15f2b98f..abdeafef6e4 100644
--- a/tests/mir-opt/building/async_await.rs
+++ b/tests/mir-opt/building/async_await.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-// This test makes sure that the generator MIR pass eliminates all calls to
+// This test makes sure that the coroutine MIR pass eliminates all calls to
 // `get_context`, and that the MIR argument type for an async fn and all locals
 // related to `yield` are `&mut Context`, and its return type is `Poll`.
 
@@ -8,10 +8,10 @@
 
 #![crate_type = "lib"]
 
-// EMIT_MIR async_await.a-{closure#0}.generator_resume.0.mir
+// EMIT_MIR async_await.a-{closure#0}.coroutine_resume.0.mir
 async fn a() {}
 
-// EMIT_MIR async_await.b-{closure#0}.generator_resume.0.mir
+// EMIT_MIR async_await.b-{closure#0}.coroutine_resume.0.mir
 pub async fn b() {
     a().await;
     a().await
diff --git a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
index 524fbeb0fea..25bffbe2488 100644
--- a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-abort.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir
@@ -1,10 +1,10 @@
-// MIR for `main::{closure#0}` 0 generator_drop
-/* generator_layout = GeneratorLayout {
+// MIR for `main::{closure#0}` 0 coroutine_drop
+/* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: GeneratorSavedTy {
+        _0: CoroutineSavedTy {
             ty: std::string::String,
             source_info: SourceInfo {
-                span: $DIR/generator_drop_cleanup.rs:12:13: 12:15 (#0),
+                span: $DIR/coroutine_drop_cleanup.rs:12:13: 12:15 (#0),
                 scope: scope[0],
             },
             ignore_for_traits: false,
@@ -21,7 +21,7 @@
     },
 } */
 
-fn main::{closure#0}(_1: *mut {generator@$DIR/generator_drop_cleanup.rs:11:15: 11:17}) -> () {
+fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
     let mut _0: ();
     let mut _2: ();
     let _3: std::string::String;
diff --git a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
index c3f61169bfb..2eac754b15c 100644
--- a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.panic-unwind.mir
+++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir
@@ -1,10 +1,10 @@
-// MIR for `main::{closure#0}` 0 generator_drop
-/* generator_layout = GeneratorLayout {
+// MIR for `main::{closure#0}` 0 coroutine_drop
+/* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: GeneratorSavedTy {
+        _0: CoroutineSavedTy {
             ty: std::string::String,
             source_info: SourceInfo {
-                span: $DIR/generator_drop_cleanup.rs:12:13: 12:15 (#0),
+                span: $DIR/coroutine_drop_cleanup.rs:12:13: 12:15 (#0),
                 scope: scope[0],
             },
             ignore_for_traits: false,
@@ -21,7 +21,7 @@
     },
 } */
 
-fn main::{closure#0}(_1: *mut {generator@$DIR/generator_drop_cleanup.rs:11:15: 11:17}) -> () {
+fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
     let mut _0: ();
     let mut _2: ();
     let _3: std::string::String;
diff --git a/tests/mir-opt/generator_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs
index fb67031f774..69984c737fe 100644
--- a/tests/mir-opt/generator_drop_cleanup.rs
+++ b/tests/mir-opt/coroutine_drop_cleanup.rs
@@ -1,12 +1,12 @@
 // skip-filecheck
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-// Regression test for #58892, generator drop shims should not have blocks
+// Regression test for #58892, coroutine drop shims should not have blocks
 // spuriously marked as cleanup
 
-// EMIT_MIR generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
+// EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir
 fn main() {
     let gen = || {
         let _s = String::new();
diff --git a/tests/mir-opt/generator_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 169d817675e..8369a3e60dd 100644
--- a/tests/mir-opt/generator_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: {generator@$DIR/generator_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
+fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
 yields ()
  {
     let mut _0: ();
@@ -78,6 +78,6 @@ yields ()
     }
 
     bb8: {
-        generator_drop;
+        coroutine_drop;
     }
 }
diff --git a/tests/mir-opt/generator_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 45e9c01b931..1773db1abff 100644
--- a/tests/mir-opt/generator_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: {generator@$DIR/generator_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
+fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
 yields ()
  {
     let mut _0: ();
@@ -78,7 +78,7 @@ yields ()
     }
 
     bb8: {
-        generator_drop;
+        coroutine_drop;
     }
 
     bb9 (cleanup): {
diff --git a/tests/mir-opt/generator_storage_dead_unwind.rs b/tests/mir-opt/coroutine_storage_dead_unwind.rs
index 91f3a20befd..253be1ff698 100644
--- a/tests/mir-opt/generator_storage_dead_unwind.rs
+++ b/tests/mir-opt/coroutine_storage_dead_unwind.rs
@@ -1,12 +1,12 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-// Test that we generate StorageDead on unwind paths for generators.
+// Test that we generate StorageDead on unwind paths for coroutines.
 //
 // Basic block and local names can safely change, but the StorageDead statements
 // should not go away.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 struct Foo(i32);
 
@@ -18,7 +18,7 @@ struct Bar(i32);
 
 fn take<T>(_x: T) {}
 
-// EMIT_MIR generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
+// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
 fn main() {
     let _gen = || {
         let a = Foo(5);
diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
index 7047a5baae5..17b99c87c39 100644
--- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
@@ -1,10 +1,10 @@
-// MIR for `main::{closure#0}` 0 generator_resume
-/* generator_layout = GeneratorLayout {
+// MIR for `main::{closure#0}` 0 coroutine_resume
+/* coroutine_layout = CoroutineLayout {
     field_tys: {
-        _0: GeneratorSavedTy {
+        _0: CoroutineSavedTy {
             ty: HasDrop,
             source_info: SourceInfo {
-                span: $DIR/generator_tiny.rs:21:13: 21:15 (#0),
+                span: $DIR/coroutine_tiny.rs:21:13: 21:15 (#0),
                 scope: scope[0],
             },
             ignore_for_traits: false,
@@ -21,9 +21,9 @@
     },
 } */
 
-fn main::{closure#0}(_1: Pin<&mut {generator@$DIR/generator_tiny.rs:20:16: 20:24}>, _2: u8) -> GeneratorState<(), ()> {
+fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}>, _2: u8) -> CoroutineState<(), ()> {
     debug _x => _10;
-    let mut _0: std::ops::GeneratorState<(), ()>;
+    let mut _0: std::ops::CoroutineState<(), ()>;
     let _3: HasDrop;
     let mut _4: !;
     let mut _5: ();
@@ -34,18 +34,18 @@ fn main::{closure#0}(_1: Pin<&mut {generator@$DIR/generator_tiny.rs:20:16: 20:24
     let _10: u8;
     let mut _11: u32;
     scope 1 {
-        debug _d => (((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop);
+        debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop);
     }
 
     bb0: {
-        _11 = discriminant((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:20:16: 20:24})));
+        _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})));
         switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6];
     }
 
     bb1: {
         _10 = move _2;
         nop;
-        (((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop) = HasDrop;
+        (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop) = HasDrop;
         StorageLive(_4);
         goto -> bb2;
     }
@@ -54,8 +54,8 @@ fn main::{closure#0}(_1: Pin<&mut {generator@$DIR/generator_tiny.rs:20:16: 20:24
         StorageLive(_6);
         StorageLive(_7);
         _7 = ();
-        _0 = GeneratorState::<(), ()>::Yielded(move _7);
-        discriminant((*(_1.0: &mut {generator@$DIR/generator_tiny.rs:20:16: 20:24}))) = 3;
+        _0 = CoroutineState::<(), ()>::Yielded(move _7);
+        discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))) = 3;
         return;
     }
 
diff --git a/tests/mir-opt/generator_tiny.rs b/tests/mir-opt/coroutine_tiny.rs
index e5570d74bbb..0fd785b28f8 100644
--- a/tests/mir-opt/generator_tiny.rs
+++ b/tests/mir-opt/coroutine_tiny.rs
@@ -1,11 +1,11 @@
 // skip-filecheck
-//! Tests that generators that cannot return or unwind don't have unnecessary
+//! Tests that coroutines that cannot return or unwind don't have unnecessary
 //! panic branches.
 
 // compile-flags: -C panic=abort
 // no-prefer-dynamic
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 struct HasDrop;
 
@@ -15,7 +15,7 @@ impl Drop for HasDrop {
 
 fn callee() {}
 
-// EMIT_MIR generator_tiny.main-{closure#0}.generator_resume.0.mir
+// EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
 fn main() {
     let _gen = |_x: u8| {
         let _d = HasDrop;
diff --git a/tests/mir-opt/inline/inline_async.rs b/tests/mir-opt/inline/inline_async.rs
index 932dc5635f0..1de87e1e43c 100644
--- a/tests/mir-opt/inline/inline_async.rs
+++ b/tests/mir-opt/inline/inline_async.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-// Checks that inliner doesn't introduce cycles when optimizing generators.
+// Checks that inliner doesn't introduce cycles when optimizing coroutines.
 // The outcome of optimization is not verfied, just the absence of the cycle.
 // Regression test for #76181.
 //
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 48d908fad88..357d95f7c22 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -3,27 +3,27 @@
   
   fn main() -> () {
       let mut _0: ();
-      let _1: std::ops::GeneratorState<i32, bool>;
-      let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>;
-      let mut _3: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8};
-      let mut _4: {generator@$DIR/inline_generator.rs:17:5: 17:8};
+      let _1: std::ops::CoroutineState<i32, bool>;
+      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>;
+      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
+      let mut _4: {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
 +     let mut _5: bool;
       scope 1 {
           debug _r => _1;
       }
 +     scope 2 (inlined g) {
 +     }
-+     scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new) {
++     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 {
-+             scope 5 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new_unchecked) {
++             scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new_unchecked) {
 +                 debug pointer => _3;
 +             }
 +         }
 +     }
 +     scope 6 (inlined g::{closure#0}) {
 +         debug a => _5;
-+         let mut _6: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8};
++         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
 +         let mut _7: u32;
 +         let mut _8: i32;
 +     }
@@ -34,22 +34,22 @@
           StorageLive(_3);
           StorageLive(_4);
 -         _4 = g() -> [return: bb1, unwind unreachable];
-+         _4 = {generator@$DIR/inline_generator.rs:17:5: 17:8 (#0)};
++         _4 = {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8 (#0)};
 +         _3 = &mut _4;
-+         _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}> { pointer: move _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}> { pointer: move _3 };
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
 +         StorageLive(_6);
 +         StorageLive(_7);
-+         _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8});
++         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
       }
   
       bb1: {
 -         _3 = &mut _4;
--         _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind unreachable];
+-         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind unreachable];
 +         StorageDead(_7);
 +         StorageDead(_6);
 +         StorageDead(_5);
@@ -59,7 +59,7 @@
   
       bb2: {
 -         StorageDead(_3);
--         _1 = <{generator@$DIR/inline_generator.rs:17:5: 17:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
+-         _1 = <{coroutine@$DIR/inline_coroutine.rs:17:5: 17:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
 +         StorageDead(_4);
 +         _0 = const ();
 +         StorageDead(_1);
@@ -88,19 +88,19 @@
 +     }
 + 
 +     bb6: {
-+         _1 = GeneratorState::<i32, bool>::Yielded(move _8);
++         _1 = CoroutineState::<i32, bool>::Yielded(move _8);
 +         discriminant((*_6)) = 3;
 +         goto -> bb1;
 +     }
 + 
 +     bb7: {
-+         assert(const false, "generator resumed after completion") -> [success: bb7, unwind unreachable];
++         assert(const false, "coroutine resumed after completion") -> [success: bb7, unwind unreachable];
 +     }
 + 
 +     bb8: {
 +         StorageLive(_8);
 +         StorageDead(_8);
-+         _1 = GeneratorState::<i32, bool>::Complete(_5);
++         _1 = CoroutineState::<i32, bool>::Complete(_5);
 +         discriminant((*_6)) = 1;
 +         goto -> bb1;
 +     }
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 9cb84b314de..e7d02096838 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -3,27 +3,27 @@
   
   fn main() -> () {
       let mut _0: ();
-      let _1: std::ops::GeneratorState<i32, bool>;
-      let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>;
-      let mut _3: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8};
-      let mut _4: {generator@$DIR/inline_generator.rs:17:5: 17:8};
+      let _1: std::ops::CoroutineState<i32, bool>;
+      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>;
+      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
+      let mut _4: {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
 +     let mut _5: bool;
       scope 1 {
           debug _r => _1;
       }
 +     scope 2 (inlined g) {
 +     }
-+     scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new) {
++     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 {
-+             scope 5 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new_unchecked) {
++             scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new_unchecked) {
 +                 debug pointer => _3;
 +             }
 +         }
 +     }
 +     scope 6 (inlined g::{closure#0}) {
 +         debug a => _5;
-+         let mut _6: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8};
++         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
 +         let mut _7: u32;
 +         let mut _8: i32;
 +     }
@@ -37,20 +37,20 @@
 -     }
 - 
 -     bb1: {
-+         _4 = {generator@$DIR/inline_generator.rs:17:5: 17:8 (#0)};
++         _4 = {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8 (#0)};
           _3 = &mut _4;
--         _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind: bb5];
+-         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind: bb5];
 -     }
 - 
 -     bb2: {
-+         _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:17:5: 17:8}> { pointer: move _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}> { pointer: move _3 };
           StorageDead(_3);
--         _1 = <{generator@$DIR/inline_generator.rs:17:5: 17:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
+-         _1 = <{coroutine@$DIR/inline_coroutine.rs:17:5: 17:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
 +         StorageLive(_5);
 +         _5 = const false;
 +         StorageLive(_6);
 +         StorageLive(_7);
-+         _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:17:5: 17:8});
++         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
       }
@@ -100,19 +100,19 @@
 +     }
 + 
 +     bb8: {
-+         _1 = GeneratorState::<i32, bool>::Yielded(move _8);
++         _1 = CoroutineState::<i32, bool>::Yielded(move _8);
 +         discriminant((*_6)) = 3;
 +         goto -> bb1;
 +     }
 + 
 +     bb9: {
-+         assert(const false, "generator resumed after completion") -> [success: bb9, unwind: bb3];
++         assert(const false, "coroutine resumed after completion") -> [success: bb9, unwind: bb3];
 +     }
 + 
 +     bb10: {
 +         StorageLive(_8);
 +         StorageDead(_8);
-+         _1 = GeneratorState::<i32, bool>::Complete(_5);
++         _1 = CoroutineState::<i32, bool>::Complete(_5);
 +         discriminant((*_6)) = 1;
 +         goto -> bb1;
 +     }
diff --git a/tests/mir-opt/inline/inline_generator.rs b/tests/mir-opt/inline/inline_coroutine.rs
index d96d1f98f14..d021cdac28e 100644
--- a/tests/mir-opt/inline/inline_generator.rs
+++ b/tests/mir-opt/inline/inline_coroutine.rs
@@ -1,18 +1,18 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Zinline-mir-hint-threshold=1000
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
-// EMIT_MIR inline_generator.main.Inline.diff
+// EMIT_MIR inline_coroutine.main.Inline.diff
 fn main() {
     let _r = Pin::new(&mut g()).resume(false);
 }
 
 #[inline]
-pub fn g() -> impl Generator<bool> {
+pub fn g() -> impl Coroutine<bool> {
     #[inline]
     |a| { yield if a { 7 } else { 13 } }
 }
diff --git a/tests/run-coverage/generator.coverage b/tests/run-coverage/coroutine.coverage
index daba2bea8b8..3a9791a0dbd 100644
--- a/tests/run-coverage/generator.coverage
+++ b/tests/run-coverage/coroutine.coverage
@@ -1,11 +1,11 @@
-   LL|       |#![feature(generators, generator_trait)]
+   LL|       |#![feature(coroutines, coroutine_trait)]
    LL|       |
-   LL|       |use std::ops::{Generator, GeneratorState};
+   LL|       |use std::ops::{Coroutine, CoroutineState};
    LL|       |use std::pin::Pin;
    LL|       |
    LL|       |// The following implementation of a function called from a `yield` statement
    LL|       |// (apparently requiring the Result and the `String` type or constructor)
-   LL|       |// creates conditions where the `generator::StateTransform` MIR transform will
+   LL|       |// creates conditions where the `coroutine::StateTransform` MIR transform will
    LL|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
    LL|       |// to handle this condition, and still report dead block coverage.
    LL|      1|fn get_u32(val: bool) -> Result<u32, String> {
@@ -15,17 +15,17 @@
    LL|       |
    LL|      1|fn main() {
    LL|      1|    let is_true = std::env::args().len() == 1;
-   LL|      1|    let mut generator = || {
+   LL|      1|    let mut coroutine = || {
    LL|      1|        yield get_u32(is_true);
    LL|      1|        return "foo";
    LL|      1|    };
    LL|       |
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Yielded(Ok(1)) => {}
    LL|      0|        _ => panic!("unexpected return from resume"),
    LL|       |    }
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Complete("foo") => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Complete("foo") => {}
    LL|      0|        _ => panic!("unexpected return from resume"),
    LL|       |    }
    LL|      1|}
diff --git a/tests/run-coverage/generator.rs b/tests/run-coverage/coroutine.rs
index 4319991021e..86d19af6f4f 100644
--- a/tests/run-coverage/generator.rs
+++ b/tests/run-coverage/coroutine.rs
@@ -1,11 +1,11 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 // The following implementation of a function called from a `yield` statement
 // (apparently requiring the Result and the `String` type or constructor)
-// creates conditions where the `generator::StateTransform` MIR transform will
+// creates conditions where the `coroutine::StateTransform` MIR transform will
 // drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
 // to handle this condition, and still report dead block coverage.
 fn get_u32(val: bool) -> Result<u32, String> {
@@ -14,17 +14,17 @@ fn get_u32(val: bool) -> Result<u32, String> {
 
 fn main() {
     let is_true = std::env::args().len() == 1;
-    let mut generator = || {
+    let mut coroutine = || {
         yield get_u32(is_true);
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(Ok(1)) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(Ok(1)) => {}
         _ => panic!("unexpected return from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
         _ => panic!("unexpected return from resume"),
     }
 }
diff --git a/tests/run-coverage/fn_sig_into_try.coverage b/tests/run-coverage/fn_sig_into_try.coverage
new file mode 100644
index 00000000000..f1ddb1da780
--- /dev/null
+++ b/tests/run-coverage/fn_sig_into_try.coverage
@@ -0,0 +1,45 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |// Regression test for inconsistent handling of function signature spans that
+   LL|       |// are followed by code using the `?` operator.
+   LL|       |//
+   LL|       |// For each of these similar functions, the line containing the function
+   LL|       |// signature should be handled in the same way.
+   LL|       |
+   LL|      1|fn a() -> Option<i32>
+   LL|      1|{
+   LL|      1|    Some(7i32);
+   LL|      1|    Some(0)
+   LL|      1|}
+   LL|       |
+   LL|      1|fn b() -> Option<i32>
+   LL|      1|{
+   LL|      1|    Some(7i32)?;
+                            ^0
+   LL|      1|    Some(0)
+   LL|      1|}
+   LL|       |
+   LL|      1|fn c() -> Option<i32>
+   LL|      1|{
+   LL|      1|    let _ = Some(7i32)?;
+                                    ^0
+   LL|      1|    Some(0)
+   LL|      1|}
+   LL|       |
+   LL|      1|fn d() -> Option<i32>
+   LL|      1|{
+   LL|      1|    let _: () = ();
+   LL|      1|    Some(7i32)?;
+                            ^0
+   LL|      1|    Some(0)
+   LL|      1|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    a();
+   LL|       |    b();
+   LL|       |    c();
+   LL|       |    d();
+   LL|       |}
+
diff --git a/tests/run-coverage/fn_sig_into_try.rs b/tests/run-coverage/fn_sig_into_try.rs
new file mode 100644
index 00000000000..92850c8a188
--- /dev/null
+++ b/tests/run-coverage/fn_sig_into_try.rs
@@ -0,0 +1,41 @@
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// Regression test for inconsistent handling of function signature spans that
+// are followed by code using the `?` operator.
+//
+// For each of these similar functions, the line containing the function
+// signature should be handled in the same way.
+
+fn a() -> Option<i32>
+{
+    Some(7i32);
+    Some(0)
+}
+
+fn b() -> Option<i32>
+{
+    Some(7i32)?;
+    Some(0)
+}
+
+fn c() -> Option<i32>
+{
+    let _ = Some(7i32)?;
+    Some(0)
+}
+
+fn d() -> Option<i32>
+{
+    let _: () = ();
+    Some(7i32)?;
+    Some(0)
+}
+
+#[coverage(off)]
+fn main() {
+    a();
+    b();
+    c();
+    d();
+}
diff --git a/tests/run-coverage/issue-84561.coverage b/tests/run-coverage/issue-84561.coverage
index 222f877d36a..e693866e277 100644
--- a/tests/run-coverage/issue-84561.coverage
+++ b/tests/run-coverage/issue-84561.coverage
@@ -135,7 +135,7 @@
    LL|      0|}
    LL|       |
    LL|       |impl std::fmt::Debug for Foo {
-   LL|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   LL|      7|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    LL|      7|        write!(f, "try and succeed")?;
                                                   ^0
    LL|      7|        Ok(())
diff --git a/tests/run-coverage/yield.coverage b/tests/run-coverage/yield.coverage
index 90c2641a7d6..d7e455f211e 100644
--- a/tests/run-coverage/yield.coverage
+++ b/tests/run-coverage/yield.coverage
@@ -1,37 +1,37 @@
-   LL|       |#![feature(generators, generator_trait)]
+   LL|       |#![feature(coroutines, coroutine_trait)]
    LL|       |#![allow(unused_assignments)]
    LL|       |
-   LL|       |use std::ops::{Generator, GeneratorState};
+   LL|       |use std::ops::{Coroutine, CoroutineState};
    LL|       |use std::pin::Pin;
    LL|       |
    LL|      1|fn main() {
-   LL|      1|    let mut generator = || {
+   LL|      1|    let mut coroutine = || {
    LL|      1|        yield 1;
    LL|      1|        return "foo";
    LL|      1|    };
    LL|       |
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Yielded(1) => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Yielded(1) => {}
    LL|      0|        _ => panic!("unexpected value from resume"),
    LL|       |    }
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Complete("foo") => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Complete("foo") => {}
    LL|      0|        _ => panic!("unexpected value from resume"),
    LL|       |    }
    LL|       |
-   LL|      1|    let mut generator = || {
+   LL|      1|    let mut coroutine = || {
    LL|      1|        yield 1;
    LL|      1|        yield 2;
    LL|      0|        yield 3;
    LL|      0|        return "foo";
    LL|      0|    };
    LL|       |
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Yielded(1) => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Yielded(1) => {}
    LL|      0|        _ => panic!("unexpected value from resume"),
    LL|       |    }
-   LL|      1|    match Pin::new(&mut generator).resume(()) {
-   LL|      1|        GeneratorState::Yielded(2) => {}
+   LL|      1|    match Pin::new(&mut coroutine).resume(()) {
+   LL|      1|        CoroutineState::Yielded(2) => {}
    LL|      0|        _ => panic!("unexpected value from resume"),
    LL|       |    }
    LL|      1|}
diff --git a/tests/run-coverage/yield.rs b/tests/run-coverage/yield.rs
index 361275c9215..b7e2ba31b59 100644
--- a/tests/run-coverage/yield.rs
+++ b/tests/run-coverage/yield.rs
@@ -1,37 +1,37 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![allow(unused_assignments)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut generator = || {
+    let mut coroutine = || {
         yield 1;
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Complete("foo") => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Complete("foo") => {}
         _ => panic!("unexpected value from resume"),
     }
 
-    let mut generator = || {
+    let mut coroutine = || {
         yield 1;
         yield 2;
         yield 3;
         return "foo";
     };
 
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(1) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match Pin::new(&mut generator).resume(()) {
-        GeneratorState::Yielded(2) => {}
+    match Pin::new(&mut coroutine).resume(()) {
+        CoroutineState::Yielded(2) => {}
         _ => panic!("unexpected value from resume"),
     }
 }
diff --git a/tests/rustdoc-ui/error-in-impl-trait/closure.rs b/tests/rustdoc-ui/error-in-impl-trait/closure.rs
index f1fd85bb23c..628c61a6a1a 100644
--- a/tests/rustdoc-ui/error-in-impl-trait/closure.rs
+++ b/tests/rustdoc-ui/error-in-impl-trait/closure.rs
@@ -1,5 +1,5 @@
 // check-pass
-// manually desugared version of an `async fn` (but with a closure instead of a generator)
+// manually desugared version of an `async fn` (but with a closure instead of a coroutine)
 pub fn a() -> impl Fn() -> u32 {
     || content::doesnt::matter()
 }
diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
index 3f7429a5fcc..ae7f341fe4e 100644
--- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
+++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -29,8 +29,8 @@ fn main() {
         TyKind::FnPtr(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Dynamic(..) => (),          //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Closure(..) => (),          //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Generator(..) => (),        //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Coroutine(..) => (),        //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::CoroutineWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Never => (),                //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Tuple(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Alias(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
index 1f49d6b6464..45b7c26faad 100644
--- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
+++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -109,13 +109,13 @@ LL |         TyKind::Closure(..) => (),
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:32:9
    |
-LL |         TyKind::Generator(..) => (),
+LL |         TyKind::Coroutine(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:33:9
    |
-LL |         TyKind::GeneratorWitness(..) => (),
+LL |         TyKind::CoroutineWitness(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
diff --git a/tests/ui-fulldeps/stable-mir/instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index fe06d9b5cc9..288c163a6a3 100644
--- a/tests/ui-fulldeps/stable-mir/instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -15,7 +15,8 @@ extern crate rustc_smir;
 extern crate stable_mir;
 
 use rustc_middle::ty::TyCtxt;
-
+use mir::{mono::Instance, TerminatorKind::*};
+use stable_mir::ty::{TyKind, RigidTy};
 use stable_mir::*;
 use rustc_smir::rustc_internal;
 use std::io::Write;
@@ -43,9 +44,28 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     // For all generic items, try_from should fail.
     assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err()));
 
+    for instance in instances {
+        test_body(instance.body())
+    }
     ControlFlow::Continue(())
 }
 
+/// Inspect the instance body
+fn test_body(body: mir::Body) {
+    for term in body.blocks.iter().map(|bb| &bb.terminator) {
+        match &term.kind {
+            Call{ func, .. } => {
+                let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() };
+                let RigidTy::FnDef(def, args) = ty else { unreachable!() };
+                let result = Instance::resolve(def, &args);
+                assert!(result.is_ok());
+            }
+            Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */}
+            _ => { unreachable!("Unexpected terminator {term:?}") }
+        }
+    }
+}
+
 
 /// This test will generate and analyze a dummy crate using the stable mir.
 /// For that, it will first write the dummy crate into a file.
@@ -56,6 +76,7 @@ fn main() {
     generate_input(&path).unwrap();
     let args = vec![
         "rustc".to_string(),
+        "-Cpanic=abort".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
         CRATE_NAME.to_string(),
@@ -78,6 +99,9 @@ fn generate_input(path: &str) -> std::io::Result<()> {
     }}
 
     pub fn monomorphic() {{
+        let v = vec![10];
+        let dup = ty_param(&v);
+        assert_eq!(v, dup);
     }}
 
     pub mod foo {{
diff --git a/tests/ui/async-await/generator-desc.rs b/tests/ui/async-await/coroutine-desc.rs
index 50081201667..50081201667 100644
--- a/tests/ui/async-await/generator-desc.rs
+++ b/tests/ui/async-await/coroutine-desc.rs
diff --git a/tests/ui/async-await/generator-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr
index d3e951cfe49..e4cb0915a10 100644
--- a/tests/ui/async-await/generator-desc.stderr
+++ b/tests/ui/async-await/coroutine-desc.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/generator-desc.rs:10:19
+  --> $DIR/coroutine-desc.rs:10:19
    |
 LL |     fun(async {}, async {});
    |     --- --------  ^^^^^^^^ expected `async` block, found a different `async` block
@@ -7,16 +7,16 @@ LL |     fun(async {}, async {});
    |     |   the expected `async` block
    |     arguments to this function are incorrect
    |
-   = note: expected `async` block `{async block@$DIR/generator-desc.rs:10:9: 10:17}`
-              found `async` block `{async block@$DIR/generator-desc.rs:10:19: 10:27}`
+   = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
+              found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:27}`
 note: function defined here
-  --> $DIR/generator-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:8:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^                                -----
 
 error[E0308]: mismatched types
-  --> $DIR/generator-desc.rs:12:16
+  --> $DIR/coroutine-desc.rs:12:16
    |
 LL |     fun(one(), two());
    |     ---        ^^^^^ expected future, found a different future
@@ -26,13 +26,13 @@ LL |     fun(one(), two());
    = help: consider `await`ing on both `Future`s
    = note: distinct uses of `impl Trait` result in different opaque types
 note: function defined here
-  --> $DIR/generator-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:8:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^                                -----
 
 error[E0308]: mismatched types
-  --> $DIR/generator-desc.rs:14:26
+  --> $DIR/coroutine-desc.rs:14:26
    |
 LL |     fun((async || {})(), (async || {})());
    |     ---           --     ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
@@ -40,10 +40,10 @@ LL |     fun((async || {})(), (async || {})());
    |     |             the expected `async` closure body
    |     arguments to this function are incorrect
    |
-   = note: expected `async` closure body `{async closure body@$DIR/generator-desc.rs:14:19: 14:21}`
-              found `async` closure body `{async closure body@$DIR/generator-desc.rs:14:36: 14:38}`
+   = note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}`
+              found `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:36: 14:38}`
 note: function defined here
-  --> $DIR/generator-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:8:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^                                -----
diff --git a/tests/ui/async-await/generator-not-future.rs b/tests/ui/async-await/coroutine-not-future.rs
index 37d7cfa6fb7..b18635fea39 100644
--- a/tests/ui/async-await/generator-not-future.rs
+++ b/tests/ui/async-await/coroutine-not-future.rs
@@ -1,42 +1,42 @@
 // edition:2018
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::future::Future;
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 async fn async_fn() {}
 fn returns_async_block() -> impl Future<Output = ()> {
     async {}
 }
-fn returns_generator() -> impl Generator<(), Yield = (), Return = ()> {
+fn returns_coroutine() -> impl Coroutine<(), Yield = (), Return = ()> {
     || {
         let _: () = yield ();
     }
 }
 
 fn takes_future(_f: impl Future<Output = ()>) {}
-fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
+fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
 
 fn main() {
     // okay:
     takes_future(async_fn());
     takes_future(returns_async_block());
     takes_future(async {});
-    takes_generator(returns_generator());
-    takes_generator(|| {
+    takes_coroutine(returns_coroutine());
+    takes_coroutine(|| {
         let _: () = yield ();
     });
 
-    // async futures are not generators:
-    takes_generator(async_fn());
+    // async futures are not coroutines:
+    takes_coroutine(async_fn());
     //~^ ERROR the trait bound
-    takes_generator(returns_async_block());
+    takes_coroutine(returns_async_block());
     //~^ ERROR the trait bound
-    takes_generator(async {});
+    takes_coroutine(async {});
     //~^ ERROR the trait bound
 
-    // generators are not futures:
-    takes_future(returns_generator());
+    // coroutines are not futures:
+    takes_future(returns_coroutine());
     //~^ ERROR is not a future
     takes_future(|ctx| {
         //~^ ERROR is not a future
diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr
new file mode 100644
index 00000000000..130c5ef526b
--- /dev/null
+++ b/tests/ui/async-await/coroutine-not-future.stderr
@@ -0,0 +1,81 @@
+error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
+  --> $DIR/coroutine-not-future.rs:31:21
+   |
+LL |     takes_coroutine(async_fn());
+   |     --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `takes_coroutine`
+  --> $DIR/coroutine-not-future.rs:18: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
+   |
+LL |     takes_coroutine(returns_async_block());
+   |     --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `takes_coroutine`
+  --> $DIR/coroutine-not-future.rs:18: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
+   |
+LL |     takes_coroutine(async {});
+   |     --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:35:21: 35:29}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `takes_coroutine`
+  --> $DIR/coroutine-not-future.rs:18: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
+   |
+LL |     takes_future(returns_coroutine());
+   |     ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine<Yield = (), Return = ()>` is not a future
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
+   = note: impl Coroutine<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `takes_future`
+  --> $DIR/coroutine-not-future.rs:17: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
+   |
+LL |       takes_future(|ctx| {
+   |  _____------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         ctx = yield ();
+LL | |     });
+   | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
+   |
+   = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}`
+   = note: {coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `takes_future`
+  --> $DIR/coroutine-not-future.rs:17:26
+   |
+LL | fn takes_future(_f: impl Future<Output = ()>) {}
+   |                          ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
index d63911b0d3c..b0447a58261 100644
--- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -19,18 +19,18 @@ print-type-size     variant `Suspend0`: 2052 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         padding: 1 bytes
 print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
-print-type-size         local `..generator_field4`: 1 bytes
+print-type-size         local `..coroutine_field4`: 1 bytes
 print-type-size         local `.__awaitee`: 1 bytes
 print-type-size     variant `Suspend1`: 3076 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         padding: 1026 bytes
-print-type-size         local `..generator_field4`: 1 bytes, alignment: 1 bytes
+print-type-size         local `..coroutine_field4`: 1 bytes, alignment: 1 bytes
 print-type-size         local `.__awaitee`: 1025 bytes
 print-type-size     variant `Suspend2`: 2052 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         padding: 1 bytes
 print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
-print-type-size         local `..generator_field4`: 1 bytes
+print-type-size         local `..coroutine_field4`: 1 bytes
 print-type-size         local `.__awaitee`: 1 bytes
 print-type-size     variant `Returned`: 1025 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
diff --git a/tests/ui/async-await/generator-not-future.stderr b/tests/ui/async-await/generator-not-future.stderr
deleted file mode 100644
index 540501b9826..00000000000
--- a/tests/ui/async-await/generator-not-future.stderr
+++ /dev/null
@@ -1,81 +0,0 @@
-error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
-  --> $DIR/generator-not-future.rs:31:21
-   |
-LL |     takes_generator(async_fn());
-   |     --------------- ^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `takes_generator`
-  --> $DIR/generator-not-future.rs:18:39
-   |
-LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
-
-error[E0277]: the trait bound `impl Future<Output = ()>: Generator<_>` is not satisfied
-  --> $DIR/generator-not-future.rs:33:21
-   |
-LL |     takes_generator(returns_async_block());
-   |     --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `takes_generator`
-  --> $DIR/generator-not-future.rs:18:39
-   |
-LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
-
-error[E0277]: the trait bound `{async block@$DIR/generator-not-future.rs:35:21: 35:29}: Generator<_>` is not satisfied
-  --> $DIR/generator-not-future.rs:35:21
-   |
-LL |     takes_generator(async {});
-   |     --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `{async block@$DIR/generator-not-future.rs:35:21: 35:29}`
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `takes_generator`
-  --> $DIR/generator-not-future.rs:18:39
-   |
-LL | fn takes_generator<ResumeTy>(_g: impl Generator<ResumeTy, Yield = (), Return = ()>) {}
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator`
-
-error[E0277]: `impl Generator<Yield = (), Return = ()>` is not a future
-  --> $DIR/generator-not-future.rs:39:18
-   |
-LL |     takes_future(returns_generator());
-   |     ------------ ^^^^^^^^^^^^^^^^^^^ `impl Generator<Yield = (), Return = ()>` is not a future
-   |     |
-   |     required by a bound introduced by this call
-   |
-   = help: the trait `Future` is not implemented for `impl Generator<Yield = (), Return = ()>`
-   = note: impl Generator<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `takes_future`
-  --> $DIR/generator-not-future.rs:17:26
-   |
-LL | fn takes_future(_f: impl Future<Output = ()>) {}
-   |                          ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
-
-error[E0277]: `{generator@$DIR/generator-not-future.rs:41:18: 41:23}` is not a future
-  --> $DIR/generator-not-future.rs:41:18
-   |
-LL |       takes_future(|ctx| {
-   |  _____------------_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |         ctx = yield ();
-LL | |     });
-   | |_____^ `{generator@$DIR/generator-not-future.rs:41:18: 41:23}` is not a future
-   |
-   = help: the trait `Future` is not implemented for `{generator@$DIR/generator-not-future.rs:41:18: 41:23}`
-   = note: {generator@$DIR/generator-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `takes_future`
-  --> $DIR/generator-not-future.rs:17:26
-   |
-LL | fn takes_future(_f: impl Future<Output = ()>) {}
-   |                          ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs
index 61f6ed1b7b2..2cda40e9e11 100644
--- a/tests/ui/async-await/issue-60709.rs
+++ b/tests/ui/async-await/issue-60709.rs
@@ -1,5 +1,5 @@
 // This used to compile the future down to ud2, due to uninhabited types being
-// handled incorrectly in generators.
+// handled incorrectly in coroutines.
 // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
 
 // run-pass
diff --git a/tests/ui/async-await/issue-61793.rs b/tests/ui/async-await/issue-61793.rs
index 9180e1d811a..bb861cf60b1 100644
--- a/tests/ui/async-await/issue-61793.rs
+++ b/tests/ui/async-await/issue-61793.rs
@@ -1,5 +1,5 @@
 // This testcase used to ICE in codegen due to inconsistent field reordering
-// in the generator state, claiming a ZST field was after a non-ZST field,
+// in the coroutine state, claiming a ZST field was after a non-ZST field,
 // while those two fields were at the same offset (which is impossible).
 // That is, memory ordering of `(X, ())`, but offsets of `((), X)`.
 
diff --git a/tests/ui/async-await/issue-62658.rs b/tests/ui/async-await/issue-62658.rs
index d0af01e0c00..8e6d070ea3f 100644
--- a/tests/ui/async-await/issue-62658.rs
+++ b/tests/ui/async-await/issue-62658.rs
@@ -1,4 +1,4 @@
-// This test created a generator whose size was not rounded to a multiple of its
+// This test created a coroutine whose size was not rounded to a multiple of its
 // alignment. This caused an assertion error in codegen.
 
 // build-pass
diff --git a/tests/ui/async-await/issue-73137.rs b/tests/ui/async-await/issue-73137.rs
index c43ce2cadba..2d16f193644 100644
--- a/tests/ui/async-await/issue-73137.rs
+++ b/tests/ui/async-await/issue-73137.rs
@@ -28,7 +28,7 @@ fn main() {
             a: async { 0 }.await,
         };
 
-        // An error in the generator transform caused `b` to be overwritten with `a` when `b` was
+        // An error in the coroutine transform caused `b` to be overwritten with `a` when `b` was
         // borrowed.
         nop(&action.b);
         assert_ne!(0usize, unsafe { std::mem::transmute(action.b) });
diff --git a/tests/ui/async-await/issues/issue-51719.rs b/tests/ui/async-await/issues/issue-51719.rs
index 09241f982aa..1cf388cd8ab 100644
--- a/tests/ui/async-await/issues/issue-51719.rs
+++ b/tests/ui/async-await/issues/issue-51719.rs
@@ -1,10 +1,10 @@
 // edition:2018
 //
-// Tests that the .await syntax can't be used to make a generator
+// Tests that the .await syntax can't be used to make a coroutine
 
 async fn foo() {}
 
-fn make_generator() {
+fn make_coroutine() {
     let _gen = || foo().await;
     //~^ ERROR `await` is only allowed inside `async` functions and blocks
 }
diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs
index c2e24a96b1d..f60ec04c31e 100644
--- a/tests/ui/async-await/issues/issue-59972.rs
+++ b/tests/ui/async-await/issues/issue-59972.rs
@@ -1,4 +1,4 @@
-// Incorrect handling of uninhabited types could cause us to mark generator
+// Incorrect handling of uninhabited types could cause us to mark coroutine
 // types as entirely uninhabited, when they were in fact constructible. This
 // caused us to hit "unreachable" code (illegal instruction on x86).
 
diff --git a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
index 66a3b07c3bd..ee28a2733ad 100644
--- a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
+++ b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
@@ -19,7 +19,7 @@ async fn async_nop(_: &u8) {}
 
 pub type ServeFut = impl Future<Output=()>;
 
-// Late bound regions occur in the generator witness type here.
+// Late bound regions occur in the coroutine witness type here.
 fn serve() -> ServeFut {
     async move {
         let x = 5;
diff --git a/tests/ui/async-await/issues/issue-64477-2.rs b/tests/ui/async-await/issues/issue-64477-2.rs
index 2360b57cc45..53ec3b06566 100644
--- a/tests/ui/async-await/issues/issue-64477-2.rs
+++ b/tests/ui/async-await/issues/issue-64477-2.rs
@@ -2,7 +2,7 @@
 //
 // In the past, the code generated by `format!` produced temporaries in the surrounding scope that
 // borrowed the arguments through `&dyn Trait`. These temporaries do not implement `Send`, which
-// meant that when `format!` was used in an async block, the resulting generator was not `Send`.
+// meant that when `format!` was used in an async block, the resulting coroutine was not `Send`.
 // See https://github.com/rust-lang/rust/issues/64477#issuecomment-534669068 for details
 // and https://github.com/rust-lang/rust/issues/64477#issuecomment-531882958 for an example.
 //
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
index 725caddae0b..9ed7a5d210e 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
@@ -1,4 +1,4 @@
-// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// issue 65419 - Attempting to run an async fn after completion mentions coroutines when it should
 // be talking about `async fn`s instead.
 
 // run-fail
@@ -8,7 +8,7 @@
 // ignore-wasm no panic or subprocess support
 // ignore-emscripten no panic or subprocess support
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 async fn foo() {
 }
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
index 5909c3a5ecc..51e9a54e48a 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
@@ -1,4 +1,4 @@
-// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// issue 65419 - Attempting to run an async fn after completion mentions coroutines when it should
 // be talking about `async fn`s instead. Should also test what happens when it panics.
 
 // run-fail
@@ -8,7 +8,7 @@
 // edition:2018
 // ignore-wasm no panic or subprocess support
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::panic;
 
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
index 9fc5667d684..e16b86f9579 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
@@ -1,17 +1,17 @@
-// issue 65419 - Attempting to run an `async fn` after completion mentions generators when it should
-// be talking about `async fn`s instead. Regression test added to make sure generators still
+// issue 65419 - Attempting to run an `async fn` after completion mentions coroutines when it should
+// be talking about `async fn`s instead. Regression test added to make sure coroutines still
 // panic when resumed after completion.
 
 // run-fail
-// error-pattern:generator resumed after completion
+// error-pattern:coroutine resumed after completion
 // edition:2018
 // ignore-wasm no panic or subprocess support
 // ignore-emscripten no panic or subprocess support
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::{
-    ops::Generator,
+    ops::Coroutine,
     pin::Pin,
 };
 
diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs
index 3fed7c972a1..1004303d5c1 100644
--- a/tests/ui/async-await/non-trivial-drop.rs
+++ b/tests/ui/async-await/non-trivial-drop.rs
@@ -1,7 +1,7 @@
 // build-pass
 // edition:2018
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     foo();
diff --git a/tests/ui/async-await/send-bound-async-closure.rs b/tests/ui/async-await/send-bound-async-closure.rs
index 4e9e7309be0..2ec006da359 100644
--- a/tests/ui/async-await/send-bound-async-closure.rs
+++ b/tests/ui/async-await/send-bound-async-closure.rs
@@ -2,7 +2,7 @@
 // check-pass
 
 // This test verifies that we do not create a query cycle when typechecking has several inference
-// variables that point to the same generator interior type.
+// variables that point to the same coroutine interior type.
 
 use std::future::Future;
 use std::pin::Pin;
diff --git a/tests/ui/async-await/task-context-arg.rs b/tests/ui/async-await/task-context-arg.rs
index 937723ca743..45b18d56b1c 100644
--- a/tests/ui/async-await/task-context-arg.rs
+++ b/tests/ui/async-await/task-context-arg.rs
@@ -10,7 +10,7 @@
 use std::future::Future;
 
 // The compiler produces a closure as part of this function. That closure initially takes an
-// argument _task_context. Later, when the MIR for that closure is transformed into a generator
+// argument _task_context. Later, when the MIR for that closure is transformed into a coroutine
 // state machine, _task_context is demoted to not be an argument, but just part of an unnamed
 // argument. If we emit debug info saying that both _task_context and the unnamed argument are both
 // argument number 2, then LLVM will fail with "conflicting debug info for argument". See
diff --git a/tests/ui/async-await/unnecessary-await.rs b/tests/ui/async-await/unnecessary-await.rs
index cd1e2871432..93b68f018e4 100644
--- a/tests/ui/async-await/unnecessary-await.rs
+++ b/tests/ui/async-await/unnecessary-await.rs
@@ -31,4 +31,9 @@ async fn with_macros() {
     f!(());
 }
 
+// Regression test for issue #117014.
+async fn desugaring_span_ctxt() {
+    for x in [] {}.await //~ ERROR `()` is not a future
+}
+
 fn main() {}
diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr
index 9a2a035b2dd..620370a6113 100644
--- a/tests/ui/async-await/unnecessary-await.stderr
+++ b/tests/ui/async-await/unnecessary-await.stderr
@@ -49,6 +49,19 @@ LL |     f!(());
    = note: required for `()` to implement `IntoFuture`
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0277]: `()` is not a future
+  --> $DIR/unnecessary-await.rs:36:20
+   |
+LL |     for x in [] {}.await
+   |                   -^^^^^
+   |                   ||
+   |                   |`()` is not a future
+   |                   help: remove the `.await`
+   |
+   = help: the trait `Future` is not implemented for `()`
+   = note: () must be a future or must implement `IntoFuture` to be awaited
+   = note: required for `()` to implement `IntoFuture`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
index d067ff44704..b52939ffc11 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
@@ -13,10 +13,10 @@ impl MarketMultiplier {
     }
 }
 
-async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
+async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
     //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied
     //~^^ ERROR struct takes 1 generic argument but 0 generic arguments were supplied
-    LockedMarket(generator.lock().unwrap().buy())
+    LockedMarket(coroutine.lock().unwrap().buy())
 }
 
 struct LockedMarket<T>(T);
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
index 73e0aaf1e45..516c1d065e6 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
@@ -1,7 +1,7 @@
 error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59
    |
-LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
+LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
    |                                                           ^^^^^^^^^^^^---- help: remove these generics
    |                                                           |
    |                                                           expected 0 lifetime arguments
@@ -15,7 +15,7 @@ LL | struct LockedMarket<T>(T);
 error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59
    |
-LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
+LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
    |                                                           ^^^^^^^^^^^^ expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
@@ -25,7 +25,7 @@ LL | struct LockedMarket<T>(T);
    |        ^^^^^^^^^^^^ -
 help: add missing generic argument
    |
-LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
+LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
    |                                                                          +++
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/closures/issue-25439.rs b/tests/ui/closures/issue-25439.rs
index 4f73ff3e38b..0269270b1b0 100644
--- a/tests/ui/closures/issue-25439.rs
+++ b/tests/ui/closures/issue-25439.rs
@@ -5,5 +5,5 @@ fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
 }
 
 fn main() {
-    fix(|_, x| x); //~ ERROR closure/generator type that references itself [E0644]
+    fix(|_, x| x); //~ ERROR closure/coroutine type that references itself [E0644]
 }
diff --git a/tests/ui/closures/issue-25439.stderr b/tests/ui/closures/issue-25439.stderr
index dadae23fdf3..5e889e6c184 100644
--- a/tests/ui/closures/issue-25439.stderr
+++ b/tests/ui/closures/issue-25439.stderr
@@ -1,4 +1,4 @@
-error[E0644]: closure/generator type that references itself
+error[E0644]: closure/coroutine type that references itself
   --> $DIR/issue-25439.rs:8:9
    |
 LL |     fix(|_, x| x);
diff --git a/tests/ui/coherence/coherence-with-generator.rs b/tests/ui/coherence/coherence-with-coroutine.rs
index 5eb8dc2a468..21857d7fe66 100644
--- a/tests/ui/coherence/coherence-with-generator.rs
+++ b/tests/ui/coherence/coherence-with-coroutine.rs
@@ -1,13 +1,13 @@
 // Test that encountering closures during coherence does not cause issues.
-#![feature(type_alias_impl_trait, generators)]
+#![feature(type_alias_impl_trait, coroutines)]
 #![cfg_attr(specialized, feature(specialization))]
 #![allow(incomplete_features)]
 
 // revisions: stock specialized
 // [specialized]check-pass
 
-type OpaqueGenerator = impl Sized;
-fn defining_use() -> OpaqueGenerator {
+type OpaqueCoroutine = impl Sized;
+fn defining_use() -> OpaqueCoroutine {
     || {
         for i in 0..10 {
             yield i;
@@ -17,8 +17,8 @@ fn defining_use() -> OpaqueGenerator {
 
 struct Wrapper<T>(T);
 trait Trait {}
-impl Trait for Wrapper<OpaqueGenerator> {}
+impl Trait for Wrapper<OpaqueCoroutine> {}
 impl<T: Sync> Trait for Wrapper<T> {}
-//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
+//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-with-generator.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
index 478ac491264..b2a9135c542 100644
--- a/tests/ui/coherence/coherence-with-generator.stock.stderr
+++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
-  --> $DIR/coherence-with-generator.rs:21:1
+error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
+  --> $DIR/coherence-with-coroutine.rs:21:1
    |
-LL | impl Trait for Wrapper<OpaqueGenerator> {}
+LL | impl Trait for Wrapper<OpaqueCoroutine> {}
    | --------------------------------------- first implementation here
 LL | impl<T: Sync> Trait for Wrapper<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueCoroutine>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/addassign-yield.rs b/tests/ui/coroutine/addassign-yield.rs
index 66f22bf31fc..919a559f85b 100644
--- a/tests/ui/generator/addassign-yield.rs
+++ b/tests/ui/coroutine/addassign-yield.rs
@@ -5,7 +5,7 @@
 // is being used), we were failing to account for all types that might
 // possibly be live across a yield point.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn foo() {
     let _x = static || {
diff --git a/tests/ui/coroutine/async-coroutine-issue-67158.rs b/tests/ui/coroutine/async-coroutine-issue-67158.rs
new file mode 100644
index 00000000000..420454656d4
--- /dev/null
+++ b/tests/ui/coroutine/async-coroutine-issue-67158.rs
@@ -0,0 +1,6 @@
+#![feature(coroutines)]
+// edition:2018
+// Regression test for #67158.
+fn main() {
+    async { yield print!(":C") }; //~ ERROR `async` coroutines are not yet supported
+}
diff --git a/tests/ui/generator/async-generator-issue-67158.stderr b/tests/ui/coroutine/async-coroutine-issue-67158.stderr
index 7270d188e8b..d583d3d5ea0 100644
--- a/tests/ui/generator/async-generator-issue-67158.stderr
+++ b/tests/ui/coroutine/async-coroutine-issue-67158.stderr
@@ -1,5 +1,5 @@
-error[E0727]: `async` generators are not yet supported
-  --> $DIR/async-generator-issue-67158.rs:5:13
+error[E0727]: `async` coroutines are not yet supported
+  --> $DIR/async-coroutine-issue-67158.rs:5:13
    |
 LL |     async { yield print!(":C") };
    |             ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/generator/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs
index aa4218e13a4..5fce70e8e54 100644
--- a/tests/ui/generator/auto-trait-regions.rs
+++ b/tests/ui/coroutine/auto-trait-regions.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 #![feature(auto_traits)]
 #![feature(negative_impls)]
 
@@ -21,7 +21,7 @@ impl<'a> Foo for &'a OnlyFooIfRef {}
 fn assert_foo<T: Foo>(f: T) {}
 
 fn main() {
-    // Make sure 'static is erased for generator interiors so we can't match it in trait selection
+    // 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 x = x;
@@ -40,7 +40,7 @@ fn main() {
     };
     assert_foo(gen); // ok
 
-    // Disallow impls which relates lifetimes in the generator interior
+    // Disallow impls which relates lifetimes in the coroutine interior
     let gen = move || {
         let a = A(&mut true, &mut true, No);
         //~^ temporary value dropped while borrowed
diff --git a/tests/ui/generator/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr
index a9a0bde2ba0..a9a0bde2ba0 100644
--- a/tests/ui/generator/auto-trait-regions.stderr
+++ b/tests/ui/coroutine/auto-trait-regions.stderr
diff --git a/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs
new file mode 100644
index 00000000000..dc052185340
--- /dev/null
+++ b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs
@@ -0,0 +1,11 @@
+// compile-flags: --emit metadata
+#![feature(coroutines, coroutine_trait)]
+
+use std::marker::Unpin;
+use std::ops::Coroutine;
+
+pub fn g() -> impl Coroutine<(), Yield = (), Return = ()> {
+    || {
+        yield;
+    }
+}
diff --git a/tests/ui/coroutine/auxiliary/xcrate-reachable.rs b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs
new file mode 100644
index 00000000000..673153f0619
--- /dev/null
+++ b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs
@@ -0,0 +1,14 @@
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+
+fn msg() -> u32 {
+    0
+}
+
+pub fn foo() -> impl Coroutine<(), Yield = (), Return = u32> {
+    || {
+        yield;
+        return msg();
+    }
+}
diff --git a/tests/ui/coroutine/auxiliary/xcrate.rs b/tests/ui/coroutine/auxiliary/xcrate.rs
new file mode 100644
index 00000000000..f749a95ad35
--- /dev/null
+++ b/tests/ui/coroutine/auxiliary/xcrate.rs
@@ -0,0 +1,18 @@
+#![feature(coroutines, coroutine_trait)]
+
+use std::marker::Unpin;
+use std::ops::Coroutine;
+
+pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
+    || {
+        if false {
+            yield;
+        }
+    }
+}
+
+pub fn bar<T: 'static>(t: T) -> Box<Coroutine<(), Yield = T, Return = ()> + Unpin> {
+    Box::new(|| {
+        yield t;
+    })
+}
diff --git a/tests/ui/generator/borrow-in-tail-expr.rs b/tests/ui/coroutine/borrow-in-tail-expr.rs
index 540f5e3e1dd..c1497ad2911 100644
--- a/tests/ui/generator/borrow-in-tail-expr.rs
+++ b/tests/ui/coroutine/borrow-in-tail-expr.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let _a = || {
diff --git a/tests/ui/generator/borrowing.rs b/tests/ui/coroutine/borrowing.rs
index d36592583cd..778eed8bd0d 100644
--- a/tests/ui/generator/borrowing.rs
+++ b/tests/ui/coroutine/borrowing.rs
@@ -1,6 +1,6 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/ui/generator/borrowing.stderr b/tests/ui/coroutine/borrowing.stderr
index 03a69fe3623..192ffaaa26b 100644
--- a/tests/ui/generator/borrowing.stderr
+++ b/tests/ui/coroutine/borrowing.stderr
@@ -5,11 +5,11 @@ LL |         Pin::new(&mut || yield &a).resume(())
    |                       ----------^
    |                       |         |
    |                       |         borrowed value does not live long enough
-   |                       value captured here by generator
+   |                       value captured here by coroutine
    |                       a temporary with access to the borrow is created here ...
 LL |
 LL |     };
-   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for coroutine
    |     |
    |     `a` dropped here while still borrowed
    |
@@ -27,7 +27,7 @@ LL |     let _b = {
    |         -- borrow later stored here
 LL |         let a = 3;
 LL |         || {
-   |         -- value captured here by generator
+   |         -- value captured here by coroutine
 LL |             yield &a
    |                    ^ borrowed value does not live long enough
 ...
diff --git a/tests/ui/generator/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs
index 9e9b59d3633..e8e82f1994d 100644
--- a/tests/ui/generator/clone-impl-async.rs
+++ b/tests/ui/coroutine/clone-impl-async.rs
@@ -1,8 +1,8 @@
 // edition:2021
-// gate-test-generator_clone
-// Verifies that feature(generator_clone) doesn't allow async blocks to be cloned/copied.
+// gate-test-coroutine_clone
+// Verifies that feature(coroutine_clone) doesn't allow async blocks to be cloned/copied.
 
-#![feature(generators, generator_clone)]
+#![feature(coroutines, coroutine_clone)]
 
 use std::future::ready;
 
diff --git a/tests/ui/generator/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr
index d172dff3abd..d172dff3abd 100644
--- a/tests/ui/generator/clone-impl-async.stderr
+++ b/tests/ui/coroutine/clone-impl-async.stderr
diff --git a/tests/ui/generator/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs
index 55ed0f281e0..9a165cf4672 100644
--- a/tests/ui/generator/clone-impl-static.rs
+++ b/tests/ui/coroutine/clone-impl-static.rs
@@ -1,7 +1,7 @@
-// gate-test-generator_clone
-// Verifies that static generators cannot be cloned/copied.
+// gate-test-coroutine_clone
+// Verifies that static coroutines cannot be cloned/copied.
 
-#![feature(generators, generator_clone)]
+#![feature(coroutines, coroutine_clone)]
 
 fn main() {
     let gen = static move || {
diff --git a/tests/ui/generator/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr
index 8b51824c7d2..8fa9fb12bf6 100644
--- a/tests/ui/generator/clone-impl-static.stderr
+++ b/tests/ui/coroutine/clone-impl-static.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}: Copy` is not satisfied
+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
    |
 LL |     check_copy(&gen);
-   |     ---------- ^^^^ the trait `Copy` is not implemented for `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}`
+   |     ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -12,11 +12,11 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}: Clone` is not satisfied
+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
    |
 LL |     check_clone(&gen);
-   |     ----------- ^^^^ the trait `Clone` is not implemented for `{static generator@$DIR/clone-impl-static.rs:7:15: 7:29}`
+   |     ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/generator/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs
index cbfd65a5309..eed6f851bd0 100644
--- a/tests/ui/generator/clone-impl.rs
+++ b/tests/ui/coroutine/clone-impl.rs
@@ -1,8 +1,8 @@
-// gate-test-generator_clone
-// Verifies that non-static generators can be cloned/copied if all their upvars and locals held
+// gate-test-coroutine_clone
+// Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held
 // across awaits can be cloned/copied.
 
-#![feature(generators, generator_clone)]
+#![feature(coroutines, coroutine_clone)]
 
 struct NonClone;
 
diff --git a/tests/ui/generator/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index 870216398b1..82a6d0495c0 100644
--- a/tests/ui/generator/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -1,11 +1,11 @@
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:36:23: 36:30}`
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
   --> $DIR/clone-impl.rs:42:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{generator@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<u32>`
+   |     ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:40:14
@@ -18,16 +18,16 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:36:23: 36:30}`
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
   --> $DIR/clone-impl.rs:42:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{generator@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<char>`
+   |     ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<char>`
    |
-note: generator does not implement `Copy` as this value is used across a yield
+note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/clone-impl.rs:38:9
    |
 LL |         let v = vec!['a'];
@@ -40,14 +40,14 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:46:23: 46:30}`
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
   --> $DIR/clone-impl.rs:58:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{generator@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<u32>`
+   |     ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:56:14
@@ -60,16 +60,16 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:46:23: 46:30}`
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
   --> $DIR/clone-impl.rs:58:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{generator@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<char>`
+   |     ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<char>`
    |
-note: generator does not implement `Copy` as this value is used across a yield
+note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/clone-impl.rs:52:9
    |
 LL |         let v = vec!['a'];
@@ -83,14 +83,14 @@ note: required by a bound in `check_copy`
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{generator@$DIR/clone-impl.rs:62:25: 62:32}`
+error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
   --> $DIR/clone-impl.rs:66:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{generator@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |     ^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`
+   |     ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:64:14
@@ -108,14 +108,14 @@ LL + #[derive(Copy)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{generator@$DIR/clone-impl.rs:62:25: 62:32}`
+error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
   --> $DIR/clone-impl.rs:68:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{generator@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |     ^^^^^^^^^^^ within `{generator@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`
+   |     ^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`
    |
 note: captured value does not implement `Clone`
   --> $DIR/clone-impl.rs:64:14
diff --git a/tests/ui/generator/conditional-drop.rs b/tests/ui/coroutine/conditional-drop.rs
index 0927df86927..634095c7acc 100644
--- a/tests/ui/generator/conditional-drop.rs
+++ b/tests/ui/coroutine/conditional-drop.rs
@@ -3,9 +3,9 @@
 // revisions: default nomiropt
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
diff --git a/tests/ui/generator/control-flow.rs b/tests/ui/coroutine/control-flow.rs
index 4f69c785560..709b135b2ee 100644
--- a/tests/ui/generator/control-flow.rs
+++ b/tests/ui/coroutine/control-flow.rs
@@ -3,19 +3,19 @@
 // revisions: default nomiropt
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::marker::Unpin;
-use std::ops::{GeneratorState, Generator};
+use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
 
 fn finish<T>(mut amt: usize, mut t: T) -> T::Return
-    where T: Generator<(), Yield = ()> + Unpin,
+    where T: Coroutine<(), Yield = ()> + Unpin,
 {
     loop {
         match Pin::new(&mut t).resume(()) {
-            GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
-            GeneratorState::Complete(ret) => {
+            CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
+            CoroutineState::Complete(ret) => {
                 assert_eq!(amt, 0);
                 return ret
             }
diff --git a/tests/ui/generator/generator-region-requirements.migrate.stderr b/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr
index 8a96d187f6b..8a96d187f6b 100644
--- a/tests/ui/generator/generator-region-requirements.migrate.stderr
+++ b/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr
diff --git a/tests/ui/generator/generator-region-requirements.rs b/tests/ui/coroutine/coroutine-region-requirements.rs
index 7269a79ca3f..8bc34fdd2f0 100644
--- a/tests/ui/generator/generator-region-requirements.rs
+++ b/tests/ui/coroutine/coroutine-region-requirements.rs
@@ -1,5 +1,5 @@
-#![feature(generators, generator_trait)]
-use std::ops::{Generator, GeneratorState};
+#![feature(coroutines, coroutine_trait)]
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn dangle(x: &mut i32) -> &'static mut i32 {
@@ -9,9 +9,9 @@ fn dangle(x: &mut i32) -> &'static mut i32 {
     };
     loop {
         match Pin::new(&mut g).resume(()) {
-            GeneratorState::Complete(c) => return c,
+            CoroutineState::Complete(c) => return c,
             //~^ ERROR lifetime may not live long enough
-            GeneratorState::Yielded(_) => (),
+            CoroutineState::Yielded(_) => (),
         }
     }
 }
diff --git a/tests/ui/generator/generator-region-requirements.stderr b/tests/ui/coroutine/coroutine-region-requirements.stderr
index 87f60467287..ad3183e7612 100644
--- a/tests/ui/generator/generator-region-requirements.stderr
+++ b/tests/ui/coroutine/coroutine-region-requirements.stderr
@@ -1,10 +1,10 @@
 error: lifetime may not live long enough
-  --> $DIR/generator-region-requirements.rs:12:51
+  --> $DIR/coroutine-region-requirements.rs:12:51
    |
 LL | fn dangle(x: &mut i32) -> &'static mut i32 {
    |              - let's call the lifetime of this reference `'1`
 ...
-LL |             GeneratorState::Complete(c) => return c,
+LL |             CoroutineState::Complete(c) => return c,
    |                                                   ^ returning this value requires that `'1` must outlive `'static`
 
 error: aborting due to previous error
diff --git a/tests/ui/generator/generator-resume-after-panic.rs b/tests/ui/coroutine/coroutine-resume-after-panic.rs
index f2e67f1f750..5915f5ad9a9 100644
--- a/tests/ui/generator/generator-resume-after-panic.rs
+++ b/tests/ui/coroutine/coroutine-resume-after-panic.rs
@@ -1,14 +1,14 @@
 // run-fail
 // needs-unwind
-// error-pattern:generator resumed after panicking
+// error-pattern:coroutine resumed after panicking
 // ignore-emscripten no processes
 
-// Test that we get the correct message for resuming a panicked generator.
+// Test that we get the correct message for resuming a panicked coroutine.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::{
-    ops::Generator,
+    ops::Coroutine,
     pin::Pin,
     panic,
 };
diff --git a/tests/ui/generator/generator-with-nll.rs b/tests/ui/coroutine/coroutine-with-nll.rs
index cee3e6d226c..28a3643fbc9 100644
--- a/tests/ui/generator/generator-with-nll.rs
+++ b/tests/ui/coroutine/coroutine-with-nll.rs
@@ -1,11 +1,11 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     || {
         // The reference in `_a` is a Legal with NLL since it ends before the yield
         let _a = &mut true;
         let b = &mut true;
-        //~^ borrow may still be in use when generator yields
+        //~^ borrow may still be in use when coroutine yields
         yield ();
         println!("{}", b);
     };
diff --git a/tests/ui/generator/generator-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr
index 14199aeb930..ed58debe2b4 100644
--- a/tests/ui/generator/generator-with-nll.stderr
+++ b/tests/ui/coroutine/coroutine-with-nll.stderr
@@ -1,5 +1,5 @@
-error[E0626]: borrow may still be in use when generator yields
-  --> $DIR/generator-with-nll.rs:7:17
+error[E0626]: borrow may still be in use when coroutine yields
+  --> $DIR/coroutine-with-nll.rs:7: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
new file mode 100644
index 00000000000..3c91b3c9329
--- /dev/null
+++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs
@@ -0,0 +1,35 @@
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
+
+// Test that we cannot create a coroutine that returns a value of its
+// own type.
+
+use std::ops::Coroutine;
+
+pub fn want_cyclic_coroutine_return<T>(_: T)
+    where T: Coroutine<Yield = (), Return = T>
+{
+}
+
+fn supply_cyclic_coroutine_return() {
+    want_cyclic_coroutine_return(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+pub fn want_cyclic_coroutine_yield<T>(_: T)
+    where T: Coroutine<Yield = T, Return = ()>
+{
+}
+
+fn supply_cyclic_coroutine_yield() {
+    want_cyclic_coroutine_yield(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+fn main() { }
diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.stderr b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr
index 7841a0854ca..325030524ba 100644
--- a/tests/ui/generator/generator-yielding-or-returning-itself.stderr
+++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr
@@ -1,7 +1,7 @@
-error[E0271]: type mismatch resolving `<{generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36} as Generator>::Return == {generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36}`
-  --> $DIR/generator-yielding-or-returning-itself.rs:15:34
+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
    |
-LL |       want_cyclic_generator_return(|| {
+LL |       want_cyclic_coroutine_return(|| {
    |  _____----------------------------_^
    | |     |
    | |     required by a bound introduced by this call
@@ -15,18 +15,18 @@ LL | |     })
            this error may be the result of a recent compiler bug-fix,
            see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
            for more information
-note: required by a bound in `want_cyclic_generator_return`
-  --> $DIR/generator-yielding-or-returning-itself.rs:10:36
+note: required by a bound in `want_cyclic_coroutine_return`
+  --> $DIR/coroutine-yielding-or-returning-itself.rs:10:36
    |
-LL | pub fn want_cyclic_generator_return<T>(_: T)
+LL | pub fn want_cyclic_coroutine_return<T>(_: T)
    |        ---------------------------- required by a bound in this function
-LL |     where T: Generator<Yield = (), Return = T>
-   |                                    ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return`
+LL |     where T: Coroutine<Yield = (), Return = T>
+   |                                    ^^^^^^^^^^ required by this bound in `want_cyclic_coroutine_return`
 
-error[E0271]: type mismatch resolving `<{generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35} as Generator>::Yield == {generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35}`
-  --> $DIR/generator-yielding-or-returning-itself.rs:28:33
+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
    |
-LL |       want_cyclic_generator_yield(|| {
+LL |       want_cyclic_coroutine_yield(|| {
    |  _____---------------------------_^
    | |     |
    | |     required by a bound introduced by this call
@@ -40,13 +40,13 @@ LL | |     })
            this error may be the result of a recent compiler bug-fix,
            see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
            for more information
-note: required by a bound in `want_cyclic_generator_yield`
-  --> $DIR/generator-yielding-or-returning-itself.rs:23:24
+note: required by a bound in `want_cyclic_coroutine_yield`
+  --> $DIR/coroutine-yielding-or-returning-itself.rs:23:24
    |
-LL | pub fn want_cyclic_generator_yield<T>(_: T)
+LL | pub fn want_cyclic_coroutine_yield<T>(_: T)
    |        --------------------------- required by a bound in this function
-LL |     where T: Generator<Yield = T, Return = ()>
-   |                        ^^^^^^^^^ required by this bound in `want_cyclic_generator_yield`
+LL |     where T: Coroutine<Yield = T, Return = ()>
+   |                        ^^^^^^^^^ required by this bound in `want_cyclic_coroutine_yield`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generator/derived-drop-parent-expr.rs b/tests/ui/coroutine/derived-drop-parent-expr.rs
index e381924517d..59a3e847838 100644
--- a/tests/ui/generator/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(generators)]
+#![feature(coroutines)]
 
 fn assert_send<T: Send>(_thing: T) {}
 
diff --git a/tests/ui/generator/discriminant.rs b/tests/ui/coroutine/discriminant.rs
index 195e7702299..73bdd9c8671 100644
--- a/tests/ui/generator/discriminant.rs
+++ b/tests/ui/coroutine/discriminant.rs
@@ -1,12 +1,12 @@
-//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are
+//! Tests that coroutine discriminant sizes and ranges are chosen optimally and that they are
 //! reflected in the output of `mem::discriminant`.
 
 // run-pass
 
-#![feature(generators, generator_trait, core_intrinsics, discriminant_kind)]
+#![feature(coroutines, coroutine_trait, core_intrinsics, discriminant_kind)]
 
 use std::intrinsics::discriminant_value;
-use std::marker::{Unpin, DiscriminantKind};
+use std::marker::{DiscriminantKind, Unpin};
 use std::mem::size_of_val;
 use std::{cmp, ops::*};
 
@@ -66,16 +66,16 @@ macro_rules! yield250 {
 }
 
 fn cycle(
-    gen: impl Generator<()> + Unpin + DiscriminantKind<Discriminant = u32>,
-    expected_max_discr: u32
+    gen: impl Coroutine<()> + Unpin + DiscriminantKind<Discriminant = u32>,
+    expected_max_discr: u32,
 ) {
     let mut gen = Box::pin(gen);
     let mut max_discr = 0;
     loop {
         max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut()));
         match gen.as_mut().resume(()) {
-            GeneratorState::Yielded(_) => {}
-            GeneratorState::Complete(_) => {
+            CoroutineState::Yielded(_) => {}
+            CoroutineState::Complete(_) => {
                 assert_eq!(max_discr, expected_max_discr);
                 return;
             }
diff --git a/tests/ui/generator/drop-and-replace.rs b/tests/ui/coroutine/drop-and-replace.rs
index a9a50a122a1..38b757fac29 100644
--- a/tests/ui/generator/drop-and-replace.rs
+++ b/tests/ui/coroutine/drop-and-replace.rs
@@ -1,19 +1,19 @@
 // run-pass
 // Regression test for incorrect DropAndReplace behavior introduced in #60840
 // and fixed in #61373. When combined with the optimization implemented in
-// #60187, this produced incorrect code for generators when a saved local was
+// #60187, this produced incorrect code for coroutines when a saved local was
 // re-assigned.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 #[derive(Debug, PartialEq)]
 struct Foo(i32);
 
 impl Drop for Foo {
-    fn drop(&mut self) { }
+    fn drop(&mut self) {}
 }
 
 fn main() {
@@ -38,7 +38,7 @@ fn main() {
 
     loop {
         match Pin::new(&mut a).resume(()) {
-            GeneratorState::Complete(()) => break,
+            CoroutineState::Complete(()) => break,
             _ => (),
         }
     }
diff --git a/tests/ui/generator/drop-control-flow.rs b/tests/ui/coroutine/drop-control-flow.rs
index 1c25c06ba4c..55d08b8d5b5 100644
--- a/tests/ui/generator/drop-control-flow.rs
+++ b/tests/ui/coroutine/drop-control-flow.rs
@@ -1,10 +1,10 @@
 // build-pass
 
-// A test to ensure generators capture values that were conditionally dropped,
+// A test to ensure coroutines capture values that were conditionally dropped,
 // and also that values that are dropped along all paths to a yield do not get
-// included in the generator type.
+// included in the coroutine type.
 
-#![feature(generators, negative_impls)]
+#![feature(coroutines, negative_impls)]
 #![allow(unused_assignments, dead_code)]
 
 struct Ptr;
diff --git a/tests/ui/generator/drop-env.rs b/tests/ui/coroutine/drop-env.rs
index 137a407931a..404c043431d 100644
--- a/tests/ui/generator/drop-env.rs
+++ b/tests/ui/coroutine/drop-env.rs
@@ -3,10 +3,10 @@
 // revisions: default nomiropt
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![allow(dropping_copy_types)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
diff --git a/tests/ui/generator/drop-track-addassign-yield.rs b/tests/ui/coroutine/drop-track-addassign-yield.rs
index 1e64f1d2ec7..6c5897458ec 100644
--- a/tests/ui/generator/drop-track-addassign-yield.rs
+++ b/tests/ui/coroutine/drop-track-addassign-yield.rs
@@ -3,7 +3,7 @@
 // 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(generators)]
+#![feature(coroutines)]
 
 fn foo() {
     let _y = static || {
diff --git a/tests/ui/generator/drop-tracking-parent-expression.rs b/tests/ui/coroutine/drop-tracking-parent-expression.rs
index 198b14528aa..4d40192c07a 100644
--- a/tests/ui/generator/drop-tracking-parent-expression.rs
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.rs
@@ -1,4 +1,4 @@
-#![feature(generators, negative_impls, rustc_attrs)]
+#![feature(coroutines, negative_impls, rustc_attrs)]
 
 macro_rules! type_combinations {
     (
diff --git a/tests/ui/generator/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
index e85bb1347a7..6cd4ec83377 100644
--- a/tests/ui/generator/drop-tracking-parent-expression.stderr
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
@@ -1,8 +1,8 @@
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/drop-tracking-parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -13,8 +13,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`
+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() }) {
@@ -38,11 +38,11 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/drop-tracking-parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -53,8 +53,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`
+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() }) {
@@ -78,11 +78,11 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/drop-tracking-parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -93,8 +93,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+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() }) {
diff --git a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs
index 92e0136d51b..622765d82aa 100644
--- a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs
+++ b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs
@@ -1,7 +1,7 @@
 // build-pass
 // edition:2018
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let _ = static |x: u8| match x {
diff --git a/tests/ui/generator/drop-yield-twice.rs b/tests/ui/coroutine/drop-yield-twice.rs
index f484cbb8d67..015343a2776 100644
--- a/tests/ui/generator/drop-yield-twice.rs
+++ b/tests/ui/coroutine/drop-yield-twice.rs
@@ -1,10 +1,10 @@
-#![feature(negative_impls, generators)]
+#![feature(negative_impls, coroutines)]
 
 struct Foo(i32);
 impl !Send for Foo {}
 
 fn main() {
-    assert_send(|| { //~ ERROR generator cannot be sent between threads safely
+    assert_send(|| { //~ ERROR coroutine cannot be sent between threads safely
         let guard = Foo(42);
         yield;
         drop(guard);
diff --git a/tests/ui/generator/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr
index 39a906f0bf4..fbbedac5775 100644
--- a/tests/ui/generator/drop-yield-twice.stderr
+++ b/tests/ui/coroutine/drop-yield-twice.stderr
@@ -1,11 +1,11 @@
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/drop-yield-twice.rs:7:5
    |
 LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+   |     ^^^^^^^^^^^ coroutine is not `Send`
    |
-   = help: within `{generator@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`
+note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-yield-twice.rs:9:9
    |
 LL |         let guard = Foo(42);
diff --git a/tests/ui/generator/dropck-resume.rs b/tests/ui/coroutine/dropck-resume.rs
index 4c18077f335..07ca4d37aba 100644
--- a/tests/ui/generator/dropck-resume.rs
+++ b/tests/ui/coroutine/dropck-resume.rs
@@ -1,6 +1,6 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 struct SetToNone<'a: 'b, 'b>(&'b mut Option<&'a i32>);
@@ -11,7 +11,7 @@ impl<'a, 'b> Drop for SetToNone<'a, 'b> {
     }
 }
 
-fn drop_using_generator() -> i32 {
+fn drop_using_coroutine() -> i32 {
     let mut y = Some(&0);
     let z = &mut y;
     let r;
@@ -29,5 +29,5 @@ fn drop_using_generator() -> i32 {
 }
 
 fn main() {
-    println!("{}", drop_using_generator());
+    println!("{}", drop_using_coroutine());
 }
diff --git a/tests/ui/generator/dropck-resume.stderr b/tests/ui/coroutine/dropck-resume.stderr
index ecf92e7e3ae..028523978f9 100644
--- a/tests/ui/generator/dropck-resume.stderr
+++ b/tests/ui/coroutine/dropck-resume.stderr
@@ -8,7 +8,7 @@ LL |         r = y.as_ref().unwrap();
    |             ^ immutable borrow occurs here
 LL |
 LL |     }
-   |     - mutable borrow might be used here, when `g` is dropped and runs the destructor for generator
+   |     - mutable borrow might be used here, when `g` is dropped and runs the destructor for coroutine
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/dropck.rs b/tests/ui/coroutine/dropck.rs
index f82111a76b1..450361c8dd0 100644
--- a/tests/ui/generator/dropck.rs
+++ b/tests/ui/coroutine/dropck.rs
@@ -1,7 +1,7 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::cell::RefCell;
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
@@ -11,7 +11,7 @@ fn main() {
     //~^ ERROR `*cell` does not live long enough [E0597]
     // the upvar is the non-dropck `&mut Option<Ref<'a, i32>>`.
     gen = || {
-        // but the generator can use it to drop a `Ref<'a, i32>`.
+        // 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/generator/dropck.stderr b/tests/ui/coroutine/dropck.stderr
index 246ac99f83f..241d6dfe0a1 100644
--- a/tests/ui/generator/dropck.stderr
+++ b/tests/ui/coroutine/dropck.stderr
@@ -11,7 +11,7 @@ LL | }
    | -
    | |
    | `*cell` dropped here while still borrowed
-   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
+   | borrow might be used here, when `gen` is dropped and runs the destructor for coroutine
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -19,8 +19,8 @@ error[E0597]: `ref_` does not live long enough
   --> $DIR/dropck.rs:15:18
    |
 LL |     gen = || {
-   |           -- value captured here by generator
-LL |         // but the generator can use it to drop a `Ref<'a, i32>`.
+   |           -- 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
 ...
@@ -28,7 +28,7 @@ LL | }
    | -
    | |
    | `ref_` dropped here while still borrowed
-   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
+   | borrow might be used here, when `gen` is dropped and runs the destructor for coroutine
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
diff --git a/tests/ui/generator/issue-102645.rs b/tests/ui/coroutine/issue-102645.rs
index 677cc69d3f2..a0263510e13 100644
--- a/tests/ui/generator/issue-102645.rs
+++ b/tests/ui/coroutine/issue-102645.rs
@@ -1,6 +1,6 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/ui/generator/issue-102645.stderr b/tests/ui/coroutine/issue-102645.stderr
index 5d28dfc45b3..3db090346cd 100644
--- a/tests/ui/generator/issue-102645.stderr
+++ b/tests/ui/coroutine/issue-102645.stderr
@@ -5,7 +5,7 @@ LL |     Pin::new(&mut b).resume();
    |                      ^^^^^^-- an argument of type `()` is missing
    |
 note: method defined here
-  --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
+  --> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL
 help: provide the argument
    |
 LL |     Pin::new(&mut b).resume(());
diff --git a/tests/ui/generator/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs
index 50b5da6e6ad..7801f1bcea0 100644
--- a/tests/ui/generator/issue-105084.rs
+++ b/tests/ui/coroutine/issue-105084.rs
@@ -1,9 +1,9 @@
-#![feature(generators)]
-#![feature(generator_clone)]
-#![feature(generator_trait)]
+#![feature(coroutines)]
+#![feature(coroutine_clone)]
+#![feature(coroutine_trait)]
 #![feature(rustc_attrs, stmt_expr_attributes)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn copy<T: Copy>(x: T) -> T {
@@ -25,9 +25,9 @@ fn main() {
     // Allocate the temporary box.
     Pin::new(&mut g).resume(());
 
-    // The temporary box is in generator locals.
+    // The temporary box is in coroutine locals.
     // As it is not taken into account for trait computation,
-    // the generator is `Copy`.
+    // the coroutine is `Copy`.
     let mut h = copy(g);
     //~^ ERROR the trait bound `Box<(i32, ())>: Copy` is not satisfied in
 
diff --git a/tests/ui/generator/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr
index 573c31f1134..38f114ff774 100644
--- a/tests/ui/generator/issue-105084.stderr
+++ b/tests/ui/coroutine/issue-105084.stderr
@@ -2,7 +2,7 @@ error[E0382]: borrow of moved value: `g`
   --> $DIR/issue-105084.rs:37:14
    |
 LL |     let mut g = || {
-   |         ----- move occurs because `g` has type `{generator@$DIR/issue-105084.rs:14:17: 14:19}`, which does not implement the `Copy` trait
+   |         ----- 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 h = copy(g);
    |                      - value moved here
@@ -22,16 +22,16 @@ 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 `{generator@$DIR/issue-105084.rs:14:17: 14:19}`
+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
    |
 LL |     let mut g = || {
-   |                 -- within this `{generator@$DIR/issue-105084.rs:14:17: 14:19}`
+   |                 -- within this `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`
 ...
 LL |     let mut h = copy(g);
-   |                 ^^^^ within `{generator@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
+   |                 ^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
    |
-note: generator does not implement `Copy` as this value is used across a yield
+note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/issue-105084.rs:21:22
    |
 LL |         Box::new((5, yield));
diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs
index a45479e5300..feaaa71ea9c 100644
--- a/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs
+++ b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs
@@ -1,5 +1,5 @@
 // edition:2021
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let x = &mut ();
diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.stderr
index 66f0e3d94bd..77da6c4cdc9 100644
--- a/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr
+++ b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.stderr
@@ -1,8 +1,8 @@
 error[E0499]: cannot borrow `*x` as mutable more than once at a time
-  --> $DIR/issue-110929-generator-conflict-error-ice.rs:8:9
+  --> $DIR/issue-110929-coroutine-conflict-error-ice.rs:8:9
    |
 LL |         let _c = || yield *&mut *x;
-   |                  --             -- first borrow occurs due to use of `*x` in generator
+   |                  --             -- first borrow occurs due to use of `*x` in coroutine
    |                  |
    |                  first mutable borrow occurs here
 LL |         || _ = &mut *x;
@@ -11,7 +11,7 @@ LL |         || _ = &mut *x;
    |         second mutable borrow occurs here
 LL |
 LL |     };
-   |     - first borrow might be used here, when `_c` is dropped and runs the destructor for generator
+   |     - first borrow might be used here, when `_c` is dropped and runs the destructor for coroutine
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/issue-113279.rs b/tests/ui/coroutine/issue-113279.rs
index f69f804b716..f251c924c13 100644
--- a/tests/ui/generator/issue-113279.rs
+++ b/tests/ui/coroutine/issue-113279.rs
@@ -1,10 +1,10 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 // `foo` attempts to dereference `""`, which results in an error being reported. Later, the
-// generator transform for `foo` then produces a union which contains a `str` type - unions should
+// coroutine transform for `foo` then produces a union which contains a `str` type - unions should
 // not contain unsized types, but this is okay because an error has been reported already.
 // When const propagation happens later in compilation, it attempts to compute the layout of the
-// generator (as part of checking whether something can be const propagated) and in turn attempts
+// coroutine (as part of checking whether something can be const propagated) and in turn attempts
 // to compute the layout of `str` in the context of a union - where this caused an ICE. This test
 // makes sure that doesn't happen again.
 
diff --git a/tests/ui/generator/issue-113279.stderr b/tests/ui/coroutine/issue-113279.stderr
index cc9b64ef9ac..cc9b64ef9ac 100644
--- a/tests/ui/generator/issue-113279.stderr
+++ b/tests/ui/coroutine/issue-113279.stderr
diff --git a/tests/ui/generator/issue-44197.rs b/tests/ui/coroutine/issue-44197.rs
index 389b9d13969..c0326bdae4e 100644
--- a/tests/ui/generator/issue-44197.rs
+++ b/tests/ui/coroutine/issue-44197.rs
@@ -1,15 +1,15 @@
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn foo(_: &str) -> String {
     String::new()
 }
 
-fn bar(baz: String) -> impl Generator<(), Yield = String, Return = ()> {
+fn bar(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> {
     move || {
         yield foo(&baz);
     }
@@ -19,7 +19,7 @@ fn foo2(_: &str) -> Result<String, ()> {
     Err(())
 }
 
-fn bar2(baz: String) -> impl Generator<(), Yield = String, Return = ()> {
+fn bar2(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> {
     move || {
         if let Ok(quux) = foo2(&baz) {
             yield quux;
@@ -30,7 +30,7 @@ fn bar2(baz: String) -> impl Generator<(), Yield = String, Return = ()> {
 fn main() {
     assert_eq!(
         Pin::new(&mut bar(String::new())).resume(()),
-        GeneratorState::Yielded(String::new())
+        CoroutineState::Yielded(String::new())
     );
-    assert_eq!(Pin::new(&mut bar2(String::new())).resume(()), GeneratorState::Complete(()));
+    assert_eq!(Pin::new(&mut bar2(String::new())).resume(()), CoroutineState::Complete(()));
 }
diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr
index 3afbea07931..a9a0d629606 100644
--- a/tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr
+++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-45729-unsafe-in-generator.rs:8:9
+  --> $DIR/issue-45729-unsafe-in-coroutine.rs:8:9
    |
 LL |         *(1 as *mut u32) = 42;
    |         ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.rs b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs
index 379c36d2ca3..7961b58597c 100644
--- a/tests/ui/generator/issue-45729-unsafe-in-generator.rs
+++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs
@@ -1,7 +1,7 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let _ = || {
diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr
index 10d768f19fc..22c83e9a3d5 100644
--- a/tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr
+++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-45729-unsafe-in-generator.rs:8:9
+  --> $DIR/issue-45729-unsafe-in-coroutine.rs:8:9
    |
 LL |         *(1 as *mut u32) = 42;
    |         ^^^^^^^^^^^^^^^^ dereference of raw pointer
diff --git a/tests/ui/generator/issue-48048.rs b/tests/ui/coroutine/issue-48048.rs
index 992bbc97a9f..b61b7c77072 100644
--- a/tests/ui/generator/issue-48048.rs
+++ b/tests/ui/coroutine/issue-48048.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let x = (|_| {},);
@@ -6,7 +6,7 @@ fn main() {
     || {
         let x = x;
 
-        x.0({ //~ ERROR borrow may still be in use when generator yields
+        x.0({ //~ ERROR borrow may still be in use when coroutine yields
             yield;
         });
     };
diff --git a/tests/ui/generator/issue-48048.stderr b/tests/ui/coroutine/issue-48048.stderr
index 23423583916..bb9f189fa7c 100644
--- a/tests/ui/generator/issue-48048.stderr
+++ b/tests/ui/coroutine/issue-48048.stderr
@@ -1,4 +1,4 @@
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/issue-48048.rs:9:9
    |
 LL |         x.0({
diff --git a/tests/ui/coroutine/issue-52304.rs b/tests/ui/coroutine/issue-52304.rs
new file mode 100644
index 00000000000..fed3a5f19b3
--- /dev/null
+++ b/tests/ui/coroutine/issue-52304.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+
+pub fn example() -> impl Coroutine {
+    || yield &1
+}
+
+fn main() {}
diff --git a/tests/ui/generator/issue-52398.rs b/tests/ui/coroutine/issue-52398.rs
index ada380d116c..8d651d0e2ce 100644
--- a/tests/ui/generator/issue-52398.rs
+++ b/tests/ui/coroutine/issue-52398.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(unused_variables)]
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 use std::cell::RefCell;
 
@@ -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 generator that must be used
+    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 generator that must be used
+    static move || { //~ WARN unused coroutine that must be used
         yield *y.borrow();
         return "Done";
     };
diff --git a/tests/ui/generator/issue-52398.stderr b/tests/ui/coroutine/issue-52398.stderr
index 539343275df..18d816da4c6 100644
--- a/tests/ui/generator/issue-52398.stderr
+++ b/tests/ui/coroutine/issue-52398.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/issue-52398.rs:17:5
    |
 LL | /     move || {
@@ -6,10 +6,10 @@ LL | |         A.test(yield);
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/issue-52398.rs:24:5
    |
 LL | /     static move || {
@@ -18,7 +18,7 @@ LL | |         return "Done";
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/generator/issue-53548-1.rs b/tests/ui/coroutine/issue-53548-1.rs
index 173ae3c6fb6..4be8e95f3e7 100644
--- a/tests/ui/generator/issue-53548-1.rs
+++ b/tests/ui/coroutine/issue-53548-1.rs
@@ -1,4 +1,4 @@
-// A variant of #53548 that does not actually require generators,
+// A variant of #53548 that does not actually require coroutines,
 // but which encountered the same ICE/error. See `issue-53548.rs`
 // for details.
 //
diff --git a/tests/ui/generator/issue-53548.rs b/tests/ui/coroutine/issue-53548.rs
index 3ebabb91462..bb267f74ae2 100644
--- a/tests/ui/generator/issue-53548.rs
+++ b/tests/ui/coroutine/issue-53548.rs
@@ -1,5 +1,5 @@
 // Regression test for #53548. The `Box<dyn Trait>` type below is
-// expanded to `Box<dyn Trait + 'static>`, but the generator "witness"
+// expanded to `Box<dyn Trait + 'static>`, but the coroutine "witness"
 // that results is `for<'r> { Box<dyn Trait + 'r> }`. The WF code was
 // encountering an ICE (when debug-assertions were enabled) and an
 // unexpected compilation error (without debug-asserions) when trying
@@ -17,7 +17,7 @@
 //
 // check-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 use std::cell::RefCell;
 use std::rc::Rc;
diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/coroutine/issue-57017.rs
index bb2d6679b67..4f63abbdb10 100644
--- a/tests/ui/generator/issue-57017.rs
+++ b/tests/ui/coroutine/issue-57017.rs
@@ -1,5 +1,5 @@
 // build-pass
-#![feature(generators, negative_impls)]
+#![feature(coroutines, negative_impls)]
 #![allow(dropping_references, dropping_copy_types)]
 
 macro_rules! type_combinations {
diff --git a/tests/ui/generator/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs
index fbed78ff280..95bed5b151e 100644
--- a/tests/ui/generator/issue-57084.rs
+++ b/tests/ui/coroutine/issue-57084.rs
@@ -2,10 +2,10 @@
 // "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '?1"
 // run-pass
 // edition:2018
-#![feature(generators,generator_trait)]
-use std::ops::Generator;
+#![feature(coroutines,coroutine_trait)]
+use std::ops::Coroutine;
 
-fn with<F>(f: F) -> impl Generator<Yield=(), Return=()>
+fn with<F>(f: F) -> impl Coroutine<Yield=(), Return=()>
 where F: Fn() -> ()
 {
     move || {
@@ -19,7 +19,7 @@ where F: Fn() -> ()
 
 fn main() {
     let data = &vec![1];
-    || { //~ WARN unused generator that must be used
+    || { //~ WARN unused coroutine that must be used
         let _to_pin = with(move || println!("{:p}", data));
         loop {
             yield
diff --git a/tests/ui/generator/issue-57084.stderr b/tests/ui/coroutine/issue-57084.stderr
index 8f1fc5e8031..9f5b79a6ae8 100644
--- a/tests/ui/generator/issue-57084.stderr
+++ b/tests/ui/coroutine/issue-57084.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/issue-57084.rs:22:5
    |
 LL | /     || {
@@ -9,7 +9,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/issue-57478.rs b/tests/ui/coroutine/issue-57478.rs
index 39710febdb9..716e4c67b87 100644
--- a/tests/ui/generator/issue-57478.rs
+++ b/tests/ui/coroutine/issue-57478.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(negative_impls, generators)]
+#![feature(negative_impls, coroutines)]
 
 struct Foo;
 impl !Send for Foo {}
diff --git a/tests/ui/generator/issue-58888.rs b/tests/ui/coroutine/issue-58888.rs
index d42d09d401e..af8e60ce460 100644
--- a/tests/ui/generator/issue-58888.rs
+++ b/tests/ui/coroutine/issue-58888.rs
@@ -2,9 +2,9 @@
 // compile-flags: -g
 // ignore-asmjs wasm2js does not support source maps yet
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 struct Database;
 
@@ -13,7 +13,7 @@ impl Database {
         Some(()).into_iter()
     }
 
-    fn check_connection(&self) -> impl Generator<Yield = (), Return = ()> + '_ {
+    fn check_connection(&self) -> impl Coroutine<Yield = (), Return = ()> + '_ {
         move || {
             let iter = self.get_connection();
             for i in iter {
diff --git a/tests/ui/generator/issue-61442-stmt-expr-with-drop.rs b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs
index 187c374021d..cff6c24a83f 100644
--- a/tests/ui/generator/issue-61442-stmt-expr-with-drop.rs
+++ b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs
@@ -4,9 +4,9 @@
 // check-pass
 // edition:2018
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 async fn drop_and_await() {
     async {};
diff --git a/tests/ui/generator/issue-62506-two_awaits.rs b/tests/ui/coroutine/issue-62506-two_awaits.rs
index 672e16b780d..b50e2a45c58 100644
--- a/tests/ui/generator/issue-62506-two_awaits.rs
+++ b/tests/ui/coroutine/issue-62506-two_awaits.rs
@@ -1,5 +1,5 @@
 // Output = String caused an ICE whereas Output = &'static str compiled successfully.
-// Broken MIR: generator contains type std::string::String in MIR,
+// Broken MIR: coroutine contains type std::string::String in MIR,
 // but typeck only knows about {<S as T>::Future, ()}
 // check-pass
 // edition:2018
diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.rs b/tests/ui/coroutine/issue-64620-yield-array-element.rs
new file mode 100644
index 00000000000..a9307d306a6
--- /dev/null
+++ b/tests/ui/coroutine/issue-64620-yield-array-element.rs
@@ -0,0 +1,9 @@
+// Regression test for #64620
+
+#![feature(coroutines)]
+
+pub fn crash(arr: [usize; 1]) {
+    yield arr[0]; //~ ERROR: yield expression outside of coroutine literal
+}
+
+fn main() {}
diff --git a/tests/ui/generator/issue-64620-yield-array-element.stderr b/tests/ui/coroutine/issue-64620-yield-array-element.stderr
index 48383c2ed08..47632d083ea 100644
--- a/tests/ui/generator/issue-64620-yield-array-element.stderr
+++ b/tests/ui/coroutine/issue-64620-yield-array-element.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield expression outside of generator literal
+error[E0627]: yield expression outside of coroutine literal
   --> $DIR/issue-64620-yield-array-element.rs:6:5
    |
 LL |     yield arr[0];
diff --git a/tests/ui/generator/issue-68112.rs b/tests/ui/coroutine/issue-68112.rs
index 9dd68726f92..e2be704dab7 100644
--- a/tests/ui/generator/issue-68112.rs
+++ b/tests/ui/coroutine/issue-68112.rs
@@ -1,18 +1,18 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::{
     cell::RefCell,
     sync::Arc,
     pin::Pin,
-    ops::{Generator, GeneratorState},
+    ops::{Coroutine, CoroutineState},
 };
 
 pub struct Ready<T>(Option<T>);
-impl<T: Unpin> Generator<()> for Ready<T> {
+impl<T: Unpin> Coroutine<()> for Ready<T> {
     type Return = T;
     type Yield = ();
-    fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> {
-        GeneratorState::Complete(self.0.take().unwrap())
+    fn resume(mut self: Pin<&mut Self>, _args: ()) -> CoroutineState<(), T> {
+        CoroutineState::Complete(self.0.take().unwrap())
     }
 }
 pub fn make_gen1<T>(t: T) -> Ready<T> {
@@ -25,40 +25,40 @@ fn require_send(_: impl Send) {}
 //~| NOTE required by this bound
 //~| NOTE required by this bound
 
-fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
+fn make_non_send_coroutine() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
     make_gen1(Arc::new(RefCell::new(0)))
 }
 
 fn test1() {
     let send_gen = || {
-        let _non_send_gen = make_non_send_generator();
+        let _non_send_gen = make_non_send_coroutine();
         //~^ NOTE not `Send`
         yield;
         //~^ NOTE yield occurs here
         //~| NOTE value is used across a yield
     };
     require_send(send_gen);
-    //~^ ERROR generator cannot be sent between threads
+    //~^ ERROR coroutine cannot be sent between threads
     //~| NOTE not `Send`
     //~| NOTE use `std::sync::RwLock` instead
 }
 
-pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
 //~^ NOTE appears within the type
 //~| NOTE expansion of desugaring
-    || { //~ NOTE used within this generator
+    || { //~ NOTE used within this coroutine
         yield;
         t
     }
 }
-fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> { //~ NOTE appears within the type
+fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> { //~ NOTE appears within the type
 //~^ NOTE expansion of desugaring
     make_gen2(Arc::new(RefCell::new(0)))
 }
 
 fn test2() {
-    let send_gen = || { //~ NOTE used within this generator
-        let _non_send_gen = make_non_send_generator2();
+    let send_gen = || { //~ NOTE used within this coroutine
+        let _non_send_gen = make_non_send_coroutine2();
         yield;
     };
     require_send(send_gen);
diff --git a/tests/ui/generator/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr
index 8080048222f..5efa72ad5fe 100644
--- a/tests/ui/generator/issue-68112.stderr
+++ b/tests/ui/coroutine/issue-68112.stderr
@@ -1,16 +1,16 @@
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/issue-68112.rs:40:5
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |     ^^^^^^^^^^^^ coroutine is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
-note: generator is not `Send` as this value is used across a yield
+note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/issue-68112.rs:36:9
    |
-LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
+LL |         let _non_send_gen = make_non_send_coroutine();
+   |             ------------- has type `impl Coroutine<Return = Arc<RefCell<i32>>>` which is not `Send`
 LL |
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
@@ -29,23 +29,23 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = 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 generator
+note: required because it's used within this coroutine
   --> $DIR/issue-68112.rs:49:5
    |
 LL |     || {
    |     ^^
-note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+note: required because it appears within the type `impl Coroutine<Return = Arc<RefCell<i32>>>`
   --> $DIR/issue-68112.rs:46:30
    |
-LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+LL | pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+note: required because it appears within the type `impl Coroutine<Return = Arc<RefCell<i32>>>`
   --> $DIR/issue-68112.rs:54:34
    |
-LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`
-note: required because it's used within this generator
+   = note: required because it captures the following types: `impl Coroutine<Return = Arc<RefCell<i32>>>`
+note: required because it's used within this coroutine
   --> $DIR/issue-68112.rs:60:20
    |
 LL |     let send_gen = || {
diff --git a/tests/ui/generator/issue-69017.rs b/tests/ui/coroutine/issue-69017.rs
index 511deb60e45..7aaa1ee03c4 100644
--- a/tests/ui/generator/issue-69017.rs
+++ b/tests/ui/coroutine/issue-69017.rs
@@ -4,12 +4,12 @@
 //
 // check-pass
 
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn gen() -> impl Generator<usize> {
+fn gen() -> impl Coroutine<usize> {
     |_: usize| {
         println!("-> {}", yield);
     }
diff --git a/tests/ui/generator/issue-69039.rs b/tests/ui/coroutine/issue-69039.rs
index ccc141860aa..041985e15a3 100644
--- a/tests/ui/generator/issue-69039.rs
+++ b/tests/ui/coroutine/issue-69039.rs
@@ -1,14 +1,14 @@
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 
 fn mkstr(my_name: String, my_mood: String) -> String {
     format!("{} is {}", my_name.trim(), my_mood.trim())
 }
 
-fn my_scenario() -> impl Generator<String, Yield = &'static str, Return = String> {
+fn my_scenario() -> impl Coroutine<String, Yield = &'static str, Return = String> {
     |_arg: String| {
         let my_name = yield "What is your name?";
         let my_mood = yield "How are you feeling?";
@@ -21,14 +21,14 @@ fn main() {
 
     assert_eq!(
         my_session.as_mut().resume("_arg".to_string()),
-        GeneratorState::Yielded("What is your name?")
+        CoroutineState::Yielded("What is your name?")
     );
     assert_eq!(
         my_session.as_mut().resume("Your Name".to_string()),
-        GeneratorState::Yielded("How are you feeling?")
+        CoroutineState::Yielded("How are you feeling?")
     );
     assert_eq!(
         my_session.as_mut().resume("Sensory Organs".to_string()),
-        GeneratorState::Complete("Your Name is Sensory Organs".to_string())
+        CoroutineState::Complete("Your Name is Sensory Organs".to_string())
     );
 }
diff --git a/tests/ui/coroutine/issue-87142.rs b/tests/ui/coroutine/issue-87142.rs
new file mode 100644
index 00000000000..b5708c4b385
--- /dev/null
+++ b/tests/ui/coroutine/issue-87142.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Cdebuginfo=2
+// build-pass
+
+// Regression test for #87142
+// This test needs the above flags and the "lib" crate type.
+
+#![feature(impl_trait_in_assoc_type, coroutine_trait, coroutines)]
+#![crate_type = "lib"]
+
+use std::ops::Coroutine;
+
+pub trait CoroutineProviderAlt: Sized {
+    type Coro: Coroutine<(), Return = (), Yield = ()>;
+
+    fn start(ctx: Context<Self>) -> Self::Coro;
+}
+
+pub struct Context<G: 'static + CoroutineProviderAlt> {
+    pub link: Box<G::Coro>,
+}
+
+impl CoroutineProviderAlt for () {
+    type Coro = impl Coroutine<(), Return = (), Yield = ()>;
+    fn start(ctx: Context<Self>) -> Self::Coro {
+        move || {
+            match ctx {
+                _ => (),
+            }
+            yield ();
+        }
+    }
+}
diff --git a/tests/ui/generator/issue-88653.rs b/tests/ui/coroutine/issue-88653.rs
index 1d9377bcef4..ec4c2054758 100644
--- a/tests/ui/generator/issue-88653.rs
+++ b/tests/ui/coroutine/issue-88653.rs
@@ -1,14 +1,14 @@
 // Regression test for #88653, where a confusing warning about a
-// type mismatch in generator arguments was issued.
+// type mismatch in coroutine arguments was issued.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn foo(bar: bool) -> impl Generator<(bool,)> {
-    //~^ ERROR: type mismatch in generator arguments [E0631]
+fn foo(bar: bool) -> impl Coroutine<(bool,)> {
+    //~^ ERROR: type mismatch in coroutine arguments [E0631]
     //~| NOTE: expected due to this
-    //~| NOTE: expected generator signature `fn((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`
     |bar| {
diff --git a/tests/ui/generator/issue-88653.stderr b/tests/ui/coroutine/issue-88653.stderr
index b742c6e2f1c..3ae50b5aff2 100644
--- a/tests/ui/generator/issue-88653.stderr
+++ b/tests/ui/coroutine/issue-88653.stderr
@@ -1,14 +1,14 @@
-error[E0631]: type mismatch in generator arguments
+error[E0631]: type mismatch in coroutine arguments
   --> $DIR/issue-88653.rs:8:22
    |
-LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
+LL | fn foo(bar: bool) -> impl Coroutine<(bool,)> {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
 ...
 LL |     |bar| {
    |     ----- found signature defined here
    |
-   = note: expected generator signature `fn((bool,)) -> _`
-              found generator signature `fn(bool) -> _`
+   = note: expected coroutine signature `fn((bool,)) -> _`
+              found coroutine signature `fn(bool) -> _`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/issue-91477.rs b/tests/ui/coroutine/issue-91477.rs
index 6c027feb422..c98546f7971 100644
--- a/tests/ui/generator/issue-91477.rs
+++ b/tests/ui/coroutine/issue-91477.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn foo() -> impl Sized {
     yield 1; //~ ERROR E0627
diff --git a/tests/ui/generator/issue-91477.stderr b/tests/ui/coroutine/issue-91477.stderr
index 4597dc1bcdf..0ab3c1fbabc 100644
--- a/tests/ui/generator/issue-91477.stderr
+++ b/tests/ui/coroutine/issue-91477.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield expression outside of generator literal
+error[E0627]: yield expression outside of coroutine literal
   --> $DIR/issue-91477.rs:4:5
    |
 LL |     yield 1;
diff --git a/tests/ui/generator/issue-93161.rs b/tests/ui/coroutine/issue-93161.rs
index ae8603b7c09..ae8603b7c09 100644
--- a/tests/ui/generator/issue-93161.rs
+++ b/tests/ui/coroutine/issue-93161.rs
diff --git a/tests/ui/generator/iterator-count.rs b/tests/ui/coroutine/iterator-count.rs
index 90eefe02f66..322e56f8a8b 100644
--- a/tests/ui/generator/iterator-count.rs
+++ b/tests/ui/coroutine/iterator-count.rs
@@ -1,27 +1,27 @@
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::marker::Unpin;
-use std::ops::{GeneratorState, Generator};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 struct W<T>(T);
 
-// This impl isn't safe in general, but the generator used in this test is movable
+// This impl isn't safe in general, but the coroutine used in this test is movable
 // so it won't cause problems.
-impl<T: Generator<(), Return = ()> + Unpin> Iterator for W<T> {
+impl<T: Coroutine<(), Return = ()> + Unpin> Iterator for W<T> {
     type Item = T::Yield;
 
     fn next(&mut self) -> Option<Self::Item> {
         match Pin::new(&mut self.0).resume(()) {
-            GeneratorState::Complete(..) => None,
-            GeneratorState::Yielded(v) => Some(v),
+            CoroutineState::Complete(..) => None,
+            CoroutineState::Yielded(v) => Some(v),
         }
     }
 }
 
-fn test() -> impl Generator<(), Return=(), Yield=u8> + Unpin {
+fn test() -> impl Coroutine<(), Return = (), Yield = u8> + Unpin {
     || {
         for i in 1..6 {
             yield i
diff --git a/tests/ui/generator/layout-error.rs b/tests/ui/coroutine/layout-error.rs
index 7c3d187409a..87da60700a4 100644
--- a/tests/ui/generator/layout-error.rs
+++ b/tests/ui/coroutine/layout-error.rs
@@ -1,4 +1,4 @@
-// Verifies that computing a layout of a generator tainted by type errors
+// Verifies that computing a layout of a coroutine tainted by type errors
 // doesn't ICE. Regression test for #80998.
 //
 // edition:2018
diff --git a/tests/ui/generator/layout-error.stderr b/tests/ui/coroutine/layout-error.stderr
index b1a258f4f2c..b1a258f4f2c 100644
--- a/tests/ui/generator/layout-error.stderr
+++ b/tests/ui/coroutine/layout-error.stderr
diff --git a/tests/ui/generator/live-upvar-across-yield.rs b/tests/ui/coroutine/live-upvar-across-yield.rs
index 6a2e42a5573..740a446e737 100644
--- a/tests/ui/generator/live-upvar-across-yield.rs
+++ b/tests/ui/coroutine/live-upvar-across-yield.rs
@@ -1,8 +1,8 @@
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/ui/generator/match-bindings.rs b/tests/ui/coroutine/match-bindings.rs
index 865904a57d4..1a5b3cdb026 100644
--- a/tests/ui/generator/match-bindings.rs
+++ b/tests/ui/coroutine/match-bindings.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 enum Enum {
     A(String),
@@ -9,7 +9,7 @@ enum Enum {
 }
 
 fn main() {
-    || { //~ WARN unused generator that must be used
+    || { //~ WARN unused coroutine that must be used
         loop {
             if let true = true {
                 match Enum::A(String::new()) {
diff --git a/tests/ui/generator/match-bindings.stderr b/tests/ui/coroutine/match-bindings.stderr
index 3dd2d595445..a7aa6eadb95 100644
--- a/tests/ui/generator/match-bindings.stderr
+++ b/tests/ui/coroutine/match-bindings.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/match-bindings.rs:12:5
    |
 LL | /     || {
@@ -10,7 +10,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/metadata-sufficient-for-layout.rs b/tests/ui/coroutine/metadata-sufficient-for-layout.rs
index d0e648ee775..434a2801597 100644
--- a/tests/ui/generator/metadata-sufficient-for-layout.rs
+++ b/tests/ui/coroutine/metadata-sufficient-for-layout.rs
@@ -1,4 +1,4 @@
-// Check that the layout of a generator is available when auxiliary crate
+// Check that the layout of a coroutine is available when auxiliary crate
 // is compiled with --emit metadata.
 //
 // Regression test for #80998.
@@ -6,15 +6,15 @@
 // aux-build:metadata-sufficient-for-layout.rs
 
 #![feature(type_alias_impl_trait, rustc_attrs)]
-#![feature(generator_trait)]
+#![feature(coroutine_trait)]
 
 extern crate metadata_sufficient_for_layout;
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-type F = impl Generator<(), Yield = (), Return = ()>;
+type F = impl Coroutine<(), Yield = (), Return = ()>;
 
-// Static queries the layout of the generator.
+// Static queries the layout of the coroutine.
 static A: Option<F> = None;
 
 fn f() -> F {
diff --git a/tests/ui/generator/metadata-sufficient-for-layout.stderr b/tests/ui/coroutine/metadata-sufficient-for-layout.stderr
index 3488b04f226..3488b04f226 100644
--- a/tests/ui/generator/metadata-sufficient-for-layout.stderr
+++ b/tests/ui/coroutine/metadata-sufficient-for-layout.stderr
diff --git a/tests/ui/coroutine/nested_coroutine.rs b/tests/ui/coroutine/nested_coroutine.rs
new file mode 100644
index 00000000000..04f4aa77153
--- /dev/null
+++ b/tests/ui/coroutine/nested_coroutine.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+fn main() {
+    let _coroutine = || {
+        let mut sub_coroutine = || {
+            yield 2;
+        };
+
+        match Pin::new(&mut sub_coroutine).resume(()) {
+            CoroutineState::Yielded(x) => {
+                yield x;
+            }
+            _ => panic!(),
+        };
+    };
+}
diff --git a/tests/ui/generator/niche-in-generator.rs b/tests/ui/coroutine/niche-in-coroutine.rs
index 42bee81f524..7ad4c6bc98a 100644
--- a/tests/ui/generator/niche-in-generator.rs
+++ b/tests/ui/coroutine/niche-in-coroutine.rs
@@ -1,8 +1,8 @@
-// Test that niche finding works with captured generator upvars.
+// Test that niche finding works with captured coroutine upvars.
 
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 use std::mem::size_of_val;
 
diff --git a/tests/ui/generator/non-static-is-unpin.rs b/tests/ui/coroutine/non-static-is-unpin.rs
index a5dde3912cc..d6ded53ae5a 100644
--- a/tests/ui/generator/non-static-is-unpin.rs
+++ b/tests/ui/coroutine/non-static-is-unpin.rs
@@ -2,7 +2,7 @@
 //[next] compile-flags: -Ztrait-solver=next
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![allow(dropping_copy_types)]
 
 use std::marker::{PhantomPinned, Unpin};
@@ -11,7 +11,7 @@ fn assert_unpin<G: Unpin>(_: G) {
 }
 
 fn main() {
-    // Even though this generator holds a `PhantomPinned` in its environment, it
+    // Even though this coroutine holds a `PhantomPinned` in its environment, it
     // remains `Unpin`.
     assert_unpin(|| {
         let pinned = PhantomPinned;
diff --git a/tests/ui/generator/not-send-sync.rs b/tests/ui/coroutine/not-send-sync.rs
index 16c8cd47629..dd6182c10de 100644
--- a/tests/ui/generator/not-send-sync.rs
+++ b/tests/ui/coroutine/not-send-sync.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 #![feature(negative_impls)]
 
 struct NotSend;
@@ -12,14 +12,14 @@ fn main() {
     fn assert_send<T: Send>(_: T) {}
 
     assert_sync(|| {
-        //~^ ERROR: generator cannot be shared between threads safely
+        //~^ ERROR: coroutine cannot be shared between threads safely
         let a = NotSync;
         yield;
         drop(a);
     });
 
     assert_send(|| {
-        //~^ ERROR: generator cannot be sent between threads safely
+        //~^ ERROR: coroutine cannot be sent between threads safely
         let a = NotSend;
         yield;
         drop(a);
diff --git a/tests/ui/generator/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr
index 13ce687e0bb..b33a1e63aaf 100644
--- a/tests/ui/generator/not-send-sync.stderr
+++ b/tests/ui/coroutine/not-send-sync.stderr
@@ -1,11 +1,11 @@
-error: generator cannot be shared between threads safely
+error: coroutine cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:14:5
    |
 LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+   |     ^^^^^^^^^^^ coroutine is not `Sync`
    |
-   = help: within `{generator@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`
-note: generator is not `Sync` as this value is used across a yield
+   = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`
+note: coroutine is not `Sync` as this value is used across a yield
   --> $DIR/not-send-sync.rs:17:9
    |
 LL |         let a = NotSync;
@@ -18,14 +18,14 @@ note: required by a bound in `assert_sync`
 LL |     fn assert_sync<T: Sync>(_: T) {}
    |                       ^^^^ required by this bound in `assert_sync`
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/not-send-sync.rs:21:5
    |
 LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+   |     ^^^^^^^^^^^ coroutine is not `Send`
    |
-   = help: within `{generator@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`
+note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/not-send-sync.rs:24:9
    |
 LL |         let a = NotSend;
diff --git a/tests/ui/generator/overlap-locals.rs b/tests/ui/coroutine/overlap-locals.rs
index 101c8714fa8..7c151270bb5 100644
--- a/tests/ui/generator/overlap-locals.rs
+++ b/tests/ui/coroutine/overlap-locals.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let a = || {
diff --git a/tests/ui/generator/panic-drops-resume.rs b/tests/ui/coroutine/panic-drops-resume.rs
index 4c3caeb14d6..e866f216a24 100644
--- a/tests/ui/generator/panic-drops-resume.rs
+++ b/tests/ui/coroutine/panic-drops-resume.rs
@@ -1,11 +1,11 @@
-//! Tests that panics inside a generator will correctly drop the initial resume argument.
+//! Tests that panics inside a coroutine will correctly drop the initial resume argument.
 
 // run-pass
 // needs-unwind
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/tests/ui/generator/panic-drops.rs b/tests/ui/coroutine/panic-drops.rs
index 65001fd879b..7e37279b9eb 100644
--- a/tests/ui/generator/panic-drops.rs
+++ b/tests/ui/coroutine/panic-drops.rs
@@ -2,9 +2,9 @@
 // needs-unwind
 
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::panic;
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/tests/ui/generator/panic-safe.rs b/tests/ui/coroutine/panic-safe.rs
index 3db80bb5821..9aa42756544 100644
--- a/tests/ui/generator/panic-safe.rs
+++ b/tests/ui/coroutine/panic-safe.rs
@@ -2,9 +2,9 @@
 // needs-unwind
 
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 use std::panic;
 
diff --git a/tests/ui/generator/parent-expression.rs b/tests/ui/coroutine/parent-expression.rs
index 198b14528aa..4d40192c07a 100644
--- a/tests/ui/generator/parent-expression.rs
+++ b/tests/ui/coroutine/parent-expression.rs
@@ -1,4 +1,4 @@
-#![feature(generators, negative_impls, rustc_attrs)]
+#![feature(coroutines, negative_impls, rustc_attrs)]
 
 macro_rules! type_combinations {
     (
diff --git a/tests/ui/generator/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr
index 25a3b051b1f..6b611bc3f10 100644
--- a/tests/ui/generator/parent-expression.stderr
+++ b/tests/ui/coroutine/parent-expression.stderr
@@ -1,8 +1,8 @@
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -13,8 +13,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`
+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() }) {
@@ -38,11 +38,11 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -53,8 +53,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`
+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() }) {
@@ -78,11 +78,11 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/parent-expression.rs:23:13
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |               ^^^^^^^^^^^ coroutine is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -93,8 +93,8 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{generator@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
-note: generator is not `Send` as this value is used across a yield
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+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() }) {
diff --git a/tests/ui/generator/partial-drop.rs b/tests/ui/coroutine/partial-drop.rs
index 868f36adce2..a4347f52a70 100644
--- a/tests/ui/generator/partial-drop.rs
+++ b/tests/ui/coroutine/partial-drop.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(negative_impls, generators)]
+#![feature(negative_impls, coroutines)]
 
 struct Foo;
 impl !Send for Foo {}
diff --git a/tests/ui/generator/partial-initialization-across-yield.rs b/tests/ui/coroutine/partial-initialization-across-yield.rs
index 65d9e6d39ca..75ad5a22804 100644
--- a/tests/ui/generator/partial-initialization-across-yield.rs
+++ b/tests/ui/coroutine/partial-initialization-across-yield.rs
@@ -1,7 +1,7 @@
-// Test that we don't allow yielding from a generator while a local is partially
+// Test that we don't allow yielding from a coroutine while a local is partially
 // initialized.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 struct S { x: i32, y: i32 }
 struct T(i32, i32);
diff --git a/tests/ui/generator/partial-initialization-across-yield.stderr b/tests/ui/coroutine/partial-initialization-across-yield.stderr
index 3f9f1c046ba..3f9f1c046ba 100644
--- a/tests/ui/generator/partial-initialization-across-yield.stderr
+++ b/tests/ui/coroutine/partial-initialization-across-yield.stderr
diff --git a/tests/ui/generator/pattern-borrow.rs b/tests/ui/coroutine/pattern-borrow.rs
index d1936370819..76084433d47 100644
--- a/tests/ui/generator/pattern-borrow.rs
+++ b/tests/ui/coroutine/pattern-borrow.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 enum Test { A(i32), B, }
 
@@ -6,7 +6,7 @@ fn main() { }
 
 fn fun(test: Test) {
     move || {
-        if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+        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/generator/pattern-borrow.stderr b/tests/ui/coroutine/pattern-borrow.stderr
index d78da510491..ddb3bf66214 100644
--- a/tests/ui/generator/pattern-borrow.stderr
+++ b/tests/ui/coroutine/pattern-borrow.stderr
@@ -1,4 +1,4 @@
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/pattern-borrow.rs:9:24
    |
 LL |         if let Test::A(ref _a) = test {
diff --git a/tests/ui/coroutine/pin-box-coroutine.rs b/tests/ui/coroutine/pin-box-coroutine.rs
new file mode 100644
index 00000000000..e348551a642
--- /dev/null
+++ b/tests/ui/coroutine/pin-box-coroutine.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+
+fn assert_coroutine<G: Coroutine>(_: G) {
+}
+
+fn main() {
+    assert_coroutine(static || yield);
+    assert_coroutine(Box::pin(static || yield));
+}
diff --git a/tests/ui/generator/print/generator-print-verbose-1.rs b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs
index e52234c08a3..c47d7572ca7 100644
--- a/tests/ui/generator/print/generator-print-verbose-1.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs
@@ -1,22 +1,22 @@
 // compile-flags: -Zverbose
 
-// Same as: tests/ui/generator/issue-68112.stderr
+// Same as: tests/ui/coroutine/issue-68112.stderr
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::{
     cell::RefCell,
     sync::Arc,
     pin::Pin,
-    ops::{Generator, GeneratorState},
+    ops::{Coroutine, CoroutineState},
 };
 
 pub struct Ready<T>(Option<T>);
-impl<T: Unpin> Generator<()> for Ready<T> {
+impl<T: Unpin> Coroutine<()> for Ready<T> {
     type Return = T;
     type Yield = ();
-    fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> {
-        GeneratorState::Complete(self.0.take().unwrap())
+    fn resume(mut self: Pin<&mut Self>, _args: ()) -> CoroutineState<(), T> {
+        CoroutineState::Complete(self.0.take().unwrap())
     }
 }
 pub fn make_gen1<T>(t: T) -> Ready<T> {
@@ -25,32 +25,32 @@ pub fn make_gen1<T>(t: T) -> Ready<T> {
 
 fn require_send(_: impl Send) {}
 
-fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
+fn make_non_send_coroutine() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
     make_gen1(Arc::new(RefCell::new(0)))
 }
 
 fn test1() {
     let send_gen = || {
-        let _non_send_gen = make_non_send_generator();
+        let _non_send_gen = make_non_send_coroutine();
         yield;
     };
     require_send(send_gen);
-    //~^ ERROR generator cannot be sent between threads
+    //~^ ERROR coroutine cannot be sent between threads
 }
 
-pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
     || {
         yield;
         t
     }
 }
-fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
     make_gen2(Arc::new(RefCell::new(0)))
 }
 
 fn test2() {
     let send_gen = || {
-        let _non_send_gen = make_non_send_generator2();
+        let _non_send_gen = make_non_send_coroutine2();
         yield;
     };
     require_send(send_gen);
diff --git a/tests/ui/generator/print/generator-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
index d949543de41..bcdcbc154cf 100644
--- a/tests/ui/generator/print/generator-print-verbose-1.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
@@ -1,26 +1,26 @@
-error: generator cannot be sent between threads safely
-  --> $DIR/generator-print-verbose-1.rs:37:5
+error: coroutine cannot be sent between threads safely
+  --> $DIR/coroutine-print-verbose-1.rs:37:5
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |     ^^^^^^^^^^^^ coroutine is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
-note: generator is not `Send` as this value is used across a yield
-  --> $DIR/generator-print-verbose-1.rs:35:9
+note: coroutine is not `Send` as this value is used across a yield
+  --> $DIR/coroutine-print-verbose-1.rs:35:9
    |
-LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[7d1d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+LL |         let _non_send_gen = make_non_send_coroutine();
+   |             ------------- has type `Opaque(DefId(0:34 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 note: required by a bound in `require_send`
-  --> $DIR/generator-print-verbose-1.rs:26:25
+  --> $DIR/coroutine-print-verbose-1.rs:26:25
    |
 LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-1.rs:56:5
+  --> $DIR/coroutine-print-verbose-1.rs:56:5
    |
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
@@ -28,29 +28,29 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = 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 generator
-  --> $DIR/generator-print-verbose-1.rs:42:5
+note: required because it's used within this coroutine
+  --> $DIR/coroutine-print-verbose-1.rs:42:5
    |
 LL |     || {
    |     ^^
-note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[7d1d]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
-  --> $DIR/generator-print-verbose-1.rs:41:30
+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
    |
-LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+LL | pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`
-  --> $DIR/generator-print-verbose-1.rs:47:34
+note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
+  --> $DIR/coroutine-print-verbose-1.rs:47:34
    |
-LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[7d1d]::make_non_send_generator2::{opaque#0}), [])`
-note: required because it's used within this generator
-  --> $DIR/generator-print-verbose-1.rs:52:20
+   = note: required because it captures the following types: `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
+note: required because it's used within this coroutine
+  --> $DIR/coroutine-print-verbose-1.rs:52:20
    |
 LL |     let send_gen = || {
    |                    ^^
 note: required by a bound in `require_send`
-  --> $DIR/generator-print-verbose-1.rs:26:25
+  --> $DIR/coroutine-print-verbose-1.rs:26:25
    |
 LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
diff --git a/tests/ui/generator/print/generator-print-verbose-2.rs b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs
index e53a7ef8cc1..c65c33cb4ba 100644
--- a/tests/ui/generator/print/generator-print-verbose-2.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs
@@ -1,7 +1,7 @@
 // compile-flags: -Zverbose
 
-// Same as test/ui/generator/not-send-sync.rs
-#![feature(generators)]
+// Same as test/ui/coroutine/not-send-sync.rs
+#![feature(coroutines)]
 #![feature(negative_impls)]
 
 struct NotSend;
@@ -15,14 +15,14 @@ fn main() {
     fn assert_send<T: Send>(_: T) {}
 
     assert_sync(|| {
-        //~^ ERROR: generator cannot be shared between threads safely
+        //~^ ERROR: coroutine cannot be shared between threads safely
         let a = NotSync;
         yield;
         drop(a);
     });
 
     assert_send(|| {
-        //~^ ERROR: generator cannot be sent between threads safely
+        //~^ ERROR: coroutine cannot be sent between threads safely
         let a = NotSend;
         yield;
         drop(a);
diff --git a/tests/ui/generator/print/generator-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
index 8ff7557619f..e9c7a8ffcaa 100644
--- a/tests/ui/generator/print/generator-print-verbose-2.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
@@ -1,39 +1,39 @@
-error: generator cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-2.rs:17:5
+error: coroutine cannot be shared between threads safely
+  --> $DIR/coroutine-print-verbose-2.rs:17:5
    |
 LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+   |     ^^^^^^^^^^^ coroutine is not `Sync`
    |
    = help: within `{main::{closure#0} upvar_tys=() {main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`
-note: generator is not `Sync` as this value is used across a yield
-  --> $DIR/generator-print-verbose-2.rs:20:9
+note: coroutine is not `Sync` as this value is used across a yield
+  --> $DIR/coroutine-print-verbose-2.rs:20:9
    |
 LL |         let a = NotSync;
    |             - has type `NotSync` which is not `Sync`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `a` maybe used later
 note: required by a bound in `assert_sync`
-  --> $DIR/generator-print-verbose-2.rs:14:23
+  --> $DIR/coroutine-print-verbose-2.rs:14:23
    |
 LL |     fn assert_sync<T: Sync>(_: T) {}
    |                       ^^^^ required by this bound in `assert_sync`
 
-error: generator cannot be sent between threads safely
-  --> $DIR/generator-print-verbose-2.rs:24:5
+error: coroutine cannot be sent between threads safely
+  --> $DIR/coroutine-print-verbose-2.rs:24:5
    |
 LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+   |     ^^^^^^^^^^^ coroutine is not `Send`
    |
    = help: within `{main::{closure#1} upvar_tys=() {main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`
-note: generator is not `Send` as this value is used across a yield
-  --> $DIR/generator-print-verbose-2.rs:27:9
+note: coroutine is not `Send` as this value is used across a yield
+  --> $DIR/coroutine-print-verbose-2.rs:27:9
    |
 LL |         let a = NotSend;
    |             - has type `NotSend` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `a` maybe used later
 note: required by a bound in `assert_send`
-  --> $DIR/generator-print-verbose-2.rs:15:23
+  --> $DIR/coroutine-print-verbose-2.rs:15:23
    |
 LL |     fn assert_send<T: Send>(_: T) {}
    |                       ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/generator/print/generator-print-verbose-3.rs b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs
index 8689539ec8e..3e4bb628176 100644
--- a/tests/ui/generator/print/generator-print-verbose-3.rs
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs
@@ -1,10 +1,10 @@
 // compile-flags: -Zverbose
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 fn main() {
     let x = "Type mismatch test";
-    let generator :() = || {
+    let coroutine :() = || {
     //~^ ERROR mismatched types
         yield 1i32;
         return x
diff --git a/tests/ui/generator/print/generator-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
index 69358ed0a91..fb80f29d10d 100644
--- a/tests/ui/generator/print/generator-print-verbose-3.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
@@ -1,7 +1,7 @@
 error[E0308]: mismatched types
-  --> $DIR/generator-print-verbose-3.rs:7:25
+  --> $DIR/coroutine-print-verbose-3.rs:7:25
    |
-LL |       let generator :() = || {
+LL |       let coroutine :() = || {
    |  ____________________--___^
    | |                    |
    | |                    expected due to this
@@ -9,10 +9,10 @@ LL | |
 LL | |         yield 1i32;
 LL | |         return x
 LL | |     };
-   | |_____^ expected `()`, found generator
+   | |_____^ expected `()`, found coroutine
    |
    = note: expected unit type `()`
-              found generator `{main::{closure#0} upvar_tys=(unavailable)}`
+              found coroutine `{main::{closure#0} upvar_tys=(unavailable)}`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/reborrow-mut-upvar.rs b/tests/ui/coroutine/reborrow-mut-upvar.rs
index dbd9e24e205..e4f717be8b5 100644
--- a/tests/ui/generator/reborrow-mut-upvar.rs
+++ b/tests/ui/coroutine/reborrow-mut-upvar.rs
@@ -1,9 +1,9 @@
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn _run(bar: &mut i32) {
-    || { //~ WARN unused generator that must be used
+    || { //~ WARN unused coroutine that must be used
         {
             let _baz = &*bar;
             yield;
diff --git a/tests/ui/generator/reborrow-mut-upvar.stderr b/tests/ui/coroutine/reborrow-mut-upvar.stderr
index 2e1fec35eaf..5b614ac4be8 100644
--- a/tests/ui/generator/reborrow-mut-upvar.stderr
+++ b/tests/ui/coroutine/reborrow-mut-upvar.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/reborrow-mut-upvar.rs:6:5
    |
 LL | /     || {
@@ -10,7 +10,7 @@ LL | |         *bar = 2;
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/ref-escapes-but-not-over-yield.rs b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
index 3856d8233bc..a9c13188ff3 100644
--- a/tests/ui/generator/ref-escapes-but-not-over-yield.rs
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs
@@ -1,7 +1,7 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn foo(x: &i32) {
-    // In this case, a reference to `b` escapes the generator, but not
+    // 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;
@@ -9,7 +9,7 @@ fn foo(x: &i32) {
         yield();
         let b = 5;
         a = &b;
-        //~^ ERROR borrowed data escapes outside of generator
+        //~^ ERROR borrowed data escapes outside of coroutine
     };
 }
 
diff --git a/tests/ui/generator/ref-escapes-but-not-over-yield.stderr b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
index 5fc81004098..4c8694e6786 100644
--- a/tests/ui/generator/ref-escapes-but-not-over-yield.stderr
+++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr
@@ -1,14 +1,14 @@
-error[E0521]: borrowed data escapes outside of generator
+error[E0521]: borrowed data escapes outside of coroutine
   --> $DIR/ref-escapes-but-not-over-yield.rs:11:9
    |
 LL |     let mut a = &3;
-   |         ----- `a` declared here, outside of the generator body
+   |         ----- `a` declared here, outside of the coroutine body
 ...
 LL |         a = &b;
    |         ^^^^--
    |         |   |
-   |         |   borrow is only valid in the generator body
-   |         reference to `b` escapes the generator body here
+   |         |   borrow is only valid in the coroutine body
+   |         reference to `b` escapes the coroutine body here
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/ref-upvar-not-send.rs b/tests/ui/coroutine/ref-upvar-not-send.rs
index eb9ef63ecfc..487fdeea2da 100644
--- a/tests/ui/generator/ref-upvar-not-send.rs
+++ b/tests/ui/coroutine/ref-upvar-not-send.rs
@@ -1,7 +1,7 @@
-// For `Send` generators, suggest a `T: Sync` requirement for `&T` upvars,
+// For `Send` coroutines, suggest a `T: Sync` requirement for `&T` upvars,
 // and suggest a `T: Send` requirement for `&mut T` upvars.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn assert_send<T: Send>(_: T) {}
 //~^ NOTE required by a bound in `assert_send`
@@ -13,16 +13,16 @@ fn main() {
     let x: &*mut () = &std::ptr::null_mut();
     let y: &mut *mut () = &mut std::ptr::null_mut();
     assert_send(move || {
-        //~^ ERROR generator cannot be sent between threads safely
-        //~| NOTE generator is not `Send`
+        //~^ ERROR coroutine cannot be sent between threads safely
+        //~| NOTE coroutine is not `Send`
         yield;
         let _x = x;
     });
     //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
     //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
     assert_send(move || {
-        //~^ ERROR generator cannot be sent between threads safely
-        //~| NOTE generator is not `Send`
+        //~^ ERROR coroutine cannot be sent between threads safely
+        //~| NOTE coroutine is not `Send`
         yield;
         let _y = y;
     });
diff --git a/tests/ui/generator/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr
index d6a2be977e4..7f18c6fba77 100644
--- a/tests/ui/generator/ref-upvar-not-send.stderr
+++ b/tests/ui/coroutine/ref-upvar-not-send.stderr
@@ -1,4 +1,4 @@
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/ref-upvar-not-send.rs:15:17
    |
 LL |       assert_send(move || {
@@ -8,7 +8,7 @@ LL | |
 LL | |         yield;
 LL | |         let _x = x;
 LL | |     });
-   | |_____^ generator is not `Send`
+   | |_____^ coroutine is not `Send`
    |
    = help: the trait `Sync` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
@@ -22,7 +22,7 @@ note: required by a bound in `assert_send`
 LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
-error: generator cannot be sent between threads safely
+error: coroutine cannot be sent between threads safely
   --> $DIR/ref-upvar-not-send.rs:23:17
    |
 LL |       assert_send(move || {
@@ -32,9 +32,9 @@ LL | |
 LL | |         yield;
 LL | |         let _y = y;
 LL | |     });
-   | |_____^ generator is not `Send`
+   | |_____^ coroutine is not `Send`
    |
-   = help: within `{generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`
+   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
   --> $DIR/ref-upvar-not-send.rs:27:18
    |
diff --git a/tests/ui/generator/reinit-in-match-guard.rs b/tests/ui/coroutine/reinit-in-match-guard.rs
index 260b341a525..1895de1f12b 100644
--- a/tests/ui/generator/reinit-in-match-guard.rs
+++ b/tests/ui/coroutine/reinit-in-match-guard.rs
@@ -1,6 +1,6 @@
 // build-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 #![allow(unused_assignments, dead_code)]
 
diff --git a/tests/ui/generator/resume-after-return.rs b/tests/ui/coroutine/resume-after-return.rs
index 01a059a161c..acbd8740a35 100644
--- a/tests/ui/generator/resume-after-return.rs
+++ b/tests/ui/coroutine/resume-after-return.rs
@@ -2,9 +2,9 @@
 // needs-unwind
 
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{GeneratorState, Generator};
+use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
 use std::panic;
 
@@ -17,12 +17,12 @@ fn main() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 
     match panic::catch_unwind(move || Pin::new(&mut foo).resume(())) {
-        Ok(_) => panic!("generator successfully resumed"),
+        Ok(_) => panic!("coroutine successfully resumed"),
         Err(_) => {}
     }
 }
diff --git a/tests/ui/generator/resume-arg-late-bound.rs b/tests/ui/coroutine/resume-arg-late-bound.rs
index 1c35ba80d2b..dd6d318afbc 100644
--- a/tests/ui/generator/resume-arg-late-bound.rs
+++ b/tests/ui/coroutine/resume-arg-late-bound.rs
@@ -1,11 +1,11 @@
-//! Tests that we cannot produce a generator that accepts a resume argument
+//! Tests that we cannot produce a coroutine that accepts a resume argument
 //! with any lifetime and then stores it across a `yield`.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+fn test(a: impl for<'a> Coroutine<&'a mut bool>) {}
 
 fn main() {
     let gen = |arg: &mut bool| {
diff --git a/tests/ui/generator/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr
index 34ee4036cc5..f1a8a8ed711 100644
--- a/tests/ui/generator/resume-arg-late-bound.stderr
+++ b/tests/ui/coroutine/resume-arg-late-bound.stderr
@@ -4,12 +4,12 @@ error[E0308]: mismatched types
 LL |     test(gen);
    |     ^^^^^^^^^ one type is more general than the other
    |
-   = note: expected trait `for<'a> Generator<&'a mut bool>`
-              found trait `Generator<&mut bool>`
+   = note: expected trait `for<'a> Coroutine<&'a mut bool>`
+              found trait `Coroutine<&mut bool>`
 note: the lifetime requirement is introduced here
   --> $DIR/resume-arg-late-bound.rs:8:17
    |
-LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/tests/ui/generator/resume-arg-size.rs b/tests/ui/coroutine/resume-arg-size.rs
index 195166f975b..22bb469f941 100644
--- a/tests/ui/generator/resume-arg-size.rs
+++ b/tests/ui/coroutine/resume-arg-size.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 #![allow(dropping_copy_types)]
 
 // run-pass
@@ -6,7 +6,7 @@
 use std::mem::size_of_val;
 
 fn main() {
-    // Generator taking a `Copy`able resume arg.
+    // Coroutine taking a `Copy`able resume arg.
     let gen_copy = |mut x: usize| {
         loop {
             drop(x);
@@ -14,7 +14,7 @@ fn main() {
         }
     };
 
-    // Generator taking a non-`Copy` resume arg.
+    // Coroutine taking a non-`Copy` resume arg.
     let gen_move = |mut x: Box<usize>| {
         loop {
             drop(x);
@@ -22,7 +22,7 @@ fn main() {
         }
     };
 
-    // Neither of these generators have the resume arg live across the `yield`, so they should be
+    // Neither of these coroutines have the resume arg live across the `yield`, so they should be
     // 1 Byte in size (only storing the discriminant)
     assert_eq!(size_of_val(&gen_copy), 1);
     assert_eq!(size_of_val(&gen_move), 1);
diff --git a/tests/ui/generator/resume-live-across-yield.rs b/tests/ui/coroutine/resume-live-across-yield.rs
index 4c4cf117a55..935e7d326be 100644
--- a/tests/ui/generator/resume-live-across-yield.rs
+++ b/tests/ui/coroutine/resume-live-across-yield.rs
@@ -1,8 +1,8 @@
 // run-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
@@ -27,11 +27,11 @@ fn main() {
 
     assert_eq!(
         g.as_mut().resume(Dropper(String::from("Hello world!"))),
-        GeneratorState::Yielded(())
+        CoroutineState::Yielded(())
     );
     assert_eq!(DROP.load(Ordering::Acquire), 0);
     match g.as_mut().resume(Dropper(String::from("Number Two"))) {
-        GeneratorState::Complete(dropper) => {
+        CoroutineState::Complete(dropper) => {
             assert_eq!(DROP.load(Ordering::Acquire), 1);
             assert_eq!(dropper.0, "Number Two");
             drop(dropper);
diff --git a/tests/ui/generator/retain-resume-ref.rs b/tests/ui/coroutine/retain-resume-ref.rs
index 0606ea71cdf..c9f995ab0cf 100644
--- a/tests/ui/generator/retain-resume-ref.rs
+++ b/tests/ui/coroutine/retain-resume-ref.rs
@@ -1,11 +1,11 @@
 //! This test ensures that a mutable reference cannot be passed as a resume argument twice.
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::marker::Unpin;
 use std::ops::{
-    Generator,
-    GeneratorState::{self, *},
+    Coroutine,
+    CoroutineState::{self, *},
 };
 use std::pin::Pin;
 
diff --git a/tests/ui/generator/retain-resume-ref.stderr b/tests/ui/coroutine/retain-resume-ref.stderr
index bc715c7030e..983443bbfeb 100644
--- a/tests/ui/generator/retain-resume-ref.stderr
+++ b/tests/ui/coroutine/retain-resume-ref.stderr
@@ -7,7 +7,7 @@ LL |     gen.as_mut().resume(&mut thing);
    |                         ^^^^^^^^^^ second mutable borrow occurs here
 LL |
 LL | }
-   | - first borrow might be used here, when `gen` is dropped and runs the destructor for generator
+   | - first borrow might be used here, when `gen` is dropped and runs the destructor for coroutine
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generator/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs
index 601a3141828..cfbbb9c1b31 100644
--- a/tests/ui/generator/size-moved-locals.rs
+++ b/tests/ui/coroutine/size-moved-locals.rs
@@ -4,7 +4,7 @@
 // `complex` below.)
 //
 // The exact sizes here can change (we'd like to know when they do). What we
-// don't want to see is the `complex` generator size being upwards of 2048 bytes
+// don't want to see is the `complex` coroutine size being upwards of 2048 bytes
 // (which would indicate it is reserving space for two copies of Foo.)
 //
 // See issue #59123 for a full explanation.
@@ -14,9 +14,9 @@
 // ignore-asmjs issue #62807
 // needs-unwind Size of Closures change on panic=abort
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 const FOO_SIZE: usize = 1024;
 struct Foo(#[allow(unused_tuple_struct_fields)] [u8; FOO_SIZE]);
@@ -25,7 +25,7 @@ impl Drop for Foo {
     fn drop(&mut self) {}
 }
 
-fn move_before_yield() -> impl Generator<Yield = (), Return = ()> {
+fn move_before_yield() -> impl Coroutine<Yield = (), Return = ()> {
     static || {
         let first = Foo([0; FOO_SIZE]);
         let _second = first;
@@ -36,7 +36,7 @@ fn move_before_yield() -> impl Generator<Yield = (), Return = ()> {
 
 fn noop() {}
 
-fn move_before_yield_with_noop() -> impl Generator<Yield = (), Return = ()> {
+fn move_before_yield_with_noop() -> impl Coroutine<Yield = (), Return = ()> {
     static || {
         let first = Foo([0; FOO_SIZE]);
         noop();
@@ -48,7 +48,7 @@ fn move_before_yield_with_noop() -> impl Generator<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 Generator<Yield = (), Return = ()> {
+fn overlap_move_points() -> impl Coroutine<Yield = (), Return = ()> {
     static || {
         let first = Foo([0; FOO_SIZE]);
         yield;
@@ -59,7 +59,7 @@ fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
-fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()> {
+fn overlap_x_and_y() -> impl Coroutine<Yield = (), Return = ()> {
     static || {
         let x = Foo([0; FOO_SIZE]);
         yield;
diff --git a/tests/ui/coroutine/sized-yield.rs b/tests/ui/coroutine/sized-yield.rs
new file mode 100644
index 00000000000..1368c88b522
--- /dev/null
+++ b/tests/ui/coroutine/sized-yield.rs
@@ -0,0 +1,14 @@
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn main() {
+    let s = String::from("foo");
+    let mut gen = move || {
+        //~^ ERROR the size for values of type
+        yield s[..];
+    };
+    Pin::new(&mut gen).resume(());
+    //~^ ERROR the size for values of type
+}
diff --git a/tests/ui/coroutine/sized-yield.stderr b/tests/ui/coroutine/sized-yield.stderr
new file mode 100644
index 00000000000..40663ac12de
--- /dev/null
+++ b/tests/ui/coroutine/sized-yield.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/sized-yield.rs:8:27
+   |
+LL |       let mut gen = move || {
+   |  ___________________________^
+LL | |
+LL | |         yield s[..];
+LL | |     };
+   | |_____^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = 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
+   |
+LL |     Pin::new(&mut gen).resume(());
+   |                        ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+note: required by a bound in `CoroutineState`
+  --> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/smoke-resume-args.rs b/tests/ui/coroutine/smoke-resume-args.rs
index fa9271c538f..a801989859e 100644
--- a/tests/ui/generator/smoke-resume-args.rs
+++ b/tests/ui/coroutine/smoke-resume-args.rs
@@ -3,20 +3,20 @@
 // revisions: default nomiropt
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::fmt::Debug;
 use std::marker::Unpin;
 use std::ops::{
-    Generator,
-    GeneratorState::{self, *},
+    Coroutine,
+    CoroutineState::{self, *},
 };
 use std::pin::Pin;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
-fn drain<G: Generator<R, Yield = Y> + Unpin, R, Y>(
+fn drain<G: Coroutine<R, Yield = Y> + Unpin, R, Y>(
     gen: &mut G,
-    inout: Vec<(R, GeneratorState<Y, G::Return>)>,
+    inout: Vec<(R, CoroutineState<Y, G::Return>)>,
 ) where
     Y: Debug + PartialEq,
     G::Return: Debug + PartialEq,
diff --git a/tests/ui/generator/smoke.rs b/tests/ui/coroutine/smoke.rs
index 7a917a05dd9..b74ed26865f 100644
--- a/tests/ui/generator/smoke.rs
+++ b/tests/ui/coroutine/smoke.rs
@@ -6,9 +6,9 @@
 // ignore-emscripten no threads support
 // compile-flags: --test
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{GeneratorState, Generator};
+use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
 use std::thread;
 
@@ -21,7 +21,7 @@ fn simple() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -37,7 +37,7 @@ fn return_capture() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(ref s) if *s == "foo" => {}
+        CoroutineState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -49,11 +49,11 @@ fn simple_yield() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Yielded(()) => {}
+        CoroutineState::Yielded(()) => {}
         s => panic!("bad state: {:?}", s),
     }
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -66,11 +66,11 @@ fn yield_capture() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Yielded(ref s) if *s == "foo" => {}
+        CoroutineState::Yielded(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -83,11 +83,11 @@ fn simple_yield_value() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Yielded(ref s) if *s == "bar" => {}
+        CoroutineState::Yielded(ref s) if *s == "bar" => {}
         s => panic!("bad state: {:?}", s),
     }
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(ref s) if *s == "foo" => {}
+        CoroutineState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -101,11 +101,11 @@ fn return_after_yield() {
     };
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Yielded(()) => {}
+        CoroutineState::Yielded(()) => {}
         s => panic!("bad state: {:?}", s),
     }
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(ref s) if *s == "foo" => {}
+        CoroutineState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
 }
@@ -153,11 +153,11 @@ fn send_over_threads() {
     let mut foo = || { yield };
     thread::spawn(move || {
         match Pin::new(&mut foo).resume(()) {
-            GeneratorState::Yielded(()) => {}
+            CoroutineState::Yielded(()) => {}
             s => panic!("bad state: {:?}", s),
         }
         match Pin::new(&mut foo).resume(()) {
-            GeneratorState::Complete(()) => {}
+            CoroutineState::Complete(()) => {}
             s => panic!("bad state: {:?}", s),
         }
     }).join().unwrap();
@@ -166,11 +166,11 @@ fn send_over_threads() {
     let mut foo = || { yield a };
     thread::spawn(move || {
         match Pin::new(&mut foo).resume(()) {
-            GeneratorState::Yielded(ref s) if *s == "a" => {}
+            CoroutineState::Yielded(ref s) if *s == "a" => {}
             s => panic!("bad state: {:?}", s),
         }
         match Pin::new(&mut foo).resume(()) {
-            GeneratorState::Complete(()) => {}
+            CoroutineState::Complete(()) => {}
             s => panic!("bad state: {:?}", s),
         }
     }).join().unwrap();
diff --git a/tests/ui/coroutine/static-coroutine.rs b/tests/ui/coroutine/static-coroutine.rs
new file mode 100644
index 00000000000..f9fd65b9793
--- /dev/null
+++ b/tests/ui/coroutine/static-coroutine.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(coroutines, coroutine_trait)]
+
+use std::pin::Pin;
+use std::ops::{Coroutine, CoroutineState};
+
+fn main() {
+    let mut coroutine = static || {
+        let a = true;
+        let b = &a;
+        yield;
+        assert_eq!(b as *const _, &a as *const _);
+    };
+    // SAFETY: We shadow the original coroutine variable so have no safe API to
+    // move it after this point.
+    let mut coroutine = unsafe { Pin::new_unchecked(&mut coroutine) };
+    assert_eq!(coroutine.as_mut().resume(()), CoroutineState::Yielded(()));
+    assert_eq!(coroutine.as_mut().resume(()), CoroutineState::Complete(()));
+}
diff --git a/tests/ui/generator/static-mut-reference-across-yield.rs b/tests/ui/coroutine/static-mut-reference-across-yield.rs
index 0fa6d9cdc77..07f810856a7 100644
--- a/tests/ui/generator/static-mut-reference-across-yield.rs
+++ b/tests/ui/coroutine/static-mut-reference-across-yield.rs
@@ -2,7 +2,7 @@
 // revisions: mir thir
 // [thir]compile-flags: -Zthir-unsafeck
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 static mut A: [i32; 5] = [1, 2, 3, 4, 5];
 
diff --git a/tests/ui/generator/static-not-unpin.current.stderr b/tests/ui/coroutine/static-not-unpin.current.stderr
index 242489841e8..cd607904f5a 100644
--- a/tests/ui/generator/static-not-unpin.current.stderr
+++ b/tests/ui/coroutine/static-not-unpin.current.stderr
@@ -1,8 +1,8 @@
-error[E0277]: `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
   --> $DIR/static-not-unpin.rs:17:18
    |
-LL |     assert_unpin(generator);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}`
+LL |     assert_unpin(coroutine);
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/generator/static-not-unpin.next.stderr b/tests/ui/coroutine/static-not-unpin.next.stderr
index 242489841e8..cd607904f5a 100644
--- a/tests/ui/generator/static-not-unpin.next.stderr
+++ b/tests/ui/coroutine/static-not-unpin.next.stderr
@@ -1,8 +1,8 @@
-error[E0277]: `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
   --> $DIR/static-not-unpin.rs:17:18
    |
-LL |     assert_unpin(generator);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/static-not-unpin.rs:14:25: 14:34}`
+LL |     assert_unpin(coroutine);
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/generator/static-not-unpin.rs b/tests/ui/coroutine/static-not-unpin.rs
index 30d3f291870..6ce78046dcc 100644
--- a/tests/ui/generator/static-not-unpin.rs
+++ b/tests/ui/coroutine/static-not-unpin.rs
@@ -1,7 +1,7 @@
 // revisions: current next
 //[next] compile-flags: -Ztrait-solver=next
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 // normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin"
 
@@ -11,8 +11,8 @@ fn assert_unpin<T: Unpin>(_: T) {
 }
 
 fn main() {
-    let mut generator = static || {
+    let mut coroutine = static || {
         yield;
     };
-    assert_unpin(generator); //~ ERROR E0277
+    assert_unpin(coroutine); //~ ERROR E0277
 }
diff --git a/tests/ui/generator/static-reference-across-yield.rs b/tests/ui/coroutine/static-reference-across-yield.rs
index 23b11593bb5..6496d8b86cc 100644
--- a/tests/ui/generator/static-reference-across-yield.rs
+++ b/tests/ui/coroutine/static-reference-across-yield.rs
@@ -1,5 +1,5 @@
 // build-pass
-#![feature(generators)]
+#![feature(coroutines)]
 
 static A: [i32; 5] = [1, 2, 3, 4, 5];
 
diff --git a/tests/ui/generator/too-live-local-in-immovable-gen.rs b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs
index e0b856db7a5..7eaa1552227 100644
--- a/tests/ui/generator/too-live-local-in-immovable-gen.rs
+++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs
@@ -1,15 +1,15 @@
 // run-pass
 #![allow(unused_unsafe)]
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     unsafe {
-        static move || { //~ WARN unused generator that must be used
-            // Tests that the generator transformation finds out that `a` is not live
+        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.
-            // The compiler will panic if the generator transformation finds that
+            // The compiler will panic if the coroutine transformation finds that
             // `a` is live and type checking finds it dead.
             let a = {
                 yield ();
diff --git a/tests/ui/generator/too-live-local-in-immovable-gen.stderr b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
index e262f213f63..4a67dbe71e1 100644
--- a/tests/ui/generator/too-live-local-in-immovable-gen.stderr
+++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
@@ -1,8 +1,8 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/too-live-local-in-immovable-gen.rs:8:9
    |
 LL | /         static move || {
-LL | |             // Tests that the generator transformation finds out that `a` is not live
+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.
 ...  |
@@ -10,7 +10,7 @@ LL | |             let _ = &a;
 LL | |         };
    | |_________^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/coroutine/too-many-parameters.rs b/tests/ui/coroutine/too-many-parameters.rs
new file mode 100644
index 00000000000..377d80c7b22
--- /dev/null
+++ b/tests/ui/coroutine/too-many-parameters.rs
@@ -0,0 +1,8 @@
+#![feature(coroutines)]
+
+fn main() {
+    |(), ()| {
+        //~^ error: too many parameters for a coroutine
+        yield;
+    };
+}
diff --git a/tests/ui/generator/too-many-parameters.stderr b/tests/ui/coroutine/too-many-parameters.stderr
index 22d40db3f26..54cf42e78d3 100644
--- a/tests/ui/generator/too-many-parameters.stderr
+++ b/tests/ui/coroutine/too-many-parameters.stderr
@@ -1,4 +1,4 @@
-error[E0628]: too many parameters for a generator (expected 0 or 1 parameters)
+error[E0628]: too many parameters for a coroutine (expected 0 or 1 parameters)
   --> $DIR/too-many-parameters.rs:4:5
    |
 LL |     |(), ()| {
diff --git a/tests/ui/generator/type-mismatch-error.rs b/tests/ui/coroutine/type-mismatch-error.rs
index d39c788a84b..0d04c21484c 100644
--- a/tests/ui/generator/type-mismatch-error.rs
+++ b/tests/ui/coroutine/type-mismatch-error.rs
@@ -1,11 +1,11 @@
 //! 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(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn f<G: Generator>(_: G, _: G::Return) {}
+fn f<G: Coroutine>(_: G, _: G::Return) {}
 
 fn main() {
     f(
diff --git a/tests/ui/generator/type-mismatch-error.stderr b/tests/ui/coroutine/type-mismatch-error.stderr
index 8f5949533e2..8f5949533e2 100644
--- a/tests/ui/generator/type-mismatch-error.stderr
+++ b/tests/ui/coroutine/type-mismatch-error.stderr
diff --git a/tests/ui/generator/type-mismatch-signature-deduction.rs b/tests/ui/coroutine/type-mismatch-signature-deduction.rs
index 8d1ce6c7a43..d4ca622e80f 100644
--- a/tests/ui/generator/type-mismatch-signature-deduction.rs
+++ b/tests/ui/coroutine/type-mismatch-signature-deduction.rs
@@ -1,8 +1,8 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn foo() -> impl Generator<Return = i32> {
+fn foo() -> impl Coroutine<Return = i32> {
     //~^ ERROR type mismatch
     || {
         if false {
diff --git a/tests/ui/generator/type-mismatch-signature-deduction.stderr b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
index fe1bade5577..f26e30a8e74 100644
--- a/tests/ui/generator/type-mismatch-signature-deduction.stderr
+++ b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr
@@ -18,10 +18,10 @@ LL |         Ok(5)
 LL |         Err(5)
    |         ++++ +
 
-error[E0271]: type mismatch resolving `<{generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7} as Generator>::Return == i32`
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7} as Coroutine>::Return == i32`
   --> $DIR/type-mismatch-signature-deduction.rs:5:13
    |
-LL | fn foo() -> impl Generator<Return = i32> {
+LL | fn foo() -> impl Coroutine<Return = i32> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<{integer}, _>`, found `i32`
    |
    = note: expected enum `Result<{integer}, _>`
diff --git a/tests/ui/generator/unresolved-ct-var.rs b/tests/ui/coroutine/unresolved-ct-var.rs
index 0316385fba9..0316385fba9 100644
--- a/tests/ui/generator/unresolved-ct-var.rs
+++ b/tests/ui/coroutine/unresolved-ct-var.rs
diff --git a/tests/ui/generator/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr
index 9badc1dc291..9badc1dc291 100644
--- a/tests/ui/generator/unresolved-ct-var.stderr
+++ b/tests/ui/coroutine/unresolved-ct-var.stderr
diff --git a/tests/ui/generator/unsized-capture-across-yield.rs b/tests/ui/coroutine/unsized-capture-across-yield.rs
index 7bcb0800ccf..ef9cbc1d677 100644
--- a/tests/ui/generator/unsized-capture-across-yield.rs
+++ b/tests/ui/coroutine/unsized-capture-across-yield.rs
@@ -1,11 +1,11 @@
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 #![feature(unsized_locals)]
 //~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn capture() -> impl Generator {
+fn capture() -> impl Coroutine {
     let b: [u8] = *(Box::new([]) as Box<[u8]>);
     move || {
         println!("{:?}", &b);
diff --git a/tests/ui/generator/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr
index 8a5b968a561..8a5b968a561 100644
--- a/tests/ui/generator/unsized-capture-across-yield.stderr
+++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr
diff --git a/tests/ui/generator/unsized-local-across-yield.rs b/tests/ui/coroutine/unsized-local-across-yield.rs
index f761f45c2af..7a8ed60e46a 100644
--- a/tests/ui/generator/unsized-local-across-yield.rs
+++ b/tests/ui/coroutine/unsized-local-across-yield.rs
@@ -1,11 +1,11 @@
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 #![feature(unsized_locals)]
 //~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn across() -> impl Generator {
+fn across() -> impl 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/generator/unsized-local-across-yield.stderr b/tests/ui/coroutine/unsized-local-across-yield.stderr
index 1942f266e6c..1942f266e6c 100644
--- a/tests/ui/generator/unsized-local-across-yield.stderr
+++ b/tests/ui/coroutine/unsized-local-across-yield.stderr
diff --git a/tests/ui/generator/xcrate-reachable.rs b/tests/ui/coroutine/xcrate-reachable.rs
index 1b1cff3387d..c6328448868 100644
--- a/tests/ui/generator/xcrate-reachable.rs
+++ b/tests/ui/coroutine/xcrate-reachable.rs
@@ -2,11 +2,11 @@
 
 // aux-build:xcrate-reachable.rs
 
-#![feature(generator_trait)]
+#![feature(coroutine_trait)]
 
 extern crate xcrate_reachable as foo;
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/ui/generator/xcrate.rs b/tests/ui/coroutine/xcrate.rs
index 40986bbeb65..4572d1cfd54 100644
--- a/tests/ui/generator/xcrate.rs
+++ b/tests/ui/coroutine/xcrate.rs
@@ -2,29 +2,29 @@
 
 // aux-build:xcrate.rs
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 extern crate xcrate;
 
-use std::ops::{GeneratorState, Generator};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
     let mut foo = xcrate::foo();
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 
     let mut foo = xcrate::bar(3);
 
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Yielded(3) => {}
+        CoroutineState::Yielded(3) => {}
         s => panic!("bad state: {:?}", s),
     }
     match Pin::new(&mut foo).resume(()) {
-        GeneratorState::Complete(()) => {}
+        CoroutineState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 }
diff --git a/tests/ui/generator/yield-in-args-rev.rs b/tests/ui/coroutine/yield-in-args-rev.rs
index 4c99bb3ef5e..b22c32ccd92 100644
--- a/tests/ui/generator/yield-in-args-rev.rs
+++ b/tests/ui/coroutine/yield-in-args-rev.rs
@@ -5,12 +5,12 @@
 // argument list is not treated as live across the yield by
 // type-checking.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn foo(_a: (), _b: &bool) {}
 
 fn bar() {
-    || { //~ WARN unused generator that must be used
+    || { //~ WARN unused coroutine that must be used
         let b = true;
         foo(yield, &b);
     };
diff --git a/tests/ui/generator/yield-in-args-rev.stderr b/tests/ui/coroutine/yield-in-args-rev.stderr
index a87248f6621..dbf46739e8b 100644
--- a/tests/ui/generator/yield-in-args-rev.stderr
+++ b/tests/ui/coroutine/yield-in-args-rev.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/yield-in-args-rev.rs:13:5
    |
 LL | /     || {
@@ -7,7 +7,7 @@ LL | |         foo(yield, &b);
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/yield-in-args.rs b/tests/ui/coroutine/yield-in-args.rs
index 80110af55ab..b2827148d77 100644
--- a/tests/ui/generator/yield-in-args.rs
+++ b/tests/ui/coroutine/yield-in-args.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn foo(_b: &bool, _a: ()) {}
 
diff --git a/tests/ui/generator/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr
index ee6d22c27cd..4ff97281d7b 100644
--- a/tests/ui/generator/yield-in-args.stderr
+++ b/tests/ui/coroutine/yield-in-args.stderr
@@ -1,4 +1,4 @@
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-in-args.rs:8:13
    |
 LL |         foo(&b, yield);
diff --git a/tests/ui/generator/yield-in-const.rs b/tests/ui/coroutine/yield-in-const.rs
index fe5ca822cec..22651f32cf8 100644
--- a/tests/ui/generator/yield-in-const.rs
+++ b/tests/ui/coroutine/yield-in-const.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 const A: u8 = { yield 3u8; 3u8};
 //~^ ERROR yield expression outside
diff --git a/tests/ui/generator/yield-in-const.stderr b/tests/ui/coroutine/yield-in-const.stderr
index dcf4fe63e64..7afcd83403e 100644
--- a/tests/ui/generator/yield-in-const.stderr
+++ b/tests/ui/coroutine/yield-in-const.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield expression outside of generator literal
+error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-const.rs:3:17
    |
 LL | const A: u8 = { yield 3u8; 3u8};
diff --git a/tests/ui/generator/yield-in-function.rs b/tests/ui/coroutine/yield-in-function.rs
index 29b811621de..a99312043bd 100644
--- a/tests/ui/generator/yield-in-function.rs
+++ b/tests/ui/coroutine/yield-in-function.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() { yield; }
 //~^ ERROR yield expression outside
diff --git a/tests/ui/generator/yield-in-function.stderr b/tests/ui/coroutine/yield-in-function.stderr
index 51cce198ca3..b2f839a65db 100644
--- a/tests/ui/generator/yield-in-function.stderr
+++ b/tests/ui/coroutine/yield-in-function.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield expression outside of generator literal
+error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-function.rs:3:13
    |
 LL | fn main() { yield; }
diff --git a/tests/ui/generator/yield-in-initializer.rs b/tests/ui/coroutine/yield-in-initializer.rs
index 0cab36e5f28..5a7b3a4feaf 100644
--- a/tests/ui/generator/yield-in-initializer.rs
+++ b/tests/ui/coroutine/yield-in-initializer.rs
@@ -1,9 +1,9 @@
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
-    static || { //~ WARN unused generator that must be used
+    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/generator/yield-in-initializer.stderr b/tests/ui/coroutine/yield-in-initializer.stderr
index ed14a2e3273..614df43f2f5 100644
--- a/tests/ui/generator/yield-in-initializer.stderr
+++ b/tests/ui/coroutine/yield-in-initializer.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/yield-in-initializer.rs:6:5
    |
 LL | /     static || {
@@ -10,7 +10,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/yield-in-static.rs b/tests/ui/coroutine/yield-in-static.rs
index d27fbb33ba1..45e0380d46d 100644
--- a/tests/ui/generator/yield-in-static.rs
+++ b/tests/ui/coroutine/yield-in-static.rs
@@ -1,4 +1,4 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 static B: u8 = { yield 3u8; 3u8};
 //~^ ERROR yield expression outside
diff --git a/tests/ui/generator/yield-in-static.stderr b/tests/ui/coroutine/yield-in-static.stderr
index d867f3ad345..17d58325e98 100644
--- a/tests/ui/generator/yield-in-static.stderr
+++ b/tests/ui/coroutine/yield-in-static.stderr
@@ -1,4 +1,4 @@
-error[E0627]: yield expression outside of generator literal
+error[E0627]: yield expression outside of coroutine literal
   --> $DIR/yield-in-static.rs:3:18
    |
 LL | static B: u8 = { yield 3u8; 3u8};
diff --git a/tests/ui/generator/yield-outside-generator-issue-78653.rs b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs
index 4e8050c81b0..31025c33b1a 100644
--- a/tests/ui/generator/yield-outside-generator-issue-78653.rs
+++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs
@@ -1,7 +1,7 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     yield || for i in 0 { }
-    //~^ ERROR yield expression outside of generator literal
+    //~^ ERROR yield expression outside of coroutine literal
     //~| ERROR `{integer}` is not an iterator
 }
diff --git a/tests/ui/generator/yield-outside-generator-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
index dcfb211744c..f28f8913508 100644
--- a/tests/ui/generator/yield-outside-generator-issue-78653.stderr
+++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
@@ -1,11 +1,11 @@
-error[E0627]: yield expression outside of generator literal
-  --> $DIR/yield-outside-generator-issue-78653.rs:4:5
+error[E0627]: yield expression outside of coroutine literal
+  --> $DIR/yield-outside-coroutine-issue-78653.rs:4:5
    |
 LL |     yield || for i in 0 { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `{integer}` is not an iterator
-  --> $DIR/yield-outside-generator-issue-78653.rs:4:23
+  --> $DIR/yield-outside-coroutine-issue-78653.rs:4:23
    |
 LL |     yield || for i in 0 { }
    |                       ^ `{integer}` is not an iterator
diff --git a/tests/ui/generator/yield-subtype.rs b/tests/ui/coroutine/yield-subtype.rs
index cb3fc909145..3595d449823 100644
--- a/tests/ui/generator/yield-subtype.rs
+++ b/tests/ui/coroutine/yield-subtype.rs
@@ -2,13 +2,13 @@
 #![allow(dead_code)]
 #![allow(dead_code)]
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn bar<'a>() {
     let a: &'static str = "hi";
     let b: &'a str = a;
 
-    || { //~ WARN unused generator that must be used
+    || { //~ WARN unused coroutine that must be used
         yield a;
         yield b;
     };
diff --git a/tests/ui/generator/yield-subtype.stderr b/tests/ui/coroutine/yield-subtype.stderr
index 97862e91cd4..5e7ae9f581e 100644
--- a/tests/ui/generator/yield-subtype.stderr
+++ b/tests/ui/coroutine/yield-subtype.stderr
@@ -1,4 +1,4 @@
-warning: unused generator that must be used
+warning: unused coroutine that must be used
   --> $DIR/yield-subtype.rs:11:5
    |
 LL | /     || {
@@ -7,7 +7,7 @@ LL | |         yield b;
 LL | |     };
    | |_____^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/generator/yield-while-iterating.rs b/tests/ui/coroutine/yield-while-iterating.rs
index 985e5d8bdc8..66ac6d3922a 100644
--- a/tests/ui/generator/yield-while-iterating.rs
+++ b/tests/ui/coroutine/yield-while-iterating.rs
@@ -1,11 +1,11 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{GeneratorState, Generator};
+use std::ops::{CoroutineState, Coroutine};
 use std::cell::Cell;
 use std::pin::Pin;
 
 fn yield_during_iter_owned_data(x: Vec<i32>) {
-    // The generator owns `x`, so we error out when yielding with a
+    // The coroutine owns `x`, so we error out when yielding with a
     // 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.
diff --git a/tests/ui/generator/yield-while-iterating.stderr b/tests/ui/coroutine/yield-while-iterating.stderr
index b6563475235..5330121f372 100644
--- a/tests/ui/generator/yield-while-iterating.stderr
+++ b/tests/ui/coroutine/yield-while-iterating.stderr
@@ -1,4 +1,4 @@
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-iterating.rs:13:18
    |
 LL |         for p in &x {
@@ -12,7 +12,7 @@ error[E0502]: cannot borrow `x` as immutable because it is also borrowed as muta
 LL |     let mut b = || {
    |                 -- mutable borrow occurs here
 LL |         for p in &mut x {
-   |                       - first borrow occurs due to use of `x` in generator
+   |                       - first borrow occurs due to use of `x` in coroutine
 ...
 LL |     println!("{}", x[0]);
    |                    ^ immutable borrow occurs here
diff --git a/tests/ui/generator/yield-while-local-borrowed.rs b/tests/ui/coroutine/yield-while-local-borrowed.rs
index 061a64dbc36..7f8d1d4543d 100644
--- a/tests/ui/generator/yield-while-local-borrowed.rs
+++ b/tests/ui/coroutine/yield-while-local-borrowed.rs
@@ -1,7 +1,7 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{GeneratorState, Generator};
 use std::cell::Cell;
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn borrow_local_inline() {
@@ -11,8 +11,8 @@ fn borrow_local_inline() {
     // `b` and gets extended by region inference.)
     let mut b = move || {
         let a = &mut 3;
-        //~^ ERROR borrow may still be in use when generator yields
-        yield();
+        //~^ ERROR borrow may still be in use when coroutine yields
+        yield ();
         println!("{}", a);
     };
     Pin::new(&mut b).resume(());
@@ -24,7 +24,7 @@ fn borrow_local_inline_done() {
         {
             let a = &mut 3;
         }
-        yield();
+        yield ();
     };
     Pin::new(&mut b).resume(());
 }
@@ -38,12 +38,12 @@ fn borrow_local() {
         let a = 3;
         {
             let b = &a;
-            //~^ ERROR borrow may still be in use when generator yields
-            yield();
+            //~^ ERROR borrow may still be in use when coroutine yields
+            yield ();
             println!("{}", b);
         }
     };
     Pin::new(&mut b).resume(());
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/generator/yield-while-local-borrowed.stderr b/tests/ui/coroutine/yield-while-local-borrowed.stderr
index c1513ef9b71..8fe981de929 100644
--- a/tests/ui/generator/yield-while-local-borrowed.stderr
+++ b/tests/ui/coroutine/yield-while-local-borrowed.stderr
@@ -1,20 +1,20 @@
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-local-borrowed.rs:13:17
    |
 LL |         let a = &mut 3;
    |                 ^^^^^^
 LL |
-LL |         yield();
-   |         ------- possible yield occurs here
+LL |         yield ();
+   |         -------- possible yield occurs here
 
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-local-borrowed.rs:40:21
    |
 LL |             let b = &a;
    |                     ^^
 LL |
-LL |             yield();
-   |             ------- possible yield occurs here
+LL |             yield ();
+   |             -------- possible yield occurs here
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generator/yield-while-ref-reborrowed.rs b/tests/ui/coroutine/yield-while-ref-reborrowed.rs
index a03ef945dd2..07c59175858 100644
--- a/tests/ui/generator/yield-while-ref-reborrowed.rs
+++ b/tests/ui/coroutine/yield-while-ref-reborrowed.rs
@@ -1,12 +1,12 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{GeneratorState, Generator};
+use std::ops::{CoroutineState, Coroutine};
 use std::cell::Cell;
 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 generator.
+    // data that outlives the coroutine.
     let mut b = move || {
         let a = &*x;
         yield();
@@ -17,7 +17,7 @@ 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 generator.
+    // data that outlives the coroutine.
     let mut b = move || {
         let a = &mut *x;
         yield();
diff --git a/tests/ui/generator/yield-while-ref-reborrowed.stderr b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr
index 47147f9c05d..e60a9531622 100644
--- a/tests/ui/generator/yield-while-ref-reborrowed.stderr
+++ b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr
@@ -2,9 +2,9 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u
   --> $DIR/yield-while-ref-reborrowed.rs:36:20
    |
 LL |     let mut b = || {
-   |                 -- generator construction occurs here
+   |                 -- coroutine construction occurs here
 LL |         let a = &mut *x;
-   |                      -- first borrow occurs due to use of `x` in generator
+   |                      -- first borrow occurs due to use of `x` in coroutine
 ...
 LL |     println!("{}", x);
    |                    ^ second borrow occurs here
diff --git a/tests/ui/generator/yielding-in-match-guards.rs b/tests/ui/coroutine/yielding-in-match-guards.rs
index 4e89fc975d0..a9575a9e77e 100644
--- a/tests/ui/generator/yielding-in-match-guards.rs
+++ b/tests/ui/coroutine/yielding-in-match-guards.rs
@@ -8,7 +8,7 @@
 // indeed a temporary borrow `y` from `x` is live
 // while `f().await` is being evaluated.
 // Thus, `&'_ u8` should be included in type signature
-// of the underlying generator.
+// of the underlying coroutine.
 
 #![feature(if_let_guard)]
 
diff --git a/tests/ui/drop/dynamic-drop.rs b/tests/ui/drop/dynamic-drop.rs
index caef6358ea7..5bf2cc30e7f 100644
--- a/tests/ui/drop/dynamic-drop.rs
+++ b/tests/ui/drop/dynamic-drop.rs
@@ -1,7 +1,7 @@
 // run-pass
 // needs-unwind
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![feature(if_let_guard)]
 
 #![allow(unused_assignments)]
@@ -9,7 +9,7 @@
 
 use std::cell::{Cell, RefCell};
 use std::mem::ManuallyDrop;
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::panic;
 use std::pin::Pin;
 
@@ -173,7 +173,7 @@ fn vec_simple(a: &Allocator) {
     let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()];
 }
 
-fn generator(a: &Allocator, run_count: usize) {
+fn coroutine(a: &Allocator, run_count: usize) {
     assert!(run_count < 4);
 
     let mut gen = || {
@@ -471,10 +471,10 @@ fn main() {
     run_test(|a| field_assignment(a, false));
     run_test(|a| field_assignment(a, true));
 
-    run_test(|a| generator(a, 0));
-    run_test(|a| generator(a, 1));
-    run_test(|a| generator(a, 2));
-    run_test(|a| generator(a, 3));
+    run_test(|a| coroutine(a, 0));
+    run_test(|a| coroutine(a, 1));
+    run_test(|a| coroutine(a, 2));
+    run_test(|a| coroutine(a, 3));
 
     run_test(|a| mixed_drop_and_nondrop(a));
 
diff --git a/tests/ui/error-codes/E0283.rs b/tests/ui/error-codes/E0283.rs
index 0643af4b7e8..5134660e3f4 100644
--- a/tests/ui/error-codes/E0283.rs
+++ b/tests/ui/error-codes/E0283.rs
@@ -1,10 +1,10 @@
-trait Generator {
+trait Coroutine {
     fn create() -> u32;
 }
 
 struct Impl;
 
-impl Generator for Impl {
+impl Coroutine for Impl {
     fn create() -> u32 { 1 }
 }
 
@@ -22,12 +22,12 @@ fn foo(bar: u32) {}
 
 struct AnotherImpl;
 
-impl Generator for AnotherImpl {
+impl Coroutine for AnotherImpl {
     fn create() -> u32 { 2 }
 }
 
 fn main() {
-    let cont: u32 = Generator::create(); //~ ERROR E0790
+    let cont: u32 = Coroutine::create(); //~ ERROR E0790
 }
 
 fn buzz() {
diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr
index fa8d4b6e015..6008809f050 100644
--- a/tests/ui/error-codes/E0283.stderr
+++ b/tests/ui/error-codes/E0283.stderr
@@ -2,14 +2,14 @@ error[E0790]: cannot call associated function on trait without specifying the co
   --> $DIR/E0283.rs:30:21
    |
 LL |     fn create() -> u32;
-   |     ------------------- `Generator::create` defined here
+   |     ------------------- `Coroutine::create` defined here
 ...
-LL |     let cont: u32 = Generator::create();
+LL |     let cont: u32 = Coroutine::create();
    |                     ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
    |
 help: use a fully-qualified path to a specific available implementation
    |
-LL |     let cont: u32 = </* self type */ as Generator>::create();
+LL |     let cont: u32 = </* self type */ as Coroutine>::create();
    |                     +++++++++++++++++++          +
 
 error[E0283]: type annotations needed
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 a4c91f3bc18..58a9c84be5a 100644
--- a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs
+++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs
@@ -1,9 +1,9 @@
 // edition:2021
 #![feature(stmt_expr_attributes)]
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
     let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures
-    let _generator = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures
+    let _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 cf2ea5fe1ca..d5ef5d09ed4 100644
--- a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr
+++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr
@@ -10,7 +10,7 @@ LL |     let _closure = #[track_caller] || {};
 error[E0658]: `#[track_caller]` on closures is currently unstable
   --> $DIR/feature-gate-closure_track_caller.rs:7:22
    |
-LL |     let _generator = #[track_caller] || { yield; };
+LL |     let _coroutine = #[track_caller] || { yield; };
    |                      ^^^^^^^^^^^^^^^
    |
    = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
diff --git a/tests/ui/feature-gates/feature-gate-generators.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs
index 931fee13471..c3c5aec8824 100644
--- a/tests/ui/feature-gates/feature-gate-generators.rs
+++ b/tests/ui/feature-gates/feature-gate-coroutines.rs
@@ -1,6 +1,6 @@
 fn main() {
     yield true; //~ ERROR yield syntax is experimental
-                //~^ ERROR yield expression outside of generator literal
+                //~^ ERROR yield expression outside of coroutine literal
 }
 
 #[cfg(FALSE)]
diff --git a/tests/ui/feature-gates/feature-gate-generators.stderr b/tests/ui/feature-gates/feature-gate-coroutines.stderr
index dfea178a637..dd561643901 100644
--- a/tests/ui/feature-gates/feature-gate-generators.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.stderr
@@ -1,32 +1,32 @@
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-generators.rs:2:5
+  --> $DIR/feature-gate-coroutines.rs:2:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(generators)]` to the crate attributes to enable
+   = help: add `#![feature(coroutines)]` to the crate attributes to enable
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-generators.rs:8:5
+  --> $DIR/feature-gate-coroutines.rs:8:5
    |
 LL |     yield;
    |     ^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(generators)]` to the crate attributes to enable
+   = help: add `#![feature(coroutines)]` to the crate attributes to enable
 
 error[E0658]: yield syntax is experimental
-  --> $DIR/feature-gate-generators.rs:9:5
+  --> $DIR/feature-gate-coroutines.rs:9:5
    |
 LL |     yield 0;
    |     ^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(generators)]` to the crate attributes to enable
+   = help: add `#![feature(coroutines)]` to the crate attributes to enable
 
-error[E0627]: yield expression outside of generator literal
-  --> $DIR/feature-gate-generators.rs:2:5
+error[E0627]: yield expression outside of coroutine literal
+  --> $DIR/feature-gate-coroutines.rs:2:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs
index 9b646060adf..1922bfb4913 100644
--- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs
+++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs
@@ -3,13 +3,17 @@
 #![deny(non_exhaustive_omitted_patterns)]
 //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns`
 //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+//~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
 #![allow(non_exhaustive_omitted_patterns)]
 //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns`
 //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+//~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
 
 fn main() {
     enum Foo {
-        A, B, C,
+        A,
+        B,
+        C,
     }
 
     #[allow(non_exhaustive_omitted_patterns)]
@@ -17,18 +21,22 @@ fn main() {
     //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
     //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
     //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
     match Foo::A {
+        //~^ ERROR non-exhaustive patterns: `Foo::C` not covered
         Foo::A => {}
         Foo::B => {}
     }
-    //~^^^^ ERROR non-exhaustive patterns: `Foo::C` not covered
 
+    #[warn(non_exhaustive_omitted_patterns)]
+    //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns`
+    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
+    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
     match Foo::A {
         Foo::A => {}
         Foo::B => {}
-        #[warn(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^^ WARNING unknown lint: `non_exhaustive_omitted_patterns`
-    //~| WARNING unknown lint: `non_exhaustive_omitted_patterns`
 }
diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
index 1c14622d637..eb61c4cf159 100644
--- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
+++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
@@ -10,7 +10,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)]
    = note: `#[warn(unknown_lints)]` on by default
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1
    |
 LL | #![allow(non_exhaustive_omitted_patterns)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)]
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5
    |
 LL |     #[allow(non_exhaustive_omitted_patterns)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5
    |
 LL |     #[allow(non_exhaustive_omitted_patterns)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,16 +41,27 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5
    |
-LL |         #[warn(non_exhaustive_omitted_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1
    |
 LL | #![deny(non_exhaustive_omitted_patterns)]
@@ -62,7 +73,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1
    |
 LL | #![allow(non_exhaustive_omitted_patterns)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -73,7 +84,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5
    |
 LL |     #[allow(non_exhaustive_omitted_patterns)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,7 +95,7 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5
    |
 LL |     #[allow(non_exhaustive_omitted_patterns)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,10 +106,21 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5
    |
-LL |         #[warn(non_exhaustive_omitted_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
@@ -106,18 +128,19 @@ LL |         #[warn(non_exhaustive_omitted_patterns)]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0004]: non-exhaustive patterns: `Foo::C` not covered
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:25:11
    |
 LL |     match Foo::A {
    |           ^^^^^^ pattern `Foo::C` not covered
    |
 note: `Foo` defined here
-  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:12:15
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:16:9
    |
 LL |     enum Foo {
    |          ---
-LL |         A, B, C,
-   |               ^ not covered
+...
+LL |         C,
+   |         ^ not covered
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -125,6 +148,50 @@ LL ~         Foo::B => {},
 LL +         Foo::C => todo!()
    |
 
-error: aborting due to previous error; 10 warnings emitted
+warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1
+   |
+LL | #![deny(non_exhaustive_omitted_patterns)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1
+   |
+LL | #![allow(non_exhaustive_omitted_patterns)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:19:5
+   |
+LL |     #[allow(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unknown lint: `non_exhaustive_omitted_patterns`
+  --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:31:5
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `non_exhaustive_omitted_patterns` lint is unstable
+   = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
+   = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to previous error; 16 warnings emitted
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/generator/async-generator-issue-67158.rs b/tests/ui/generator/async-generator-issue-67158.rs
deleted file mode 100644
index 8125a7a9bb6..00000000000
--- a/tests/ui/generator/async-generator-issue-67158.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(generators)]
-// edition:2018
-// Regression test for #67158.
-fn main() {
-    async { yield print!(":C") }; //~ ERROR `async` generators are not yet supported
-}
diff --git a/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs b/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs
deleted file mode 100644
index 207c2735f88..00000000000
--- a/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// compile-flags: --emit metadata
-#![feature(generators, generator_trait)]
-
-use std::marker::Unpin;
-use std::ops::Generator;
-
-pub fn g() -> impl Generator<(), Yield = (), Return = ()> {
-    || {
-        yield;
-    }
-}
diff --git a/tests/ui/generator/auxiliary/xcrate-reachable.rs b/tests/ui/generator/auxiliary/xcrate-reachable.rs
deleted file mode 100644
index 2dd5ea67523..00000000000
--- a/tests/ui/generator/auxiliary/xcrate-reachable.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-
-fn msg() -> u32 {
-    0
-}
-
-pub fn foo() -> impl Generator<(), Yield=(), Return=u32> {
-    || {
-        yield;
-        return msg();
-    }
-}
diff --git a/tests/ui/generator/auxiliary/xcrate.rs b/tests/ui/generator/auxiliary/xcrate.rs
deleted file mode 100644
index d07abd0918c..00000000000
--- a/tests/ui/generator/auxiliary/xcrate.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#![feature(generators, generator_trait)]
-
-use std::marker::Unpin;
-use std::ops::Generator;
-
-pub fn foo() -> impl Generator<(), Yield = (), Return = ()> {
-    || {
-        if false {
-            yield;
-        }
-    }
-}
-
-pub fn bar<T: 'static>(t: T) -> Box<Generator<(), Yield = T, Return = ()> + Unpin> {
-    Box::new(|| {
-        yield t;
-    })
-}
diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.rs b/tests/ui/generator/generator-yielding-or-returning-itself.rs
deleted file mode 100644
index 30788e3c186..00000000000
--- a/tests/ui/generator/generator-yielding-or-returning-itself.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-#![feature(generator_trait)]
-#![feature(generators)]
-
-// Test that we cannot create a generator that returns a value of its
-// own type.
-
-use std::ops::Generator;
-
-pub fn want_cyclic_generator_return<T>(_: T)
-    where T: Generator<Yield = (), Return = T>
-{
-}
-
-fn supply_cyclic_generator_return() {
-    want_cyclic_generator_return(|| {
-        //~^ ERROR type mismatch
-        if false { yield None.unwrap(); }
-        None.unwrap()
-    })
-}
-
-pub fn want_cyclic_generator_yield<T>(_: T)
-    where T: Generator<Yield = T, Return = ()>
-{
-}
-
-fn supply_cyclic_generator_yield() {
-    want_cyclic_generator_yield(|| {
-        //~^ ERROR type mismatch
-        if false { yield None.unwrap(); }
-        None.unwrap()
-    })
-}
-
-fn main() { }
diff --git a/tests/ui/generator/issue-52304.rs b/tests/ui/generator/issue-52304.rs
deleted file mode 100644
index 3e9de765b12..00000000000
--- a/tests/ui/generator/issue-52304.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-
-pub fn example() -> impl Generator {
-    || yield &1
-}
-
-fn main() {}
diff --git a/tests/ui/generator/issue-64620-yield-array-element.rs b/tests/ui/generator/issue-64620-yield-array-element.rs
deleted file mode 100644
index 2cbe8f51614..00000000000
--- a/tests/ui/generator/issue-64620-yield-array-element.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Regression test for #64620
-
-#![feature(generators)]
-
-pub fn crash(arr: [usize; 1]) {
-    yield arr[0]; //~ ERROR: yield expression outside of generator literal
-}
-
-fn main() {}
diff --git a/tests/ui/generator/issue-87142.rs b/tests/ui/generator/issue-87142.rs
deleted file mode 100644
index 7f670919ed6..00000000000
--- a/tests/ui/generator/issue-87142.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: -Cdebuginfo=2
-// build-pass
-
-// Regression test for #87142
-// This test needs the above flags and the "lib" crate type.
-
-#![feature(impl_trait_in_assoc_type, generator_trait, generators)]
-#![crate_type = "lib"]
-
-use std::ops::Generator;
-
-pub trait GeneratorProviderAlt: Sized {
-    type Gen: Generator<(), Return = (), Yield = ()>;
-
-    fn start(ctx: Context<Self>) -> Self::Gen;
-}
-
-pub struct Context<G: 'static + GeneratorProviderAlt> {
-    pub link: Box<G::Gen>,
-}
-
-impl GeneratorProviderAlt for () {
-    type Gen = impl Generator<(), Return = (), Yield = ()>;
-    fn start(ctx: Context<Self>) -> Self::Gen {
-        move || {
-            match ctx {
-                _ => (),
-            }
-            yield ();
-        }
-    }
-}
diff --git a/tests/ui/generator/nested_generators.rs b/tests/ui/generator/nested_generators.rs
deleted file mode 100644
index 45519150eec..00000000000
--- a/tests/ui/generator/nested_generators.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-
-#![feature(generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
-    let _generator = || {
-        let mut sub_generator = || {
-            yield 2;
-        };
-
-        match Pin::new(&mut sub_generator).resume(()) {
-            GeneratorState::Yielded(x) => {
-                yield x;
-            }
-            _ => panic!(),
-        };
-    };
-}
diff --git a/tests/ui/generator/pin-box-generator.rs b/tests/ui/generator/pin-box-generator.rs
deleted file mode 100644
index c3136f5c0ec..00000000000
--- a/tests/ui/generator/pin-box-generator.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-
-fn assert_generator<G: Generator>(_: G) {
-}
-
-fn main() {
-    assert_generator(static || yield);
-    assert_generator(Box::pin(static || yield));
-}
diff --git a/tests/ui/generator/sized-yield.rs b/tests/ui/generator/sized-yield.rs
deleted file mode 100644
index c6dd738d6ac..00000000000
--- a/tests/ui/generator/sized-yield.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-use std::pin::Pin;
-
-fn main() {
-   let s = String::from("foo");
-   let mut gen = move || {
-   //~^ ERROR the size for values of type
-       yield s[..];
-   };
-   Pin::new(&mut gen).resume(());
-   //~^ ERROR the size for values of type
-}
diff --git a/tests/ui/generator/sized-yield.stderr b/tests/ui/generator/sized-yield.stderr
deleted file mode 100644
index fb34540d969..00000000000
--- a/tests/ui/generator/sized-yield.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/sized-yield.rs:8:26
-   |
-LL |      let mut gen = move || {
-   |  __________________________^
-LL | |
-LL | |        yield s[..];
-LL | |    };
-   | |____^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-   = note: the yield type of a generator 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:23
-   |
-LL |    Pin::new(&mut gen).resume(());
-   |                       ^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-note: required by a bound in `GeneratorState`
-  --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/static-generators.rs b/tests/ui/generator/static-generators.rs
deleted file mode 100644
index d098bf1e688..00000000000
--- a/tests/ui/generator/static-generators.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![feature(generators, generator_trait)]
-
-use std::pin::Pin;
-use std::ops::{Generator, GeneratorState};
-
-fn main() {
-    let mut generator = static || {
-        let a = true;
-        let b = &a;
-        yield;
-        assert_eq!(b as *const _, &a as *const _);
-    };
-    // SAFETY: We shadow the original generator variable so have no safe API to
-    // move it after this point.
-    let mut generator = unsafe { Pin::new_unchecked(&mut generator) };
-    assert_eq!(generator.as_mut().resume(()), GeneratorState::Yielded(()));
-    assert_eq!(generator.as_mut().resume(()), GeneratorState::Complete(()));
-}
diff --git a/tests/ui/generator/too-many-parameters.rs b/tests/ui/generator/too-many-parameters.rs
deleted file mode 100644
index 7a353ea298b..00000000000
--- a/tests/ui/generator/too-many-parameters.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(generators)]
-
-fn main() {
-    |(), ()| {
-        //~^ error: too many parameters for a generator
-        yield;
-    };
-}
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.rs b/tests/ui/generic-associated-types/bugs/issue-100013.rs
index 973c548d785..b13b730d5d8 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.rs
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.rs
@@ -3,7 +3,7 @@
 // edition: 2021
 
 // We really should accept this, but we need implied bounds between the regions
-// in a generator interior.
+// in a coroutine interior.
 
 pub trait FutureIterator {
     type Future<'s, 'cx>: Send
@@ -12,21 +12,21 @@ pub trait FutureIterator {
 }
 
 fn call<I: FutureIterator>() -> impl Send {
-    async { // a generator checked for autotrait impl `Send`
+    async { // a coroutine checked for autotrait impl `Send`
         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
         async {}.await; // a yield point
     }
 }
 
 fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
-    async { // a generator checked for autotrait impl `Send`
+    async { // a coroutine checked for autotrait impl `Send`
         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
         async {}.await; // a yield point
     }
 }
 
 fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
-    async { // a generator checked for autotrait impl `Send`
+    async { // a coroutine checked for autotrait impl `Send`
         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
         async {}.await; // a yield point
     }
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
index 93c69422f00..ff82aebfef9 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
@@ -1,7 +1,7 @@
 error: lifetime bound not satisfied
   --> $DIR/issue-100013.rs:15:5
    |
-LL | /     async { // a generator checked for autotrait impl `Send`
+LL | /     async { // a coroutine checked for autotrait impl `Send`
 LL | |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
 LL | |         async {}.await; // a yield point
 LL | |     }
@@ -12,7 +12,7 @@ LL | |     }
 error: lifetime bound not satisfied
   --> $DIR/issue-100013.rs:22:5
    |
-LL | /     async { // a generator checked for autotrait impl `Send`
+LL | /     async { // a coroutine checked for autotrait impl `Send`
 LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
 LL | |         async {}.await; // a yield point
 LL | |     }
@@ -27,7 +27,7 @@ LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
    |          --  -- lifetime `'b` defined here
    |          |
    |          lifetime `'a` defined here
-LL |     async { // a generator checked for autotrait impl `Send`
+LL |     async { // a coroutine checked for autotrait impl `Send`
 LL |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
    |
@@ -36,7 +36,7 @@ LL |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
 error: lifetime bound not satisfied
   --> $DIR/issue-100013.rs:29:5
    |
-LL | /     async { // a generator checked for autotrait impl `Send`
+LL | /     async { // a coroutine checked for autotrait impl `Send`
 LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
 LL | |         async {}.await; // a yield point
 LL | |     }
diff --git a/tests/ui/impl-trait/bounds_regression.rs b/tests/ui/impl-trait/bounds_regression.rs
index 31fc46203d3..f32d83c0c40 100644
--- a/tests/ui/impl-trait/bounds_regression.rs
+++ b/tests/ui/impl-trait/bounds_regression.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-pub trait FakeGenerator {
+pub trait FakeCoroutine {
     type Yield;
     type Return;
 }
@@ -9,15 +9,15 @@ pub trait FakeFuture {
     type Output;
 }
 
-pub fn future_from_generator<
-    T: FakeGenerator<Yield = ()>
+pub fn future_from_coroutine<
+    T: FakeCoroutine<Yield = ()>
 >(x: T) -> impl FakeFuture<Output = T::Return> {
     GenFuture(x)
 }
 
-struct GenFuture<T: FakeGenerator<Yield = ()>>(#[allow(unused_tuple_struct_fields)] T);
+struct GenFuture<T: FakeCoroutine<Yield = ()>>(#[allow(unused_tuple_struct_fields)] T);
 
-impl<T: FakeGenerator<Yield = ()>> FakeFuture for GenFuture<T> {
+impl<T: FakeCoroutine<Yield = ()>> FakeFuture for GenFuture<T> {
     type Output = T::Return;
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs
index f1d7b94ef2d..03b51ae92d1 100644
--- a/tests/ui/impl-trait/issues/issue-58504.rs
+++ b/tests/ui/impl-trait/issues/issue-58504.rs
@@ -1,12 +1,12 @@
-#![feature(generators, generator_trait, never_type)]
+#![feature(coroutines, coroutine_trait, never_type)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn mk_gen() -> impl Generator<Return=!, Yield=()> {
+fn mk_gen() -> impl Coroutine<Return=!, Yield=()> {
     || { loop { yield; } }
 }
 
 fn main() {
-    let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+    let gens: [impl Coroutine<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
     //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr
index 1be676ee075..49376f559cf 100644
--- a/tests/ui/impl-trait/issues/issue-58504.stderr
+++ b/tests/ui/impl-trait/issues/issue-58504.stderr
@@ -1,7 +1,7 @@
 error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-58504.rs:10:16
    |
-LL |     let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
+LL |     let gens: [impl Coroutine<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/tests/ui/impl-trait/lifetimes.rs b/tests/ui/impl-trait/lifetimes.rs
index 9a9843375e4..f853117a9c6 100644
--- a/tests/ui/impl-trait/lifetimes.rs
+++ b/tests/ui/impl-trait/lifetimes.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![allow(warnings)]
-#![feature(generators)]
+#![feature(coroutines)]
 
 use std::fmt::Debug;
 
@@ -114,7 +114,7 @@ impl<'unnecessary_lifetime> MyVec {
         self.0.iter().flat_map(|inner_vec| inner_vec.iter())
     }
 
-    fn generator_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized {
+    fn coroutine_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized {
         || yield
     }
 }
diff --git a/tests/ui/impl-trait/recursive-generator.rs b/tests/ui/impl-trait/recursive-coroutine.rs
index 000af70c454..6351cef95a6 100644
--- a/tests/ui/impl-trait/recursive-generator.rs
+++ b/tests/ui/impl-trait/recursive-coroutine.rs
@@ -1,16 +1,16 @@
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 
-fn foo() -> impl Generator<Yield = (), Return = ()> {
+fn foo() -> impl Coroutine<Yield = (), Return = ()> {
     //~^ ERROR cannot resolve opaque type
     //~| NOTE recursive opaque type
     //~| NOTE in this expansion of desugaring of
     || {
         let mut gen = Box::pin(foo());
-        //~^ NOTE generator captures itself here
+        //~^ NOTE coroutine captures itself here
         let mut r = gen.as_mut().resume(());
-        while let GeneratorState::Yielded(v) = r {
+        while let CoroutineState::Yielded(v) = r {
             yield v;
             r = gen.as_mut().resume(());
         }
diff --git a/tests/ui/impl-trait/recursive-generator.stderr b/tests/ui/impl-trait/recursive-coroutine.stderr
index 86e193d9599..d36a58a8643 100644
--- a/tests/ui/impl-trait/recursive-generator.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine.stderr
@@ -1,11 +1,11 @@
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-generator.rs:5:13
+  --> $DIR/recursive-coroutine.rs:5:13
    |
-LL | fn foo() -> impl Generator<Yield = (), Return = ()> {
+LL | fn foo() -> impl Coroutine<Yield = (), Return = ()> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
 ...
 LL |         let mut gen = Box::pin(foo());
-   |             ------- generator captures itself here
+   |             ------- coroutine captures itself here
 
 error: aborting due to previous error
 
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 ffc0cd9d10c..8331eec906e 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -1,7 +1,7 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden.
 
-#![feature(generators)]
+#![feature(coroutines)]
 #![allow(unconditional_recursion)]
 
 fn option(i: i32) -> impl Sized {
@@ -50,14 +50,14 @@ fn closure_sig() -> impl Sized {
     || closure_sig()
 }
 
-fn generator_sig() -> impl Sized {
+fn coroutine_sig() -> impl Sized {
     //~^ ERROR
-    || generator_sig()
+    || coroutine_sig()
 }
 
-fn generator_capture() -> impl Sized {
+fn coroutine_capture() -> impl Sized {
     //~^ ERROR
-    let x = generator_capture();
+    let x = coroutine_capture();
     move || {
         yield;
         x;
@@ -69,10 +69,10 @@ fn substs_change<T: 'static>() -> impl Sized {
     (substs_change::<&T>(),)
 }
 
-fn generator_hold() -> impl Sized {
+fn coroutine_hold() -> impl Sized {
     //~^ ERROR
     move || {
-        let x = generator_hold();
+        let x = coroutine_hold();
         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 1d919fb5240..8e9aa8ad0a6 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -81,24 +81,24 @@ LL |     || closure_sig()
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
    |
-LL | fn generator_sig() -> impl Sized {
+LL | fn coroutine_sig() -> impl Sized {
    |                       ^^^^^^^^^^ recursive opaque type
 LL |
-LL |     || generator_sig()
+LL |     || coroutine_sig()
    |     ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7}`
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
    |
-LL |   fn generator_capture() -> impl Sized {
+LL |   fn coroutine_capture() -> impl Sized {
    |                             ^^^^^^^^^^ recursive opaque type
 ...
 LL | /     move || {
 LL | |         yield;
 LL | |         x;
-   | |         - generator captures itself here
+   | |         - coroutine captures itself here
 LL | |     }
-   | |_____- returning here with type `{generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12}`
+   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12}`
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
@@ -112,11 +112,11 @@ LL |     (substs_change::<&T>(),)
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
    |
-LL | fn generator_hold() -> impl Sized {
+LL | fn coroutine_hold() -> impl Sized {
    |                        ^^^^^^^^^^ recursive opaque type
 ...
-LL |         let x = generator_hold();
-   |             - generator captures itself here
+LL |         let x = coroutine_hold();
+   |             - coroutine captures itself here
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
diff --git a/tests/ui/invalid/invalid-llvm-passes.rs b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs
index ee28f5eb6d6..ee28f5eb6d6 100644
--- a/tests/ui/invalid/invalid-llvm-passes.rs
+++ b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs
diff --git a/tests/ui/invalid/invalid-llvm-passes.stderr b/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr
index ae1f85e41e4..ae1f85e41e4 100644
--- a/tests/ui/invalid/invalid-llvm-passes.stderr
+++ b/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr
diff --git a/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
index f02a93ed41b..80aba0ba04d 100644
--- a/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
@@ -1,8 +1,8 @@
 // check-pass
 
-#![feature(generator_trait, negative_impls)]
+#![feature(coroutine_trait, negative_impls)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::task::{Poll, Context};
 use std::future::{Future};
 use std::ptr::NonNull;
@@ -17,27 +17,27 @@ unsafe impl Send for ResumeTy {}
 
 unsafe impl Sync for ResumeTy {}
 
-pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+pub const fn from_coroutine<T>(gen: T) -> impl Future<Output = T::Return>
 where
-    T: Generator<ResumeTy, Yield = ()>,
+    T: Coroutine<ResumeTy, Yield = ()>,
 {
-    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
+    struct GenFuture<T: Coroutine<ResumeTy, Yield = ()>>(T);
 
     // We rely on the fact that async/await futures are immovable in order to create
-    // self-referential borrows in the underlying generator.
-    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
+    // self-referential borrows in the underlying coroutine.
+    impl<T: Coroutine<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
 
-    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
+    impl<T: Coroutine<ResumeTy, Yield = ()>> Future for GenFuture<T> {
         type Output = T::Return;
         fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
             // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
             let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
 
-            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
+            // Resume the coroutine, turning the `&mut Context` into a `NonNull` raw pointer. The
             // `.await` lowering will safely cast that back to a `&mut Context`.
             match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
-                GeneratorState::Yielded(()) => Poll::Pending,
-                GeneratorState::Complete(x) => Poll::Ready(x),
+                CoroutineState::Yielded(()) => Poll::Pending,
+                CoroutineState::Complete(x) => Poll::Ready(x),
             }
         }
     }
diff --git a/tests/ui/lifetimes/borrowck-let-suggestion.stderr b/tests/ui/lifetimes/borrowck-let-suggestion.stderr
index da0078698ae..62119664764 100644
--- a/tests/ui/lifetimes/borrowck-let-suggestion.stderr
+++ b/tests/ui/lifetimes/borrowck-let-suggestion.stderr
@@ -10,6 +10,10 @@ LL |     x.use_mut();
    |     - borrow later used here
    |
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider consuming the `Vec<i32>` when turning it into an `Iterator`
+   |
+LL |     let mut x = vec![1].into_iter();
+   |                         ~~~~~~~~~
 help: consider using a `let` binding to create a longer lived value
    |
 LL ~     let binding = vec![1];
diff --git a/tests/ui/lifetimes/issue-77175.rs b/tests/ui/lifetimes/issue-77175.rs
index 2282752b6c1..8072691ae3c 100644
--- a/tests/ui/lifetimes/issue-77175.rs
+++ b/tests/ui/lifetimes/issue-77175.rs
@@ -5,7 +5,7 @@
 // Prior to the fix, the compiler complained that the 'a lifetime was only used
 // once. This was obviously wrong since the lifetime is used twice: For the s3
 // parameter and the return type. The issue was caused by the compiler
-// desugaring the async function into a generator that uses only a single
+// desugaring the async function into a coroutine that uses only a single
 // lifetime, which then the validator complained about becauase of the
 // single_use_lifetimes constraints.
 async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str {
diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
index c7e14e42561..2f3c5d9ea29 100644
--- a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
+++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs
@@ -1,7 +1,7 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn main() {
-    let _generator = || {
+    let _coroutine = || {
         yield ((), ((), ()));
         yield ((), ());
         //~^ ERROR mismatched types
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 8064c3a88d1..c5dd281cb4e 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,8 +1,8 @@
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 #![deny(unused_braces, unused_parens)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs
index c96c907318c..12ee8b3a9bb 100644
--- a/tests/ui/lint/unused/unused-closure.rs
+++ b/tests/ui/lint/unused/unused-closure.rs
@@ -1,8 +1,8 @@
-// Test that closures and generators are "must use" types.
+// Test that closures and coroutines are "must use" types.
 // edition:2018
 
 #![feature(async_closure)]
-#![feature(generators)]
+#![feature(coroutines)]
 #![deny(unused_must_use)]
 
 fn unused() {
diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs
index d446d57d396..17158dfbc6c 100644
--- a/tests/ui/liveness/liveness-upvars.rs
+++ b/tests/ui/liveness/liveness-upvars.rs
@@ -1,6 +1,6 @@
 // edition:2018
 // check-pass
-#![feature(generators)]
+#![feature(coroutines)]
 #![warn(unused)]
 #![allow(unreachable_code)]
 
@@ -60,7 +60,7 @@ pub fn f() {
     };
     let _ = async move {
         println!("{}", c);
-        // Never read because this is a generator.
+        // Never read because this is a coroutine.
         c += 1; //~  WARN value assigned to `c` is never read
     };
 }
@@ -110,7 +110,7 @@ async fn yield_now() {
     todo!();
 }
 
-pub fn async_generator() {
+pub fn async_coroutine() {
     let mut state: u32 = 0;
 
     let _ = async {
@@ -129,7 +129,7 @@ pub fn async_generator() {
     };
 }
 
-pub fn generator() {
+pub fn coroutine() {
     let mut s: u32 = 0;
     let _ = |_| {
         s = 0;
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 8b4e6250a30..1e9e7a89dde 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -7,7 +7,7 @@
 #![feature(box_patterns)]
 #![feature(const_trait_impl)]
 #![feature(decl_macro)]
-#![feature(generators)]
+#![feature(coroutines)]
 #![feature(more_qualified_paths)]
 #![feature(raw_ref_op)]
 #![feature(trait_alias)]
diff --git a/tests/ui/mir/issue-71793-inline-args-storage.rs b/tests/ui/mir/issue-71793-inline-args-storage.rs
index 18f2e38d14c..3749d5ebf81 100644
--- a/tests/ui/mir/issue-71793-inline-args-storage.rs
+++ b/tests/ui/mir/issue-71793-inline-args-storage.rs
@@ -1,5 +1,5 @@
 // Verifies that inliner emits StorageLive & StorageDead when introducing
-// temporaries for arguments, so that they don't become part of the generator.
+// temporaries for arguments, so that they don't become part of the coroutine.
 // Regression test for #71793.
 //
 // check-pass
diff --git a/tests/ui/mir/remove-zsts-query-cycle.rs b/tests/ui/mir/remove-zsts-query-cycle.rs
index be4d68f2de7..bcaf8468857 100644
--- a/tests/ui/mir/remove-zsts-query-cycle.rs
+++ b/tests/ui/mir/remove-zsts-query-cycle.rs
@@ -1,5 +1,5 @@
 // Regression test for #88972. Used to cause a query cycle:
-//   optimized mir -> remove zsts -> layout of a generator -> optimized mir.
+//   optimized mir -> remove zsts -> layout of a coroutine -> optimized mir.
 //
 // edition:2018
 // compile-flags: --crate-type=lib -Zinline-mir=yes
diff --git a/tests/ui/nll/generator-distinct-lifetime.rs b/tests/ui/nll/coroutine-distinct-lifetime.rs
index 90fe6b56960..0483b8858ba 100644
--- a/tests/ui/nll/generator-distinct-lifetime.rs
+++ b/tests/ui/nll/coroutine-distinct-lifetime.rs
@@ -1,7 +1,7 @@
-#![feature(generators)]
+#![feature(coroutines)]
 
 // Test for issue #47189. Here, both `s` and `t` are live for the
-// generator's lifetime, but within the generator they have distinct
+// coroutine's lifetime, but within the coroutine they have distinct
 // lifetimes. We accept this code -- even though the borrow extends
 // over a yield -- because the data that is borrowed (`*x`) is not
 // stored on the stack.
diff --git a/tests/ui/nll/generator-upvar-mutability.rs b/tests/ui/nll/coroutine-upvar-mutability.rs
index c49ea15b824..12853b16b9b 100644
--- a/tests/ui/nll/generator-upvar-mutability.rs
+++ b/tests/ui/nll/coroutine-upvar-mutability.rs
@@ -1,6 +1,6 @@
-// Check that generators respect the muatability of their upvars.
+// Check that coroutines respect the muatability of their upvars.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn mutate_upvar() {
     let x = 0;
diff --git a/tests/ui/nll/generator-upvar-mutability.stderr b/tests/ui/nll/coroutine-upvar-mutability.stderr
index 31b061b61d1..464bbc76931 100644
--- a/tests/ui/nll/generator-upvar-mutability.stderr
+++ b/tests/ui/nll/coroutine-upvar-mutability.stderr
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/generator-upvar-mutability.rs:8:9
+  --> $DIR/coroutine-upvar-mutability.rs:8:9
    |
 LL |     let x = 0;
    |         - help: consider changing this to be mutable: `mut x`
diff --git a/tests/ui/nll/extra-unused-mut.rs b/tests/ui/nll/extra-unused-mut.rs
index 340f2952acc..b04e3954249 100644
--- a/tests/ui/nll/extra-unused-mut.rs
+++ b/tests/ui/nll/extra-unused-mut.rs
@@ -2,7 +2,7 @@
 
 // check-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 #![deny(unused_mut)]
 
 fn ref_argument(ref _y: i32) {}
@@ -16,7 +16,7 @@ fn mutable_upvar() {
 }
 
 // #50897
-fn generator_mutable_upvar() {
+fn coroutine_mutable_upvar() {
     let mut x = 0;
     move || {
         x = 1;
diff --git a/tests/ui/nll/issue-48623-generator.rs b/tests/ui/nll/issue-48623-coroutine.rs
index 08d2584ee5e..bd11aaf1429 100644
--- a/tests/ui/nll/issue-48623-generator.rs
+++ b/tests/ui/nll/issue-48623-coroutine.rs
@@ -2,7 +2,7 @@
 #![allow(path_statements)]
 #![allow(dead_code)]
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 struct WithDrop;
 
@@ -10,9 +10,9 @@ impl Drop for WithDrop {
     fn drop(&mut self) {}
 }
 
-fn reborrow_from_generator(r: &mut ()) {
+fn reborrow_from_coroutine(r: &mut ()) {
     let d = WithDrop;
-    move || { d; yield; &mut *r }; //~ WARN unused generator that must be used
+    move || { d; yield; &mut *r }; //~ WARN unused coroutine that must be used
 }
 
 fn main() {}
diff --git a/tests/ui/nll/issue-48623-generator.stderr b/tests/ui/nll/issue-48623-coroutine.stderr
index bfdfca21004..1b7b1735aac 100644
--- a/tests/ui/nll/issue-48623-generator.stderr
+++ b/tests/ui/nll/issue-48623-coroutine.stderr
@@ -1,10 +1,10 @@
-warning: unused generator that must be used
-  --> $DIR/issue-48623-generator.rs:15:5
+warning: unused coroutine that must be used
+  --> $DIR/issue-48623-coroutine.rs:15:5
    |
 LL |     move || { d; yield; &mut *r };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: generators are lazy and do nothing unless resumed
+   = note: coroutines are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/nll/issue-55850.rs b/tests/ui/nll/issue-55850.rs
index e6279bd028e..fc873af9463 100644
--- a/tests/ui/nll/issue-55850.rs
+++ b/tests/ui/nll/issue-55850.rs
@@ -1,16 +1,16 @@
 #![allow(unused_mut)]
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
 use std::marker::Unpin;
-use std::ops::Generator;
-use std::ops::GeneratorState::Yielded;
+use std::ops::Coroutine;
+use std::ops::CoroutineState::Yielded;
 use std::pin::Pin;
 
 pub struct GenIter<G>(G);
 
 impl <G> Iterator for GenIter<G>
 where
-    G: Generator + Unpin,
+    G: Coroutine + Unpin,
 {
     type Item = G::Yield;
 
@@ -26,7 +26,7 @@ fn bug<'a>() -> impl Iterator<Item = &'a str> {
     GenIter(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 generator yields
+        //~| ERROR borrow may still be in use when coroutine yields
     })
 }
 
diff --git a/tests/ui/nll/issue-55850.stderr b/tests/ui/nll/issue-55850.stderr
index 86a8cdc42ff..3d43817f4d8 100644
--- a/tests/ui/nll/issue-55850.stderr
+++ b/tests/ui/nll/issue-55850.stderr
@@ -7,7 +7,7 @@ LL |         yield &s[..]
    |         |      `s` is borrowed here
    |         yields a value referencing data owned by the current function
 
-error[E0626]: borrow may still be in use when generator yields
+error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/issue-55850.rs:28:16
    |
 LL |         yield &s[..]
diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed
new file mode 100644
index 00000000000..45c7e07a264
--- /dev/null
+++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+trait TraitWithAType {
+    type Item: ?Sized;
+}
+trait Trait {}
+struct A {}
+impl TraitWithAType for A {
+    type Item = dyn Trait; //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs
new file mode 100644
index 00000000000..c3e958f4983
--- /dev/null
+++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+trait TraitWithAType {
+    type Item;
+}
+trait Trait {}
+struct A {}
+impl TraitWithAType for A {
+    type Item = dyn Trait; //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr
new file mode 100644
index 00000000000..110e7150733
--- /dev/null
+++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/assoc_type_bounds_implicit_sized.rs:8:17
+   |
+LL |     type Item = dyn Trait;
+   |                 ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+note: required by a bound in `TraitWithAType::Item`
+  --> $DIR/assoc_type_bounds_implicit_sized.rs:3:5
+   |
+LL |     type Item;
+   |     ^^^^^^^^^^ required by this bound in `TraitWithAType::Item`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Item: ?Sized;
+   |              ++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
index 224d33fb2da..b67a1244ece 100644
--- a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
+++ b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
@@ -33,6 +33,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized`
 LL - fn bop<T: Bop + ?Sized>() {
 LL + fn bop<T: Bop>() {
    |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Bar: Default + ?Sized
+   |                       ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs
index 9f9f41e2515..4fec72763a4 100644
--- a/tests/ui/packed/packed-struct-drop-aligned.rs
+++ b/tests/ui/packed/packed-struct-drop-aligned.rs
@@ -1,9 +1,9 @@
 // run-pass
-#![feature(generators)]
-#![feature(generator_trait)]
+#![feature(coroutines)]
+#![feature(coroutine_trait)]
 use std::cell::Cell;
 use std::mem;
-use std::ops::Generator;
+use std::ops::Coroutine;
 use std::pin::Pin;
 
 struct Aligned<'a> {
@@ -44,7 +44,7 @@ fn main() {
         let _ = &p;
         p.1 = Aligned { drop_count };
         assert_eq!(drop_count.get(), 1);
-        // Test that a generator drop function moves a value from a packed
+        // Test that a coroutine drop function moves a value from a packed
         // struct to a separate local before dropping it. We move out the
         // first field to generate and open drop for the second field.
         drop(p.0);
diff --git a/tests/ui/polymorphization/generators.rs b/tests/ui/polymorphization/coroutine.rs
index 779bac0ace2..3f28e89e36c 100644
--- a/tests/ui/polymorphization/generators.rs
+++ b/tests/ui/polymorphization/coroutine.rs
@@ -1,10 +1,10 @@
 // build-fail
 // compile-flags:-Zpolymorphize=on -Zinline-mir=off
-#![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+#![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)]
 //~^ WARN the feature `generic_const_exprs` is incomplete
 
 use std::marker::Unpin;
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 enum YieldOrReturn<Y, R> {
@@ -14,13 +14,13 @@ enum YieldOrReturn<Y, R> {
 
 fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>>
 where
-    T: Generator<(), Yield = Y, Return = R> + Unpin,
+    T: Coroutine<(), Yield = Y, Return = R> + Unpin,
 {
     let mut results = Vec::new();
     loop {
         match Pin::new(&mut t).resume(()) {
-            GeneratorState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)),
-            GeneratorState::Complete(returned) => {
+            CoroutineState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)),
+            CoroutineState::Complete(returned) => {
                 results.push(YieldOrReturn::Return(returned));
                 return results;
             }
@@ -28,10 +28,10 @@ where
     }
 }
 
-// This test checks that the polymorphization analysis functions on generators.
+// This test checks that the polymorphization analysis functions on coroutines.
 
 #[rustc_polymorphize_error]
-pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -40,7 +40,7 @@ pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
 }
 
 #[rustc_polymorphize_error]
-pub fn used_type_in_yield<Y: Default>() -> impl Generator<(), Yield = Y, Return = u32> + Unpin {
+pub fn used_type_in_yield<Y: Default>() -> impl Coroutine<(), Yield = Y, Return = u32> + Unpin {
     || {
         yield Y::default();
         2
@@ -48,7 +48,7 @@ pub fn used_type_in_yield<Y: Default>() -> impl Generator<(), Yield = Y, Return
 }
 
 #[rustc_polymorphize_error]
-pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Return = R> + Unpin {
+pub fn used_type_in_return<R: Default>() -> impl Coroutine<(), Yield = u32, Return = R> + Unpin {
     || {
         yield 3;
         R::default()
@@ -56,7 +56,7 @@ pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Retu
 }
 
 #[rustc_polymorphize_error]
-pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -65,7 +65,7 @@ pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return =
 }
 
 #[rustc_polymorphize_error]
-pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
+pub fn used_const_in_yield<const Y: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
 {
     || {
         yield Y;
@@ -74,7 +74,7 @@ pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Re
 }
 
 #[rustc_polymorphize_error]
-pub fn used_const_in_return<const R: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
+pub fn used_const_in_return<const R: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin
 {
     || {
         yield 4;
diff --git a/tests/ui/polymorphization/generators.stderr b/tests/ui/polymorphization/coroutine.stderr
index 32d49d25f02..67b55a59883 100644
--- a/tests/ui/polymorphization/generators.stderr
+++ b/tests/ui/polymorphization/coroutine.stderr
@@ -1,24 +1,24 @@
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generators.rs:3:12
+  --> $DIR/coroutine.rs:3:12
    |
-LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+LL | #![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)]
    |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:35:5
+  --> $DIR/coroutine.rs:35:5
    |
-LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+LL | pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
    |                    - generic parameter `T` is unused
 LL |     || {
    |     ^^
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:60:5
+  --> $DIR/coroutine.rs:60:5
    |
-LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+LL | pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin {
    |                     ------------ generic parameter `T` is unused
 LL |     || {
    |     ^^
diff --git a/tests/ui/print_type_sizes/generator.rs b/tests/ui/print_type_sizes/coroutine.rs
index d1cd36274ef..aae72e0f37e 100644
--- a/tests/ui/print_type_sizes/generator.rs
+++ b/tests/ui/print_type_sizes/coroutine.rs
@@ -2,11 +2,11 @@
 // build-pass
 // ignore-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 
-use std::ops::Generator;
+use std::ops::Coroutine;
 
-fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Return = ()> {
+fn coroutine<const C: usize>(array: [u8; C]) -> impl Coroutine<Yield = (), Return = ()> {
     move |()| {
         yield ();
         let _ = array;
@@ -14,5 +14,5 @@ fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Retur
 }
 
 pub fn foo() {
-    let _ = generator([0; 8192]);
+    let _ = coroutine([0; 8192]);
 }
diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/coroutine.stdout
index f8c52a595cc..5d51339558c 100644
--- a/tests/ui/print_type_sizes/generator.stdout
+++ b/tests/ui/print_type_sizes/coroutine.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `{generator@$DIR/generator.rs:10:5: 10:14}`: 8193 bytes, alignment: 1 bytes
+print-type-size type: `{coroutine@$DIR/coroutine.rs:10:5: 10: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/generator_discr_placement.rs b/tests/ui/print_type_sizes/coroutine_discr_placement.rs
index 6adc14f9b99..78fe75cdeb9 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.rs
+++ b/tests/ui/print_type_sizes/coroutine_discr_placement.rs
@@ -2,10 +2,10 @@
 // build-pass
 // ignore-pass
 
-// Tests a generator that has its discriminant as the *final* field.
+// Tests a coroutine that has its discriminant as the *final* field.
 
 // Avoid emitting panic handlers, like the rest of these tests...
-#![feature(generators)]
+#![feature(coroutines)]
 #![allow(dropping_copy_types)]
 
 pub fn foo() {
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout
index f7bdee1112b..f34a8e9a706 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.stdout
+++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `{generator@$DIR/generator_discr_placement.rs:12:13: 12:15}`: 8 bytes, alignment: 4 bytes
+print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:12:13: 12:15}`: 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/closure-in-projection-issue-97405.rs b/tests/ui/regions/closure-in-projection-issue-97405.rs
index e567d5c2723..5489533972e 100644
--- a/tests/ui/regions/closure-in-projection-issue-97405.rs
+++ b/tests/ui/regions/closure-in-projection-issue-97405.rs
@@ -1,5 +1,5 @@
 // Regression test for #97405.
-// In `good_generic_fn` the param `T` ends up in the substs of closures/generators,
+// In `good_generic_fn` the param `T` ends up in the substs of closures/coroutines,
 // but we should be able to prove `<Gen<T> as Iterator>::Item: 'static` without
 // requiring `T: 'static`
 
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
index 3482af74752..ecfeb3f9b98 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs
@@ -13,8 +13,8 @@ use enums::{
     EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
     VariantNonExhaustive,
 };
-use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
 use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
+use unstable::{OnlyUnstableEnum, OnlyUnstableStruct, UnstableEnum, UnstableStruct};
 
 #[non_exhaustive]
 #[derive(Default)]
@@ -35,10 +35,10 @@ fn main() {
     let enumeration = Bar::A;
 
     // Ok: this is a crate local non_exhaustive enum
+    #[deny(non_exhaustive_omitted_patterns)]
     match enumeration {
         Bar::A => {}
         Bar::B => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
 
@@ -51,50 +51,87 @@ fn main() {
         _ => {}
     }
 
+    #[deny(non_exhaustive_omitted_patterns)]
     match non_enum {
+        //~^ some variants are not matched explicitly
         NonExhaustiveEnum::Unit => {}
         NonExhaustiveEnum::Tuple(_) => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 
+    #[deny(non_exhaustive_omitted_patterns)]
     match non_enum {
+        //~^ some variants are not matched explicitly
         NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 
     let x = 5;
+    // We ignore the guard.
+    #[deny(non_exhaustive_omitted_patterns)]
     match non_enum {
         NonExhaustiveEnum::Unit if x > 10 => {}
         NonExhaustiveEnum::Tuple(_) => {}
         NonExhaustiveEnum::Struct { .. } => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match (non_enum, true) {
+        (NonExhaustiveEnum::Unit, true) => {}
+        (NonExhaustiveEnum::Tuple(_), false) => {}
+        (NonExhaustiveEnum::Struct { .. }, false) => {}
+        _ => {}
+    }
+    #[deny(non_exhaustive_omitted_patterns)]
+    match (non_enum, true) {
+        //~^ some variants are not matched explicitly
+        (NonExhaustiveEnum::Unit, true) => {}
+        (NonExhaustiveEnum::Tuple(_), false) => {}
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match (true, non_enum) {
+        (true, NonExhaustiveEnum::Unit) => {}
+        (false, NonExhaustiveEnum::Tuple(_)) => {}
+        (false, NonExhaustiveEnum::Struct { .. }) => {}
+        _ => {}
+    }
+    #[deny(non_exhaustive_omitted_patterns)]
+    match (true, non_enum) {
+        //~^ some variants are not matched explicitly
+        (true, NonExhaustiveEnum::Unit) => {}
+        (false, NonExhaustiveEnum::Tuple(_)) => {}
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match Some(non_enum) {
+        //~^ some variants are not matched explicitly
+        Some(NonExhaustiveEnum::Unit) => {}
+        Some(NonExhaustiveEnum::Tuple(_)) => {}
+        _ => {}
+    }
 
     // Ok: all covered and not `unreachable-patterns`
     #[deny(unreachable_patterns)]
+    #[deny(non_exhaustive_omitted_patterns)]
     match non_enum {
         NonExhaustiveEnum::Unit => {}
         NonExhaustiveEnum::Tuple(_) => {}
         NonExhaustiveEnum::Struct { .. } => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
 
     #[deny(non_exhaustive_omitted_patterns)]
     match NestedNonExhaustive::B {
+        //~^ some variants are not matched explicitly
         NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
         NestedNonExhaustive::A(_) => {}
         NestedNonExhaustive::B => {}
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
-    //~^^^^^ some variants are not matched explicitly
 
     #[warn(non_exhaustive_omitted_patterns)]
     match VariantNonExhaustive::Baz(1, 2) {
@@ -120,30 +157,36 @@ fn main() {
     #[warn(non_exhaustive_omitted_patterns)]
     let MixedVisFields { a, b, .. } = MixedVisFields::default();
 
-    // Ok: because this only has 1 variant
+    // Ok: this only has 1 variant
     #[deny(non_exhaustive_omitted_patterns)]
     match NonExhaustiveSingleVariant::A(true) {
         NonExhaustiveSingleVariant::A(true) => {}
         _ => {}
     }
 
+    // We can't catch the case below, so for consistency we don't catch this one either.
     #[deny(non_exhaustive_omitted_patterns)]
     match NonExhaustiveSingleVariant::A(true) {
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
+    // We can't catch this case, because this would require digging fully through all the values of
+    // any type we encounter. We need to be able to only consider present constructors.
+    #[deny(non_exhaustive_omitted_patterns)]
+    match &NonExhaustiveSingleVariant::A(true) {
+        _ => {}
+    }
 
     // Ok: we don't lint on `if let` expressions
     #[deny(non_exhaustive_omitted_patterns)]
     if let NonExhaustiveEnum::Tuple(_) = non_enum {}
 
+    #[deny(non_exhaustive_omitted_patterns)]
     match UnstableEnum::Stable {
+        //~^ some variants are not matched explicitly
         UnstableEnum::Stable => {}
         UnstableEnum::Stable2 => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 
     // Ok: the feature is on and all variants are matched
     #[deny(non_exhaustive_omitted_patterns)]
@@ -164,10 +207,10 @@ fn main() {
 
     #[deny(non_exhaustive_omitted_patterns)]
     match OnlyUnstableEnum::Unstable {
+        //~^ some variants are not matched explicitly
         OnlyUnstableEnum::Unstable => {}
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 
     #[warn(non_exhaustive_omitted_patterns)]
     let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
@@ -194,14 +237,13 @@ fn main() {
     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
     //~^ refutable pattern in local binding
 
-    // Check that matching on a reference results in a correctly spanned diagnostic
     #[deny(non_exhaustive_omitted_patterns)]
     match &non_enum {
+        //~^ some variants are not matched explicitly
         NonExhaustiveEnum::Unit => {}
         NonExhaustiveEnum::Tuple(_) => {}
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 }
 
 #[deny(non_exhaustive_omitted_patterns)]
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
index 923394474b2..7db61f1241e 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -1,5 +1,5 @@
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:102:9
+  --> $DIR/omitted-patterns.rs:139:9
    |
 LL |         VariantNonExhaustive::Bar { x, .. } => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
@@ -7,13 +7,13 @@ LL |         VariantNonExhaustive::Bar { x, .. } => {}
    = help: ensure that all fields are mentioned explicitly by adding the suggested fields
    = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:99:12
+  --> $DIR/omitted-patterns.rs:136:12
    |
 LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:107:9
+  --> $DIR/omitted-patterns.rs:144:9
    |
 LL |     let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
@@ -21,13 +21,13 @@ LL |     let FunctionalRecord { first_field, second_field, .. } = FunctionalReco
    = help: ensure that all fields are mentioned explicitly by adding the suggested fields
    = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:106:12
+  --> $DIR/omitted-patterns.rs:143:12
    |
 LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:115:29
+  --> $DIR/omitted-patterns.rs:152:29
    |
 LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
@@ -35,13 +35,13 @@ LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested
    = help: ensure that all fields are mentioned explicitly by adding the suggested fields
    = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:114:12
+  --> $DIR/omitted-patterns.rs:151:12
    |
 LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:115:9
+  --> $DIR/omitted-patterns.rs:152:9
    |
 LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
@@ -50,7 +50,7 @@ LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested
    = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
 
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:173:9
+  --> $DIR/omitted-patterns.rs:216:9
    |
 LL |     let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
@@ -58,13 +58,13 @@ LL |     let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
    = help: ensure that all fields are mentioned explicitly by adding the suggested fields
    = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:172:12
+  --> $DIR/omitted-patterns.rs:215:12
    |
 LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: some fields are not explicitly listed
-  --> $DIR/omitted-patterns.rs:181:9
+  --> $DIR/omitted-patterns.rs:224:9
    |
 LL |     let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
@@ -72,120 +72,125 @@ LL |     let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
    = help: ensure that all fields are mentioned explicitly by adding the suggested fields
    = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:180:12
+  --> $DIR/omitted-patterns.rs:223:12
    |
 LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:58:9
+  --> $DIR/omitted-patterns.rs:55:11
    |
-LL |         _ => {}
-   |         ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+LL |     match non_enum {
+   |           ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
    = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:57:16
+  --> $DIR/omitted-patterns.rs:54:12
    |
-LL |         #[deny(non_exhaustive_omitted_patterns)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:65:9
+  --> $DIR/omitted-patterns.rs:63:11
    |
-LL |         _ => {}
-   |         ^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
+LL |     match non_enum {
+   |           ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
    = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:64:16
+  --> $DIR/omitted-patterns.rs:62:12
    |
-LL |         #[deny(non_exhaustive_omitted_patterns)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:75:9
+  --> $DIR/omitted-patterns.rs:87:11
    |
-LL |         _ => {}
-   |         ^ pattern `NonExhaustiveEnum::Unit` not covered
+LL |     match (non_enum, true) {
+   |           ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
-   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+   = note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:74:16
+  --> $DIR/omitted-patterns.rs:86:12
    |
-LL |         #[deny(non_exhaustive_omitted_patterns)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:92:32
+  --> $DIR/omitted-patterns.rs:102:11
    |
-LL |         NestedNonExhaustive::A(_) => {}
-   |                                ^ patterns `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+LL |     match (true, non_enum) {
+   |           ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
-   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+   = note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:89:12
+  --> $DIR/omitted-patterns.rs:101:12
    |
 LL |     #[deny(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:94:9
+  --> $DIR/omitted-patterns.rs:110:11
    |
-LL |         _ => {}
-   |         ^ pattern `NestedNonExhaustive::C` not covered
+LL |     match Some(non_enum) {
+   |           ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
-   = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+   = note: the matched value is of type `Option<NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+  --> $DIR/omitted-patterns.rs:109:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:132:9
+  --> $DIR/omitted-patterns.rs:128:11
    |
-LL |         _ => {}
-   |         ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered
+LL |     match NestedNonExhaustive::B {
+   |           ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
-   = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+   = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:130:12
+  --> $DIR/omitted-patterns.rs:127:12
    |
 LL |     #[deny(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:144:9
+  --> $DIR/omitted-patterns.rs:184:11
    |
-LL |         _ => {}
-   |         ^ pattern `UnstableEnum::Unstable` not covered
+LL |     match UnstableEnum::Stable {
+   |           ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
    = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:143:16
+  --> $DIR/omitted-patterns.rs:183:12
    |
-LL |         #[deny(non_exhaustive_omitted_patterns)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:168:9
+  --> $DIR/omitted-patterns.rs:209:11
    |
-LL |         _ => {}
-   |         ^ pattern `OnlyUnstableEnum::Unstable2` not covered
+LL |     match OnlyUnstableEnum::Unstable {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
    = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:165:12
+  --> $DIR/omitted-patterns.rs:208:12
    |
 LL |     #[deny(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/omitted-patterns.rs:194:9
+  --> $DIR/omitted-patterns.rs:237:9
    |
 LL |     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
    |         ^^^^^^^^^^^^^^^ pattern `_` not covered
@@ -199,15 +204,15 @@ LL |     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit
    |                                                                             ++++++++++++++++
 
 error: some variants are not matched explicitly
-  --> $DIR/omitted-patterns.rs:202:9
+  --> $DIR/omitted-patterns.rs:241:11
    |
-LL |         _ => {}
-   |         ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+LL |     match &non_enum {
+   |           ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
-   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+   = note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/omitted-patterns.rs:198:12
+  --> $DIR/omitted-patterns.rs:240:12
    |
 LL |     #[deny(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
index 82ee68687ed..1828fdef901 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
@@ -6,23 +6,23 @@
 // aux-build:unstable.rs
 extern crate unstable;
 
-use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
+use unstable::{OnlyUnstableEnum, OnlyUnstableStruct, UnstableEnum, UnstableStruct};
 
 fn main() {
     // OK: this matches all the stable variants
+    #[deny(non_exhaustive_omitted_patterns)]
     match UnstableEnum::Stable {
         UnstableEnum::Stable => {}
         UnstableEnum::Stable2 => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
 
+    #[deny(non_exhaustive_omitted_patterns)]
     match UnstableEnum::Stable {
+        //~^ some variants are not matched explicitly
         UnstableEnum::Stable => {}
-        #[deny(non_exhaustive_omitted_patterns)]
         _ => {}
     }
-    //~^^ some variants are not matched explicitly
 
     // Ok: although this is a bit odd, we don't have anything to report
     // since there is no stable variants and the feature is off
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
index f38368590fb..27939176f75 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
@@ -13,18 +13,18 @@ LL |     #[warn(non_exhaustive_omitted_patterns)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: some variants are not matched explicitly
-  --> $DIR/stable-omitted-patterns.rs:23:9
+  --> $DIR/stable-omitted-patterns.rs:21:11
    |
-LL |         _ => {}
-   |         ^ pattern `UnstableEnum::Stable2` not covered
+LL |     match UnstableEnum::Stable {
+   |           ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Stable2` not covered
    |
    = help: ensure that all variants are matched explicitly by adding the suggested match arms
    = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
 note: the lint level is defined here
-  --> $DIR/stable-omitted-patterns.rs:22:16
+  --> $DIR/stable-omitted-patterns.rs:20:12
    |
-LL |         #[deny(non_exhaustive_omitted_patterns)]
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
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 670c423a7e0..86bcf1f6f8d 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs
@@ -2,10 +2,10 @@
 
 #![feature(stmt_expr_attributes)]
 #![feature(closure_track_caller)]
-#![feature(generator_trait)]
-#![feature(generators)]
+#![feature(coroutine_trait)]
+#![feature(coroutines)]
 
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 use std::panic::Location;
 
@@ -93,53 +93,53 @@ fn test_closure() {
 
 
 #[track_caller]
-fn mono_generator<F: Generator<String, Yield = (&'static str, String, Loc), Return = ()>>(
+fn mono_coroutine<F: Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>(
     val: Pin<&mut F>
 ) -> (&'static str, String, Loc) {
     match val.resume("Mono".to_string()) {
-        GeneratorState::Yielded(val) => val,
+        CoroutineState::Yielded(val) => val,
         _ => unreachable!()
     }
 }
 
 #[track_caller]
-fn dyn_generator(
-    val: Pin<&mut dyn Generator<String, Yield = (&'static str, String, Loc), Return = ()>>
+fn dyn_coroutine(
+    val: Pin<&mut dyn Coroutine<String, Yield = (&'static str, String, Loc), Return = ()>>
 ) -> (&'static str, String, Loc) {
     match val.resume("Dyn".to_string()) {
-        GeneratorState::Yielded(val) => val,
+        CoroutineState::Yielded(val) => val,
         _ => unreachable!()
     }
 }
 
-fn test_generator() {
-    let generator = #[track_caller] |arg: String| {
+fn test_coroutine() {
+    let coroutine = #[track_caller] |arg: String| {
         yield ("first", arg.clone(), Location::caller());
         yield ("second", arg.clone(), Location::caller());
     };
 
-    let mut pinned = Box::pin(generator);
-    let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut());
+    let mut pinned = Box::pin(coroutine);
+    let (dyn_ret, dyn_arg, dyn_loc) = dyn_coroutine(pinned.as_mut());
     assert_eq!(dyn_ret, "first");
     assert_eq!(dyn_arg, "Dyn".to_string());
-    // The `Generator` trait does not have `#[track_caller]` on `resume`, so
+    // The `Coroutine` trait does not have `#[track_caller]` on `resume`, so
     // this will not match.
     assert_ne!(dyn_loc.file(), file!());
 
 
-    let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut());
+    let (mono_ret, mono_arg, mono_loc) = mono_coroutine(pinned.as_mut());
     let mono_line = line!() - 1;
     assert_eq!(mono_ret, "second");
-    // The generator ignores the argument to the second `resume` call
+    // The coroutine ignores the argument to the second `resume` call
     assert_eq!(mono_arg, "Dyn".to_string());
     assert_eq!(mono_loc.file(), file!());
     assert_eq!(mono_loc.line(), mono_line);
     assert_eq!(mono_loc.column(), 42);
 
-    let non_tracked_generator = || { yield Location::caller(); };
-    let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller
-    let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) {
-        GeneratorState::Yielded(val) => val,
+    let non_tracked_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,
         _ => unreachable!()
     };
     assert_eq!(non_tracked_loc.file(), file!());
@@ -150,5 +150,5 @@ fn test_generator() {
 
 fn main() {
     test_closure();
-    test_generator();
+    test_coroutine();
 }
diff --git a/tests/ui/sanitize/issue-111184-generator-witness.rs b/tests/ui/sanitize/issue-111184-coroutine-witness.rs
index d36d8bce561..dffb739f203 100644
--- a/tests/ui/sanitize/issue-111184-generator-witness.rs
+++ b/tests/ui/sanitize/issue-111184-coroutine-witness.rs
@@ -1,4 +1,4 @@
-// Regression test for issue 111184, where ty::GeneratorWitness were not expected to occur in
+// Regression test for issue 111184, where ty::CoroutineWitness were not expected to occur in
 // encode_ty and caused the compiler to ICE.
 //
 // needs-sanitizer-cfi
diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr
index 6d0a0c7b3fa..238ee637c7d 100644
--- a/tests/ui/suggestions/issue-81839.stderr
+++ b/tests/ui/suggestions/issue-81839.stderr
@@ -4,15 +4,22 @@ error[E0308]: `match` arms have incompatible types
 LL | /     match num {
 LL | |         1 => {
 LL | |             cx.answer_str("hi");
-   | |             --------------------
-   | |             |                  |
-   | |             |                  help: consider removing this semicolon
-   | |             this is found to be of type `()`
+   | |             -------------------- this is found to be of type `()`
 LL | |         }
 LL | |         _ => cx.answer_str("hi"),
    | |              ^^^^^^^^^^^^^^^^^^^ expected `()`, found future
 LL | |     }
    | |_____- `match` arms have incompatible types
+   |
+help: consider removing this semicolon
+   |
+LL -             cx.answer_str("hi");
+LL +             cx.answer_str("hi")
+   |
+help: consider using a semicolon here, but this will discard any values in the match arms
+   |
+LL |     };
+   |      +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs
index 6813b07a2ee..6a35d779c1c 100644
--- a/tests/ui/suggestions/issue-84973-blacklist.rs
+++ b/tests/ui/suggestions/issue-84973-blacklist.rs
@@ -1,7 +1,7 @@
 // Checks that certain traits for which we don't want to suggest borrowing
 // are blacklisted and don't cause the suggestion to be issued.
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn f_copy<T: Copy>(t: T) {}
 fn f_clone<T: Clone>(t: T) {}
diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr
index c8ce146cebf..e0bdb6949a9 100644
--- a/tests/ui/suggestions/issue-84973-blacklist.stderr
+++ b/tests/ui/suggestions/issue-84973-blacklist.stderr
@@ -31,11 +31,11 @@ LL + #[derive(Clone)]
 LL | struct S;
    |
 
-error[E0277]: `{static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` cannot be unpinned
+error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` cannot be unpinned
   --> $DIR/issue-84973-blacklist.rs:17:13
    |
 LL |     f_unpin(static || { yield; });
-   |     ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22}`
+   |     ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/suggestions/silenced-binding-typo.fixed b/tests/ui/suggestions/silenced-binding-typo.fixed
new file mode 100644
index 00000000000..e0f9e31bef3
--- /dev/null
+++ b/tests/ui/suggestions/silenced-binding-typo.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let x = 42; //~ HELP
+    let _y = x; //~ ERROR
+}
diff --git a/tests/ui/suggestions/silenced-binding-typo.rs b/tests/ui/suggestions/silenced-binding-typo.rs
new file mode 100644
index 00000000000..6cadd5a93a7
--- /dev/null
+++ b/tests/ui/suggestions/silenced-binding-typo.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _x = 42; //~ HELP
+    let _y = x; //~ ERROR
+}
diff --git a/tests/ui/suggestions/silenced-binding-typo.stderr b/tests/ui/suggestions/silenced-binding-typo.stderr
new file mode 100644
index 00000000000..9c0e6e26569
--- /dev/null
+++ b/tests/ui/suggestions/silenced-binding-typo.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/silenced-binding-typo.rs:4:14
+   |
+LL |     let _y = x;
+   |              ^
+   |
+help: a local variable with a similar name exists, consider changing it
+   |
+LL |     let x = 42;
+   |         ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs
index f2485041d9b..a4e32d7c806 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(generators)]
+#![feature(coroutines)]
 
 const A = 5;
 //~^ ERROR: missing type for `const` item
diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr
index 19e9af14535..d003b91691c 100644
--- a/tests/ui/suggestions/unnamable-types.stderr
+++ b/tests/ui/suggestions/unnamable-types.stderr
@@ -55,7 +55,7 @@ error: missing type for `const` item
 LL | const G = || -> i32 { yield 0; return 1; };
    |        ^
    |
-note: however, the inferred type `{generator@$DIR/unnamable-types.rs:37:11: 37:20}` cannot be named
+note: however, the inferred type `{coroutine@$DIR/unnamable-types.rs:37:11: 37:20}` cannot be named
   --> $DIR/unnamable-types.rs:37:11
    |
 LL | const G = || -> i32 { yield 0; return 1; };
diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs
index fd53bb607f7..61f54ac4e0b 100644
--- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs
+++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs
@@ -37,7 +37,7 @@ macro_rules! is_sync_send {
 }
 
 fn main() {
-    // The iterator "generator" list should exhaust what corresponding
+    // The iterator "coroutine" list should exhaust what corresponding
     // implementations have where `Sync` and `Send` semantics apply.
     all_sync_send!(BinaryHeap::<usize>::new(), iter, drain, into_iter);
 
diff --git a/tests/ui/traits/new-solver/coroutine.fail.stderr b/tests/ui/traits/new-solver/coroutine.fail.stderr
new file mode 100644
index 00000000000..14e67727d0b
--- /dev/null
+++ b/tests/ui/traits/new-solver/coroutine.fail.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:18:21: 18:23}: Coroutine<A>` is not satisfied
+  --> $DIR/coroutine.rs:18:21
+   |
+LL |       needs_coroutine(|| {
+   |  _____---------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | |         yield ();
+LL | |     });
+   | |_____^ the trait `Coroutine<A>` is not implemented for `{coroutine@$DIR/coroutine.rs:18:21: 18:23}`
+   |
+note: required by a bound in `needs_coroutine`
+  --> $DIR/coroutine.rs:14:28
+   |
+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
+   |
+LL |       needs_coroutine(|| {
+   |  _____---------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | |         yield ();
+LL | |     });
+   | |_____^ types differ
+   |
+note: required by a bound in `needs_coroutine`
+  --> $DIR/coroutine.rs:14:41
+   |
+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
+   |
+LL |       needs_coroutine(|| {
+   |  _____---------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | |         yield ();
+LL | |     });
+   | |_____^ types differ
+   |
+note: required by a bound in `needs_coroutine`
+  --> $DIR/coroutine.rs:14:52
+   |
+LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
+   |                                                    ^^^^^^^^^^ required by this bound in `needs_coroutine`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/new-solver/coroutine.rs b/tests/ui/traits/new-solver/coroutine.rs
new file mode 100644
index 00000000000..af16f70fb56
--- /dev/null
+++ b/tests/ui/traits/new-solver/coroutine.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Ztrait-solver=next
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+#![feature(coroutine_trait, coroutines)]
+
+use std::ops::Coroutine;
+
+struct A;
+struct B;
+struct C;
+
+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 ();
+    });
+}
+
+#[cfg(pass)]
+fn main() {
+    needs_coroutine(|_: A| {
+        let _: A = yield B;
+        C
+    })
+}
diff --git a/tests/ui/traits/new-solver/generator.fail.stderr b/tests/ui/traits/new-solver/generator.fail.stderr
deleted file mode 100644
index e3fe4bf5a6a..00000000000
--- a/tests/ui/traits/new-solver/generator.fail.stderr
+++ /dev/null
@@ -1,64 +0,0 @@
-error[E0277]: the trait bound `{generator@$DIR/generator.rs:18:21: 18:23}: Generator<A>` is not satisfied
-  --> $DIR/generator.rs:18:21
-   |
-LL |       needs_generator(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ the trait `Generator<A>` is not implemented for `{generator@$DIR/generator.rs:18:21: 18:23}`
-   |
-note: required by a bound in `needs_generator`
-  --> $DIR/generator.rs:14:28
-   |
-LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_generator`
-
-error[E0271]: type mismatch resolving `<{generator@$DIR/generator.rs:18:21: 18:23} as Generator<A>>::Yield == B`
-  --> $DIR/generator.rs:18:21
-   |
-LL |       needs_generator(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ types differ
-   |
-note: required by a bound in `needs_generator`
-  --> $DIR/generator.rs:14:41
-   |
-LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
-   |                                         ^^^^^^^^^ required by this bound in `needs_generator`
-
-error[E0271]: type mismatch resolving `<{generator@$DIR/generator.rs:18:21: 18:23} as Generator<A>>::Return == C`
-  --> $DIR/generator.rs:18:21
-   |
-LL |       needs_generator(|| {
-   |  _____---------------_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |
-LL | |         yield ();
-LL | |     });
-   | |_____^ types differ
-   |
-note: required by a bound in `needs_generator`
-  --> $DIR/generator.rs:14:52
-   |
-LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
-   |                                                    ^^^^^^^^^^ required by this bound in `needs_generator`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/new-solver/generator.rs b/tests/ui/traits/new-solver/generator.rs
deleted file mode 100644
index 364373ca8be..00000000000
--- a/tests/ui/traits/new-solver/generator.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: -Ztrait-solver=next
-// edition: 2021
-// revisions: pass fail
-//[pass] check-pass
-
-#![feature(generator_trait, generators)]
-
-use std::ops::Generator;
-
-struct A;
-struct B;
-struct C;
-
-fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
-
-#[cfg(fail)]
-fn main() {
-    needs_generator(|| {
-        //[fail]~^ ERROR Generator<A>` is not satisfied
-        //[fail]~| ERROR as Generator<A>>::Yield == B`
-        //[fail]~| ERROR as Generator<A>>::Return == C`
-        yield ();
-    });
-}
-
-#[cfg(pass)]
-fn main() {
-    needs_generator(|_: A| {
-        let _: A = yield B;
-        C
-    })
-}
diff --git a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
index 3ff20d99ad8..7d8193b26cc 100644
--- a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
+++ b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
@@ -1,5 +1,5 @@
 // When WF checking the hidden type in the ParamEnv of the opaque type,
-// one complication arises when the hidden type is a closure/generator:
+// one complication arises when the hidden type is a closure/coroutine:
 // the "parent_substs" of the type may reference lifetime parameters
 // not present in the opaque type.
 // These region parameters are not really useful in this check.
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
new file mode 100644
index 00000000000..ad1ede9c3e4
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
@@ -0,0 +1,22 @@
+#![feature(coroutines, coroutine_trait, rustc_attrs)]
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+mod gen {
+    use std::ops::Coroutine;
+
+    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> {
+        move || {
+            yield yielding;
+
+            return returning;
+        }
+    }
+}
+
+const FOO: gen::CoroOnce<usize, usize> = gen::const_coroutine(10, 100);
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
deleted file mode 100644
index a213dbba4ea..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(generators, generator_trait, rustc_attrs)]
-#![feature(type_alias_impl_trait)]
-
-// check-pass
-
-mod gen {
-    use std::ops::Generator;
-
-    pub type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>;
-
-    pub const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
-        move || {
-            yield yielding;
-
-            return returning;
-        }
-    }
-}
-
-const FOO: gen::GenOnce<usize, usize> = gen::const_generator(10, 100);
-
-fn main() {}
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
new file mode 100644
index 00000000000..bc6a3439212
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+#![feature(coroutines, coroutine_trait)]
+#![feature(type_alias_impl_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+type RandCoroutine<'a> = impl Coroutine<Return = (), Yield = u64> + 'a;
+fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> {
+    move || {
+        let _rng = rng;
+        loop {
+            yield 0;
+        }
+    }
+}
+
+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> {
+        move || {
+            let _rng = rng;
+            loop {
+                yield 0;
+            }
+        }
+    }
+
+    helper(rng)
+}
+
+fn main() {
+    let mut gen = rand_coroutine(&());
+    match unsafe { Pin::new_unchecked(&mut gen) }.resume(()) {
+        CoroutineState::Yielded(_) => {}
+        CoroutineState::Complete(_) => {}
+    };
+}
diff --git a/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs
deleted file mode 100644
index 477b61390ed..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// check-pass
-
-#![feature(generators, generator_trait)]
-#![feature(type_alias_impl_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-type RandGenerator<'a> = impl Generator<Return = (), Yield = u64> + 'a;
-fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> {
-    move || {
-        let _rng = rng;
-        loop {
-            yield 0;
-        }
-    }
-}
-
-pub type RandGeneratorWithIndirection<'c> = impl Generator<Return = (), Yield = u64> + 'c;
-pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> {
-    fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return = (), Yield = u64> {
-        move || {
-            let _rng = rng;
-            loop {
-                yield 0;
-            }
-        }
-    }
-
-    helper(rng)
-}
-
-fn main() {
-    let mut gen = rand_generator(&());
-    match unsafe { Pin::new_unchecked(&mut gen) }.resume(()) {
-        GeneratorState::Yielded(_) => {}
-        GeneratorState::Complete(_) => {}
-    };
-}
diff --git a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
index 27ca7d0fdc9..a1cf23dab7b 100644
--- a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
 #![feature(type_alias_impl_trait)]
 
 trait Trait {}
diff --git a/tests/ui/type-alias-impl-trait/issue-94429.rs b/tests/ui/type-alias-impl-trait/issue-94429.rs
index d764545f906..306e73003fa 100644
--- a/tests/ui/type-alias-impl-trait/issue-94429.rs
+++ b/tests/ui/type-alias-impl-trait/issue-94429.rs
@@ -1,18 +1,18 @@
-#![feature(impl_trait_in_assoc_type, generator_trait, generators)]
-use std::ops::Generator;
+#![feature(impl_trait_in_assoc_type, coroutine_trait, coroutines)]
+use std::ops::Coroutine;
 
 trait Runnable {
-    type Gen: Generator<Yield = (), Return = ()>;
+    type Coro: Coroutine<Yield = (), Return = ()>;
 
-    fn run(&mut self) -> Self::Gen;
+    fn run(&mut self) -> Self::Coro;
 }
 
 struct Implementor {}
 
 impl Runnable for Implementor {
-    type Gen = impl Generator<Yield = (), Return = ()>;
+    type Coro = impl Coroutine<Yield = (), Return = ()>;
 
-    fn run(&mut self) -> Self::Gen {
+    fn run(&mut self) -> Self::Coro {
         //~^ ERROR: type mismatch resolving
         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 26605cdd2c2..360ecfa61bf 100644
--- a/tests/ui/type-alias-impl-trait/issue-94429.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr
@@ -1,8 +1,8 @@
-error[E0271]: type mismatch resolving `<{generator@$DIR/issue-94429.rs:17:9: 17:16} as Generator>::Yield == ()`
+error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:17:9: 17:16} as Coroutine>::Yield == ()`
   --> $DIR/issue-94429.rs:15:26
    |
-LL |     fn run(&mut self) -> Self::Gen {
-   |                          ^^^^^^^^^ expected integer, found `()`
+LL |     fn run(&mut self) -> Self::Coro {
+   |                          ^^^^^^^^^^ expected integer, found `()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/issue-36708.stderr b/tests/ui/typeck/issue-36708.stderr
index 140f19f1ff7..f1e0f471928 100644
--- a/tests/ui/typeck/issue-36708.stderr
+++ b/tests/ui/typeck/issue-36708.stderr
@@ -2,7 +2,12 @@ error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0
   --> $DIR/issue-36708.rs:8:12
    |
 LL |     fn foo<T>() {}
-   |            ^ found 1 type parameter, expected 0
+   |            ^ found 1 type parameter
+   |
+  ::: $DIR/auxiliary/issue-36708.rs:4:5
+   |
+LL |     fn foo();
+   |     --------- expected 0 type parameters
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs
index 29204276bb3..1ffc56e6612 100644
--- a/tests/ui/typeck/issue-91334.rs
+++ b/tests/ui/typeck/issue-91334.rs
@@ -2,6 +2,6 @@
 
 // error-pattern: this file contains an unclosed delimiter
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 fn f(){||yield(((){),
diff --git a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs
index 9d0aa413207..057bdf0f618 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs
@@ -5,5 +5,5 @@
 fn g<F>(_: F) where F: FnOnce(Option<F>) {}
 
 fn main() {
-    g(|_| {  }); //~ ERROR closure/generator type that references itself
+    g(|_| {  }); //~ ERROR closure/coroutine type that references itself
 }
diff --git a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
index 6d5dbca0558..9d3c1902cf3 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
@@ -1,4 +1,4 @@
-error[E0644]: closure/generator type that references itself
+error[E0644]: closure/coroutine type that references itself
   --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7
    |
 LL |     g(|_| {  });
diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs
index 892b281357f..6d40d6377c5 100644
--- a/tests/ui/weird-exprs.rs
+++ b/tests/ui/weird-exprs.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(generators)]
+#![feature(coroutines)]
 
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index 66504e44060..d5b23572ff5 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -11,6 +11,10 @@ LL | |     }
    |
    = note: expected reference `&S`
               found reference `&R`
+help: consider using a semicolon here, but this will discard any values in the match arms
+   |
+LL |     };
+   |      +
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-unsafe-trait-obj-match.rs:26:21
diff --git a/triagebot.toml b/triagebot.toml
index fbdc28787ff..e3c4233c843 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -23,10 +23,10 @@ allow-unauthenticated = [
     "needs-triage",
 ]
 
-[review-submitted] 
-# This label is added when a "request changes" review is submitted. 
-reviewed_label = "S-waiting-on-author" 
-# These labels are removed when a "request changes" review is submitted. 
+[review-submitted]
+# This label is added when a "request changes" review is submitted.
+reviewed_label = "S-waiting-on-author"
+# These labels are removed when a "request changes" review is submitted.
 review_labels = ["S-waiting-on-review"]
 
 [review-requested]
@@ -586,17 +586,19 @@ message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x
 message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging."
 cc = ["@davidtwco", "@wesleywiser"]
 
-[mentions."src/bootstrap/config.rs"]
-message = "This PR changes `src/bootstrap/config.rs`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`."
+[mentions."src/bootstrap/src/core/config"]
+message = "This PR modifies `src/bootstrap/src/core/config`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
+[mentions."src/bootstrap/defaults"]
+message = "This PR modifies `src/bootstrap/defaults`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
 [mentions."config.example.toml"]
-message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`."
+message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
 
 [mentions."src/bootstrap/defaults/config.compiler.toml"]
 message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync."
 [mentions."src/bootstrap/defaults/config.codegen.toml"]
 message = "This PR changes src/bootstrap/defaults/config.codegen.toml. If appropriate, please also update `config.compiler.toml` so the defaults are in sync."
 
-[mentions."src/bootstrap/llvm.rs"]
+[mentions."src/bootstrap/src/core/build_steps/llvm.rs"]
 message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp."
 
 [mentions."tests/ui/deriving/deriving-all-codegen.stdout"]