about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes6
-rw-r--r--compiler/rustc_ast/src/ast.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs7
-rw-r--r--compiler/rustc_ast/src/util/comments/tests.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs5
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs93
-rw-r--r--compiler/rustc_borrowck/src/lib.rs59
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs29
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs23
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs210
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs200
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs266
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/asm.rs7
-rw-r--r--compiler/rustc_const_eval/src/check_consts/resolver.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0307.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0708.md4
-rw-r--r--compiler/rustc_errors/src/lib.rs9
-rw-r--r--compiler/rustc_expand/src/expand.rs32
-rw-r--r--compiler/rustc_expand/src/module.rs10
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir/src/def.rs2
-rw-r--r--compiler/rustc_hir/src/definitions.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/intravisit.rs3
-rw-r--r--compiler/rustc_hir/src/tests.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs37
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs118
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs27
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs15
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs560
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs2
-rw-r--r--compiler/rustc_lint/src/async_closures.rs4
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/tests.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp2
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs5
-rw-r--r--compiler/rustc_middle/src/traits/query.rs12
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs37
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs95
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs88
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs63
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs82
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs48
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/visitor.rs21
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs12
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs102
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs44
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs78
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs44
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/points.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs12
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs32
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs56
-rw-r--r--compiler/rustc_mir_transform/src/strip_debuginfo.rs34
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs5
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs14
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs6
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs2
-rw-r--r--compiler/rustc_parse/src/parser/tokenstream/tests.rs2
-rw-r--r--compiler/rustc_passes/src/input_stats.rs1
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/ident.rs82
-rw-r--r--compiler/rustc_resolve/src/imports.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs7
-rw-r--r--compiler/rustc_resolve/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs3
-rw-r--r--compiler/rustc_session/src/config.rs16
-rw-r--r--compiler/rustc_session/src/options.rs14
-rw-r--r--compiler/rustc_span/src/edit_distance/tests.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/windows_gnullvm.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32v1_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs2
-rw-r--r--compiler/rustc_target/src/target_features.rs4
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs59
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs79
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs26
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs2
-rw-r--r--library/alloc/src/alloc.rs3
-rw-r--r--library/alloc/src/boxed.rs9
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs3
-rw-r--r--library/alloc/src/ffi/c_str.rs3
-rw-r--r--library/alloc/src/lib.rs4
-rw-r--r--library/alloc/src/slice.rs2
-rw-r--r--library/alloc/src/sync.rs3
-rw-r--r--library/alloc/tests/alloc.rs (renamed from library/alloc/src/alloc/tests.rs)5
-rw-r--r--library/alloc/tests/c_str2.rs (renamed from library/alloc/src/ffi/c_str/tests.rs)7
-rw-r--r--library/alloc/tests/collections/binary_heap.rs (renamed from library/alloc/src/collections/binary_heap/tests.rs)8
-rw-r--r--library/alloc/tests/collections/mod.rs1
-rw-r--r--library/alloc/tests/lib.rs24
-rw-r--r--library/alloc/tests/misc_tests.rs (renamed from library/alloc/src/tests.rs)0
-rw-r--r--library/alloc/tests/sync.rs (renamed from library/alloc/src/sync/tests.rs)10
-rw-r--r--library/alloc/tests/testing/crash_test.rs80
-rw-r--r--library/alloc/tests/testing/mod.rs1
-rw-r--r--library/core/src/error.rs2
-rw-r--r--library/core/src/ffi/mod.rs133
-rw-r--r--library/core/src/fmt/rt.rs34
-rw-r--r--library/core/src/num/mod.rs33
-rw-r--r--library/core/src/ops/async_function.rs24
-rw-r--r--library/core/src/prelude/mod.rs4
-rw-r--r--library/core/src/ptr/mut_ptr.rs9
-rw-r--r--library/core/src/slice/mod.rs58
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/hurd/mod.rs1
-rw-r--r--library/std/src/prelude/common.rs3
-rw-r--r--library/std/src/prelude/mod.rs21
-rw-r--r--library/unwind/src/lib.rs5
-rw-r--r--library/unwind/src/libunwind.rs9
-rw-r--r--src/bootstrap/src/bin/main.rs20
-rw-r--r--src/bootstrap/src/bin/rustc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs46
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs6
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs14
-rw-r--r--src/bootstrap/src/core/builder/mod.rs14
-rw-r--r--src/bootstrap/src/core/config/config.rs60
-rw-r--r--src/bootstrap/src/core/config/flags.rs4
-rw-r--r--src/bootstrap/src/core/download.rs26
-rw-r--r--src/bootstrap/src/core/sanity.rs4
-rw-r--r--src/bootstrap/src/lib.rs28
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/bootstrap/src/utils/helpers.rs6
-rw-r--r--src/bootstrap/src/utils/metrics.rs2
-rw-r--r--src/bootstrap/src/utils/render_tests.rs50
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh2
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/html/render/search_index.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/duplicate_mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.fixed1
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.rs1
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.stderr12
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.rs1
-rw-r--r--src/tools/clippy/tests/ui/infinite_loops.rs1
-rw-r--r--src/tools/clippy/tests/ui/infinite_loops.stderr42
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr34
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs2
-rw-r--r--src/tools/compiletest/src/compute_diff.rs2
-rw-r--r--src/tools/compiletest/src/debuggers.rs6
-rw-r--r--src/tools/compiletest/src/lib.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs52
-rw-r--r--src/tools/compiletest/src/runtest/codegen_units.rs22
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs10
-rw-r--r--src/tools/compiletest/src/runtest/incremental.rs2
-rw-r--r--src/tools/compiletest/src/runtest/mir_opt.rs2
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc_json.rs2
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs4
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure-captures.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure-drop.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure.rs2
-rw-r--r--src/tools/miri/tests/pass/async-drop.rs2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock44
-rw-r--r--src/tools/rust-analyzer/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs140
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs86
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lower.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs39
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs105
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs88
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs126
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/pretty.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs30
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs301
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs96
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs118
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs433
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs73
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs79
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs258
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs45
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs83
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs57
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs54
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs121
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs170
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs49
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs43
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs36
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs64
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs442
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs154
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs458
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs794
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs138
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs94
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs69
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/typing.rs403
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol.rs30
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs10
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs24
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs48
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs10
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs66
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs30
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs76
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs26
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs12
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/params.rs18
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs175
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/types.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/parser.rs19
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs51
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast7
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast14
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast50
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast8
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast33
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast79
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast83
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rast28
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast37
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast29
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast78
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast39
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast111
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast175
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rast32
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast9
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast15
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast10
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast24
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast21
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast461
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast6
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast14
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast48
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast128
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/precise_capturing.rast12
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast49
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast43
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast10
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast60
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0018_struct_type_params.rast48
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0020_type_param_bounds.rast23
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast57
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast8
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs48
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs95
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs11
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs37
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs78
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs40
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs64
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs124
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs38
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs30
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs351
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs49
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs22
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs274
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs115
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md2
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc4
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json46
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts31
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts18
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts12
-rw-r--r--src/tools/rust-analyzer/editors/code/src/run.ts35
-rw-r--r--src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts122
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rustfmt/src/items.rs2
-rw-r--r--src/tools/rustfmt/src/modules.rs7
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--tests/codegen/async-closure-debug.rs2
-rw-r--r--tests/codegen/instrument-coverage/testprog.rs6
-rw-r--r--tests/codegen/mem-replace-big-type.rs5
-rw-r--r--tests/codegen/naked-asan.rs11
-rw-r--r--tests/codegen/naked-fn/aligned.rs9
-rw-r--r--tests/codegen/naked-fn/generics.rs116
-rw-r--r--tests/codegen/naked-fn/instruction-set.rs59
-rw-r--r--tests/codegen/naked-fn/naked-functions.rs150
-rw-r--r--tests/codegen/naked-fn/naked-nocoverage.rs19
-rw-r--r--tests/codegen/naked-fn/naked-noinline.rs31
-rw-r--r--tests/coverage/async_closure.cov-map24
-rw-r--r--tests/coverage/async_closure.coverage1
-rw-r--r--tests/coverage/async_closure.rs1
-rw-r--r--tests/crashes/116979.rs14
-rw-r--r--tests/crashes/117808.rs27
-rw-r--r--tests/crashes/117877.rs13
-rw-r--r--tests/crashes/118778.rs24
-rw-r--r--tests/crashes/118784.rs19
-rw-r--r--tests/crashes/120175.rs11
-rw-r--r--tests/crashes/121176.rs9
-rw-r--r--tests/crashes/123861.rs5
-rw-r--r--tests/crashes/123862.rs14
-rw-r--r--tests/crashes/124375.rs11
-rw-r--r--tests/crashes/130395.rs10
-rw-r--r--tests/crashes/132765.rs12
-rw-r--r--tests/crashes/132766.rs9
-rw-r--r--tests/crashes/132882.rs13
-rw-r--r--tests/crashes/132981.rs7
-rw-r--r--tests/crashes/133063.rs8
-rw-r--r--tests/crashes/133066.rs12
-rw-r--r--tests/crashes/133199.rs11
-rw-r--r--tests/crashes/133275-1.rs13
-rw-r--r--tests/crashes/133275-2.rs15
-rw-r--r--tests/crashes/auxiliary/aux133199.rs13
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir6
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir6
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir6
-rw-r--r--tests/mir-opt/async_closure_shims.rs1
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff1
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff1
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir79
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir79
-rw-r--r--tests/mir-opt/strip_debuginfo.rs39
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs2
-rw-r--r--tests/ui/alias-uninit-value.rs19
-rw-r--r--tests/ui/allow-non-lint-warnings.rs8
-rw-r--r--tests/ui/artificial-block.rs5
-rw-r--r--tests/ui/as-precedence.rs10
-rw-r--r--tests/ui/asm/aarch64/srcloc.new.stderr320
-rw-r--r--tests/ui/asm/aarch64/srcloc.old.stderr (renamed from tests/ui/asm/aarch64/srcloc.stderr)48
-rw-r--r--tests/ui/asm/aarch64/srcloc.rs3
-rw-r--r--tests/ui/asm/generic_const_simd_vec_len.rs21
-rw-r--r--tests/ui/asm/generic_const_simd_vec_len.stderr14
-rw-r--r--tests/ui/asm/inline-syntax.arm.stderr24
-rw-r--r--tests/ui/asm/inline-syntax.arm_llvm_18.stderr90
-rw-r--r--tests/ui/asm/inline-syntax.rs16
-rw-r--r--tests/ui/asm/inline-syntax.x86_64.stderr14
-rw-r--r--tests/ui/asm/naked-functions-instruction-set.rs2
-rw-r--r--tests/ui/asm/named_const_simd_vec_len.rs22
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr64
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr194
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr64
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr194
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr64
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr194
-rw-r--r--tests/ui/asm/riscv/riscv32e-registers.rs14
-rw-r--r--tests/ui/asm/x86_64/srcloc.new.stderr332
-rw-r--r--tests/ui/asm/x86_64/srcloc.old.stderr (renamed from tests/ui/asm/x86_64/srcloc.stderr)50
-rw-r--r--tests/ui/asm/x86_64/srcloc.rs3
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.rs1
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.stderr2
-rw-r--r--tests/ui/async-await/async-closure-matches-expr.rs2
-rw-r--r--tests/ui/async-await/async-closure.rs2
-rw-r--r--tests/ui/async-await/async-closures/ambiguous-arg.rs2
-rw-r--r--tests/ui/async-await/async-closures/ambiguous-arg.stderr2
-rw-r--r--tests/ui/async-await/async-closures/arg-mismatch.rs2
-rw-r--r--tests/ui/async-await/async-closures/arg-mismatch.stderr4
-rw-r--r--tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/auxiliary/block-on.rs2
-rw-r--r--tests/ui/async-await/async-closures/auxiliary/foreign.rs2
-rw-r--r--tests/ui/async-await/async-closures/await-inference-guidance.rs2
-rw-r--r--tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs2
-rw-r--r--tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs2
-rw-r--r--tests/ui/async-await/async-closures/brand.rs2
-rw-r--r--tests/ui/async-await/async-closures/call-once-deduction.rs2
-rw-r--r--tests/ui/async-await/async-closures/captures.rs2
-rw-r--r--tests/ui/async-await/async-closures/clone-closure.rs2
-rw-r--r--tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs2
-rw-r--r--tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr4
-rw-r--r--tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs2
-rw-r--r--tests/ui/async-await/async-closures/debuginfo-by-move-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/def-path.rs2
-rw-r--r--tests/ui/async-await/async-closures/def-path.stderr2
-rw-r--r--tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs2
-rw-r--r--tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs2
-rw-r--r--tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr6
-rw-r--r--tests/ui/async-await/async-closures/drop.rs1
-rw-r--r--tests/ui/async-await/async-closures/fn-exception-target-features.rs2
-rw-r--r--tests/ui/async-await/async-closures/fn-exception.rs2
-rw-r--r--tests/ui/async-await/async-closures/fn-exception.stderr8
-rw-r--r--tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs2
-rw-r--r--tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs2
-rw-r--r--tests/ui/async-await/async-closures/foreign.rs2
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked-return.rs2
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked-return.stderr4
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked.rs2
-rw-r--r--tests/ui/async-await/async-closures/implements-fnmut.rs2
-rw-r--r--tests/ui/async-await/async-closures/inline-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/is-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/is-not-fn.rs4
-rw-r--r--tests/ui/async-await/async-closures/is-not-fn.stderr8
-rw-r--r--tests/ui/async-await/async-closures/lint-closure-returning-async-block.rs1
-rw-r--r--tests/ui/async-await/async-closures/lint-closure-returning-async-block.stderr12
-rw-r--r--tests/ui/async-await/async-closures/mac-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/mangle.rs2
-rw-r--r--tests/ui/async-await/async-closures/moro-example.rs2
-rw-r--r--tests/ui/async-await/async-closures/move-consuming-capture.rs2
-rw-r--r--tests/ui/async-await/async-closures/move-consuming-capture.stderr4
-rw-r--r--tests/ui/async-await/async-closures/move-is-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/move-out-of-ref.rs2
-rw-r--r--tests/ui/async-await/async-closures/move-out-of-ref.stderr4
-rw-r--r--tests/ui/async-await/async-closures/mut-ref-reborrow.rs2
-rw-r--r--tests/ui/async-await/async-closures/mutate.rs2
-rw-r--r--tests/ui/async-await/async-closures/no-borrow-from-env.rs2
-rw-r--r--tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs2
-rw-r--r--tests/ui/async-await/async-closures/not-clone-closure.rs2
-rw-r--r--tests/ui/async-await/async-closures/not-clone-closure.stderr8
-rw-r--r--tests/ui/async-await/async-closures/not-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/not-fn.stderr4
-rw-r--r--tests/ui/async-await/async-closures/not-lending.rs2
-rw-r--r--tests/ui/async-await/async-closures/not-lending.stderr8
-rw-r--r--tests/ui/async-await/async-closures/once.rs2
-rw-r--r--tests/ui/async-await/async-closures/overlapping-projs.rs2
-rw-r--r--tests/ui/async-await/async-closures/precise-captures.rs1
-rw-r--r--tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs4
-rw-r--r--tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr2
-rw-r--r--tests/ui/async-await/async-closures/refd.rs2
-rw-r--r--tests/ui/async-await/async-closures/return-type-mismatch.rs2
-rw-r--r--tests/ui/async-await/async-closures/return-type-mismatch.stderr2
-rw-r--r--tests/ui/async-await/async-closures/sig-from-bare-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/signature-deduction.rs2
-rw-r--r--tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs2
-rw-r--r--tests/ui/async-await/async-closures/tainted-body-2.rs2
-rw-r--r--tests/ui/async-await/async-closures/tainted-body-2.stderr2
-rw-r--r--tests/ui/async-await/async-closures/tainted-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/tainted-body.stderr2
-rw-r--r--tests/ui/async-await/async-closures/truncated-fields-when-imm.rs2
-rw-r--r--tests/ui/async-await/async-closures/validate-synthetic-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs2
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr20
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.rs2
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.stderr6
-rw-r--r--tests/ui/async-await/async-drop.rs2
-rw-r--r--tests/ui/async-await/async-fn/auxiliary/block-on.rs2
-rw-r--r--tests/ui/async-await/async-fn/dyn-pos.rs2
-rw-r--r--tests/ui/async-await/async-fn/dyn-pos.stderr2
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.rs2
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.stderr22
-rw-r--r--tests/ui/async-await/async-fn/higher-ranked-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-fn/impl-trait.rs2
-rw-r--r--tests/ui/async-await/async-fn/project.rs2
-rw-r--r--tests/ui/async-await/async-fn/simple.rs2
-rw-r--r--tests/ui/async-await/async-fn/sugar.rs2
-rw-r--r--tests/ui/async-await/coroutine-desc.rs1
-rw-r--r--tests/ui/async-await/coroutine-desc.stderr20
-rw-r--r--tests/ui/async-await/dyn/auxiliary/block-on.rs20
-rw-r--r--tests/ui/async-await/dyn/mut-is-pointer-like.rs40
-rw-r--r--tests/ui/async-await/dyn/mut-is-pointer-like.run.stdout1
-rw-r--r--tests/ui/async-await/dyn/mut-is-pointer-like.stderr11
-rw-r--r--tests/ui/async-await/dyn/works.rs32
-rw-r--r--tests/ui/async-await/dyn/works.run.stdout1
-rw-r--r--tests/ui/async-await/dyn/works.stderr11
-rw-r--r--tests/ui/async-await/dyn/wrong-size.rs23
-rw-r--r--tests/ui/async-await/dyn/wrong-size.stderr21
-rw-r--r--tests/ui/async-await/feature-async-closure.rs8
-rw-r--r--tests/ui/async-await/feature-async-closure.stderr14
-rw-r--r--tests/ui/async-await/inference_var_self_argument.stderr4
-rw-r--r--tests/ui/async-await/issue-66312.stderr4
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.rs1
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr20
-rw-r--r--tests/ui/async-await/issues/issue-62009-2.rs2
-rw-r--r--tests/ui/async-await/issues/issue-62009-2.stderr2
-rw-r--r--tests/ui/async-await/no-params-non-move-async-closure.rs2
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.fixed2
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.rs2
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.stderr6
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.rs2
-rw-r--r--tests/ui/async-await/track-caller/panic-track-caller.rs2
-rw-r--r--tests/ui/async-await/try-on-option-in-async.rs1
-rw-r--r--tests/ui/async-await/try-on-option-in-async.stderr6
-rw-r--r--tests/ui/closures/binder/async-closure-with-binder.rs1
-rw-r--r--tests/ui/closures/local-type-mix.rs2
-rw-r--r--tests/ui/closures/local-type-mix.stderr16
-rw-r--r--tests/ui/codegen/alias-uninit-value.rs26
-rw-r--r--tests/ui/coroutine/break-inside-coroutine-issue-124495.rs1
-rw-r--r--tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr14
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.rs27
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr8
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.rs2
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.stderr14
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.rs2
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.stderr18
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2021.fixed28
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2021.stderr52
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2024.stderr37
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.rs28
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs14
-rw-r--r--tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr48
-rw-r--r--tests/ui/feature-gates/feature-gate-async-trait-bounds.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr4
-rw-r--r--tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs (renamed from tests/ui/anonymous-higher-ranked-lifetime.rs)6
-rw-r--r--tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr (renamed from tests/ui/anonymous-higher-ranked-lifetime.stderr)44
-rw-r--r--tests/ui/impl-trait/in-trait/sized-rpits-dont-need-pointer-like.rs13
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed4
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs4
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr21
-rw-r--r--tests/ui/issues/auxiliary/issue-111011.rs2
-rw-r--r--tests/ui/issues/issue-56806.stderr4
-rw-r--r--tests/ui/layout/post-mono-layout-cycle-2.rs2
-rw-r--r--tests/ui/layout/post-mono-layout-cycle-2.stderr4
-rw-r--r--tests/ui/lifetimes/could-not-resolve-issue-121503.stderr2
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.rs1
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.stderr56
-rw-r--r--tests/ui/lint/unused/lint-unused-variables.rs1
-rw-r--r--tests/ui/lint/unused/lint-unused-variables.stderr24
-rw-r--r--tests/ui/lint/unused/unused-closure.rs1
-rw-r--r--tests/ui/lint/unused/unused-closure.stderr16
-rw-r--r--tests/ui/macros/stringify.rs1
-rw-r--r--tests/ui/methods/call_method_unknown_referent.rs48
-rw-r--r--tests/ui/methods/call_method_unknown_referent.stderr29
-rw-r--r--tests/ui/methods/call_method_unknown_referent2.rs24
-rw-r--r--tests/ui/mir/issue-68841.rs2
-rw-r--r--tests/ui/never_type/fallback-closure-ret.nofallback.stderr4
-rw-r--r--tests/ui/parser/as-precedence.rs18
-rw-r--r--tests/ui/parser/bad-name.stderr12
-rw-r--r--tests/ui/parser/circular_modules_main.stderr19
-rw-r--r--tests/ui/reachable/artificial-block.rs30
-rw-r--r--tests/ui/resolve/parse-error-resolve.rs7
-rw-r--r--tests/ui/resolve/parse-error-resolve.stderr22
-rw-r--r--tests/ui/resolve/parse_error.rs5
-rw-r--r--tests/ui/resolve/parse_error.stderr13
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs1
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr40
-rw-r--r--tests/ui/sanitizer/cfi/async-closures.rs1
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs64
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr70
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.default.stderr4
-rw-r--r--tests/ui/self/arbitrary-self-opaque.stderr4
-rw-r--r--tests/ui/self/arbitrary_self_types_by_value_reborrow.rs69
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_over_receiver.rs23
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr59
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_receiver.rs50
-rw-r--r--tests/ui/self/arbitrary_self_types_generic_receiver.stderr48
-rw-r--r--tests/ui/self/arbitrary_self_types_lifetime_elision.rs27
-rw-r--r--tests/ui/self/arbitrary_self_types_no_generics.rs32
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs38
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr39
-rw-r--r--tests/ui/self/arbitrary_self_types_recursive_receiver.rs32
-rw-r--r--tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs33
-rw-r--r--tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs31
-rw-r--r--tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs25
-rw-r--r--tests/ui/self/arbitrary_self_types_unshadowing.rs55
-rw-r--r--tests/ui/self/arbitrary_self_types_unshadowing.stderr105
-rw-r--r--tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs61
-rw-r--r--tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr122
-rw-r--r--tests/ui/self/conflicting_inner.rs38
-rw-r--r--tests/ui/self/conflicting_inner2.rs63
-rw-r--r--tests/ui/span/issue-27522.stderr4
-rw-r--r--tests/ui/structs/default-field-values-support.rs52
-rw-r--r--tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs1
-rw-r--r--tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr14
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr4
-rw-r--r--tests/ui/suggestions/method-missing-parentheses.rs1
-rw-r--r--tests/ui/suggestions/method-missing-parentheses.stderr8
-rw-r--r--tests/ui/suggestions/suggest-boxed-empty-block.fixed2
-rw-r--r--tests/ui/suggestions/suggest-boxed-empty-block.rs2
-rw-r--r--tests/ui/suggestions/suggest-boxed-empty-block.stderr4
-rw-r--r--tests/ui/suggestions/suggest-on-bare-closure-call.rs2
-rw-r--r--tests/ui/suggestions/suggest-on-bare-closure-call.stderr4
-rw-r--r--tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs22
-rw-r--r--tests/ui/traits/const-traits/effects/auxiliary/minicore.rs10
-rw-r--r--tests/ui/traits/issue-78372.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.next.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.next.stderr8
-rw-r--r--tests/ui/ufcs/ufcs-explicit-self-bad.stderr12
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.rs1
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout1
-rw-r--r--triagebot.toml11
746 files changed, 14814 insertions, 5420 deletions
diff --git a/.gitattributes b/.gitattributes
index a02c95fbd48..d29c15fe712 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4,10 +4,8 @@
 *.cpp rust
 *.h rust
 *.rs rust diff=rust
-*.fixed linguist-language=Rust -merge
-*.mir linguist-language=Rust -merge
-*.stderr -merge
-*.stdout -merge
+*.fixed linguist-language=Rust
+*.mir linguist-language=Rust
 src/etc/installer/gfx/* binary
 src/vendor/** -text
 Cargo.lock linguist-generated=false
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 650525a2f52..a219f1dc032 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2877,7 +2877,7 @@ pub enum ModKind {
     /// or with definition outlined to a separate file `mod foo;` and already loaded from it.
     /// The inner span is from the first token past `{` to the last token until `}`,
     /// or from the first to the last token in the loaded file.
-    Loaded(ThinVec<P<Item>>, Inline, ModSpans),
+    Loaded(ThinVec<P<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
     /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
     Unloaded,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2c09059fe19..0e299c60479 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1212,7 +1212,12 @@ impl WalkItemKind for ItemKind {
             ItemKind::Mod(safety, mod_kind) => {
                 visit_safety(vis, safety);
                 match mod_kind {
-                    ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => {
+                    ModKind::Loaded(
+                        items,
+                        _inline,
+                        ModSpans { inner_span, inject_use_span },
+                        _,
+                    ) => {
                         items.flat_map_in_place(|item| vis.flat_map_item(item));
                         vis.visit_span(inner_span);
                         vis.visit_span(inject_use_span);
diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs
index 61bb2468e79..f88b534a0c1 100644
--- a/compiler/rustc_ast/src/util/comments/tests.rs
+++ b/compiler/rustc_ast/src/util/comments/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use rustc_span::create_default_session_globals_then;
 
 use super::*;
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a7f7c37693a..a6232b6dfaf 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -380,7 +380,7 @@ impl WalkItemKind for ItemKind {
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _inline, _inner_span) => {
+                ModKind::Loaded(items, _inline, _inner_span, _) => {
                     walk_list!(visitor, visit_item, items);
                 }
                 ModKind::Unloaded => {}
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7d6c41992eb..d63131eacb5 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -238,7 +238,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 })
             }
             ItemKind::Mod(_, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _, spans) => {
+                ModKind::Loaded(items, _, spans, _) => {
                     hir::ItemKind::Mod(self.lower_mod(items, spans))
                 }
                 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 64e91c91e2c..290c2e52970 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1029,7 +1029,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
                 }
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
-                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
+                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
                     && !attr::contains_name(&item.attrs, sym::path)
                 {
                     self.check_mod_file_item_asciionly(item.ident);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index aa3b772efb1..61a710517ea 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -512,11 +512,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     );
     gate_all!(let_chains, "`let` expressions in this position are unstable");
     gate_all!(
-        async_closure,
-        "async closures are unstable",
-        "to use an async block, remove the `||`: `async {`"
-    );
-    gate_all!(
         async_trait_bounds,
         "`async` trait bounds are unstable",
         "use the desugared name of the async trait, such as `AsyncFn`"
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 452038bc328..dc4eab766c9 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -8,7 +8,10 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::fmt::DebugWithContext;
-use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
+use rustc_mir_dataflow::impls::{
+    EverInitializedPlaces, EverInitializedPlacesDomain, MaybeUninitializedPlaces,
+    MaybeUninitializedPlacesDomain,
+};
 use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects};
 use tracing::debug;
 
@@ -24,7 +27,7 @@ pub(crate) struct Borrowck<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
-    type Domain = BorrowckDomain<'a, 'tcx>;
+    type Domain = BorrowckDomain;
 
     const NAME: &'static str = "borrowck";
 
@@ -41,48 +44,48 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
         unreachable!();
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc);
-        self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc);
-        self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
+        self.borrows.apply_early_statement_effect(&mut state.borrows, stmt, loc);
+        self.uninits.apply_early_statement_effect(&mut state.uninits, stmt, loc);
+        self.ever_inits.apply_early_statement_effect(&mut state.ever_inits, stmt, loc);
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc);
-        self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc);
-        self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc);
+        self.borrows.apply_primary_statement_effect(&mut state.borrows, stmt, loc);
+        self.uninits.apply_primary_statement_effect(&mut state.uninits, stmt, loc);
+        self.ever_inits.apply_primary_statement_effect(&mut state.ever_inits, stmt, loc);
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
         state: &mut Self::Domain,
         term: &mir::Terminator<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc);
-        self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc);
-        self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
+        self.borrows.apply_early_terminator_effect(&mut state.borrows, term, loc);
+        self.uninits.apply_early_terminator_effect(&mut state.uninits, term, loc);
+        self.ever_inits.apply_early_terminator_effect(&mut state.ever_inits, term, loc);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         term: &'mir mir::Terminator<'tcx>,
         loc: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        self.borrows.apply_terminator_effect(&mut state.borrows, term, loc);
-        self.uninits.apply_terminator_effect(&mut state.uninits, term, loc);
-        self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc);
+        self.borrows.apply_primary_terminator_effect(&mut state.borrows, term, loc);
+        self.uninits.apply_primary_terminator_effect(&mut state.uninits, term, loc);
+        self.ever_inits.apply_primary_terminator_effect(&mut state.ever_inits, term, loc);
 
         // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this
         // analysis doesn't use.
@@ -110,14 +113,14 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
     }
 }
 
-impl JoinSemiLattice for BorrowckDomain<'_, '_> {
+impl JoinSemiLattice for BorrowckDomain {
     fn join(&mut self, _other: &Self) -> bool {
         // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
         unreachable!();
     }
 }
 
-impl<'tcx, C> DebugWithContext<C> for BorrowckDomain<'_, 'tcx>
+impl<'tcx, C> DebugWithContext<C> for BorrowckDomain
 where
     C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>,
 {
@@ -160,10 +163,10 @@ where
 
 /// The transient state of the dataflow analyses used by the borrow checker.
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct BorrowckDomain<'a, 'tcx> {
-    pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
-    pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
-    pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
+pub(crate) struct BorrowckDomain {
+    pub(crate) borrows: BorrowsDomain,
+    pub(crate) uninits: MaybeUninitializedPlacesDomain,
+    pub(crate) ever_inits: EverInitializedPlacesDomain,
 }
 
 rustc_index::newtype_index! {
@@ -503,7 +506,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
     /// That means they went out of a nonlexical scope
     fn kill_loans_out_of_scope_at_location(
         &self,
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         location: Location,
     ) {
         // NOTE: The state associated with a given `location`
@@ -518,14 +521,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
         // region, then setting that gen-bit will override any
         // potential kill introduced here.
         if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) {
-            trans.kill_all(indices.iter().copied());
+            state.kill_all(indices.iter().copied());
         }
     }
 
     /// Kill any borrows that conflict with `place`.
     fn kill_borrows_on_place(
         &self,
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         place: Place<'tcx>,
     ) {
         debug!("kill_borrows_on_place: place={:?}", place);
@@ -543,7 +546,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
         // `places_conflict` for every borrow.
         if place.projection.is_empty() {
             if !self.body.local_decls[place.local].is_ref_to_static() {
-                trans.kill_all(other_borrows_of_local);
+                state.kill_all(other_borrows_of_local);
             }
             return;
         }
@@ -562,10 +565,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
             )
         });
 
-        trans.kill_all(definitely_conflicting_borrows);
+        state.kill_all(definitely_conflicting_borrows);
     }
 }
 
+type BorrowsDomain = BitSet<BorrowIndex>;
+
 /// Forward dataflow computation of the set of borrows that are in scope at a particular location.
 /// - we gen the introduced loans
 /// - we kill loans on locals going out of (regular) scope
@@ -574,7 +579,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
 /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
 ///   `a.b.c` when `a` is overwritten.
 impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
-    type Domain = BitSet<BorrowIndex>;
+    type Domain = BorrowsDomain;
 
     const NAME: &'static str = "borrows";
 
@@ -588,18 +593,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
         // function execution, so this method has no effect.
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        self.kill_loans_out_of_scope_at_location(trans, location);
+        self.kill_loans_out_of_scope_at_location(state, location);
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -617,18 +622,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
                         panic!("could not find BorrowIndex for location {location:?}");
                     });
 
-                    trans.gen_(index);
+                    state.gen_(index);
                 }
 
                 // Make sure there are no remaining borrows for variables
                 // that are assigned over.
-                self.kill_borrows_on_place(trans, *lhs);
+                self.kill_borrows_on_place(state, *lhs);
             }
 
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(trans, Place::from(*local));
+                self.kill_borrows_on_place(state, Place::from(*local));
             }
 
             mir::StatementKind::FakeRead(..)
@@ -646,18 +651,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
         }
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _terminator: &mir::Terminator<'tcx>,
         location: Location,
     ) {
-        self.kill_loans_out_of_scope_at_location(trans, location);
+        self.kill_loans_out_of_scope_at_location(state, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         _location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
@@ -666,7 +671,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
                 if let mir::InlineAsmOperand::Out { place: Some(place), .. }
                 | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } = *op
                 {
-                    self.kill_borrows_on_place(trans, place);
+                    self.kill_borrows_on_place(state, place);
                 }
             }
         }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d7db92da18f..18b7984e90d 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_mir_dataflow::impls::{
 use rustc_mir_dataflow::move_paths::{
     InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
 };
-use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results};
+use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
 use rustc_session::lint::builtin::UNUSED_MUT;
 use rustc_span::{Span, Symbol};
 use smallvec::SmallVec;
@@ -426,14 +426,14 @@ fn get_flow_results<'a, 'tcx>(
         ever_inits: ever_inits.analysis,
     };
 
-    assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len());
-    assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len());
-    let entry_sets: EntrySets<'_, Borrowck<'_, '_>> =
-        itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets)
+    assert_eq!(borrows.entry_states.len(), uninits.entry_states.len());
+    assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len());
+    let entry_states: EntryStates<'_, Borrowck<'_, '_>> =
+        itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states)
             .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits })
             .collect();
 
-    Results { analysis, entry_sets }
+    Results { analysis, entry_states }
 }
 
 pub(crate) struct BorrowckInferCtxt<'tcx> {
@@ -600,10 +600,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
 impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         stmt: &'a Statement<'tcx>,
         location: Location,
     ) {
@@ -674,10 +674,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         }
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
@@ -787,10 +787,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         }
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
@@ -983,7 +983,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         place_span: (Place<'tcx>, Span),
         kind: (AccessDepth, ReadOrWrite),
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let (sd, rw) = kind;
 
@@ -1032,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         place_span: (Place<'tcx>, Span),
         sd: AccessDepth,
         rw: ReadOrWrite,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) -> bool {
         let mut error_reported = false;
 
@@ -1172,7 +1172,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         place_span: (Place<'tcx>, Span),
         kind: AccessDepth,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         // Write of P[i] or *P requires P init'd.
         self.check_if_assigned_path_is_moved(location, place_span, state);
@@ -1190,7 +1190,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (rvalue, span): (&'a Rvalue<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         match rvalue {
             &Rvalue::Ref(_ /*rgn*/, bk, place) => {
@@ -1448,7 +1448,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (operand, span): (&'a Operand<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         match *operand {
             Operand::Copy(place) => {
@@ -1568,12 +1568,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         }
     }
 
-    fn check_activations(
-        &mut self,
-        location: Location,
-        span: Span,
-        state: &BorrowckDomain<'a, 'tcx>,
-    ) {
+    fn check_activations(&mut self, location: Location, span: Span, state: &BorrowckDomain) {
         // Two-phase borrow support: For each activation that is newly
         // generated at this statement, check if it interferes with
         // another borrow.
@@ -1731,7 +1726,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let maybe_uninits = &state.uninits;
 
@@ -1836,7 +1831,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let maybe_uninits = &state.uninits;
 
@@ -1935,7 +1930,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
@@ -2001,7 +1996,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
             location: Location,
             base: PlaceRef<'tcx>,
             span: Span,
-            state: &BorrowckDomain<'a, 'tcx>,
+            state: &BorrowckDomain,
         ) {
             // rust-lang/rust#21232: Until Rust allows reads from the
             // initialized parts of partially initialized structs, we
@@ -2092,7 +2087,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         (place, span): (Place<'tcx>, Span),
         kind: ReadOrWrite,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         location: Location,
     ) -> bool {
         debug!(
@@ -2206,18 +2201,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         }
     }
 
-    fn is_local_ever_initialized(
-        &self,
-        local: Local,
-        state: &BorrowckDomain<'a, 'tcx>,
-    ) -> Option<InitIndex> {
+    fn is_local_ever_initialized(&self, local: Local, state: &BorrowckDomain) -> Option<InitIndex> {
         let mpi = self.move_data.rev_lookup.find_local(local)?;
         let ii = &self.move_data.init_path_map[mpi];
         ii.into_iter().find(|&&index| state.ever_inits.contains(index)).copied()
     }
 
     /// Adds the place into the used mutable variables set
-    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain<'a, 'tcx>) {
+    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain) {
         match root_place {
             RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index b2048c534a4..e7ff65e08f9 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -141,8 +141,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
-            item.kind
+        if let ast::ItemKind::Mod(
+            _,
+            ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
+        ) = item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
             walk_item_kind(
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index a1f9eab10e7..415f8affab9 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -867,6 +867,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         template_str.push_str("\n.popsection");
         self.context.add_top_level_asm(None, &template_str);
     }
+
+    fn mangled_name(&self, instance: Instance<'tcx>) -> String {
+        // TODO(@Amanieu): Additional mangling is needed on
+        // some targets to add a leading underscore (Mach-O)
+        // or byte count suffixes (x86 Windows).
+        self.tcx.symbol_name(instance).name.to_string()
+    }
 }
 
 fn modifier_to_gcc(
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index d1804cb49ad..3722d4350a2 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -442,6 +442,14 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
             );
         }
     }
+
+    fn mangled_name(&self, instance: Instance<'tcx>) -> String {
+        let llval = self.get_fn(instance);
+        llvm::build_string(|s| unsafe {
+            llvm::LLVMRustGetMangledName(llval, s);
+        })
+        .expect("symbol is not valid UTF-8")
+    }
 }
 
 pub(crate) fn inline_asm_call<'ll>(
@@ -504,14 +512,13 @@ pub(crate) fn inline_asm_call<'ll>(
             let key = "srcloc";
             let kind = llvm::LLVMGetMDKindIDInContext(
                 bx.llcx,
-                key.as_ptr() as *const c_char,
+                key.as_ptr().cast::<c_char>(),
                 key.len() as c_uint,
             );
 
-            // srcloc contains one integer for each line of assembly code.
-            // Unfortunately this isn't enough to encode a full span so instead
-            // we just encode the start position of each line.
-            // FIXME: Figure out a way to pass the entire line spans.
+            // `srcloc` contains one 64-bit integer for each line of assembly code,
+            // where the lower 32 bits hold the lo byte position and the upper 32 bits
+            // hold the hi byte position.
             let mut srcloc = vec![];
             if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
                 // LLVM inserts an extra line to add the ".intel_syntax", so add
@@ -521,13 +528,13 @@ pub(crate) fn inline_asm_call<'ll>(
                 // due to the asm template string coming from a macro. LLVM will
                 // default to the first srcloc for lines that don't have an
                 // associated srcloc.
-                srcloc.push(llvm::LLVMValueAsMetadata(bx.const_i32(0)));
+                srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
             }
-            srcloc.extend(
-                line_spans
-                    .iter()
-                    .map(|span| llvm::LLVMValueAsMetadata(bx.const_i32(span.lo().to_u32() as i32))),
-            );
+            srcloc.extend(line_spans.iter().map(|span| {
+                llvm::LLVMValueAsMetadata(bx.const_u64(
+                    u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
+                ))
+            }));
             let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
             let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
             llvm::LLVMSetMetadata(call, kind, md);
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index cb958c1d4d7..5552a241060 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -395,17 +395,9 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
         to_add.push(MemoryEffects::None.create_attr(cx.llcx));
     }
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-        to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
-        // HACK(jubilee): "indirect branch tracking" works by attaching prologues to functions.
-        // And it is a module-level attribute, so the alternative is pulling naked functions into
-        // new LLVM modules. Otherwise LLVM's "naked" functions come with endbr prefixes per
-        // https://github.com/rust-lang/rust/issues/98768
-        to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
-        if llvm_util::get_version() < (19, 0, 0) {
-            // Prior to LLVM 19, branch-target-enforcement was disabled by setting the attribute to
-            // the string "false". Now it is disabled by absence of the attribute.
-            to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
-        }
+        // do nothing; a naked function is converted into an extern function
+        // and a global assembly block. LLVM's support for naked functions is
+        // not used.
     } else {
         // Do not set sanitizer attributes for naked functions.
         to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index bde6668929c..66ca4e2b473 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -25,8 +25,8 @@ use rustc_session::Session;
 use rustc_session::config::{
     self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
 };
-use rustc_span::InnerSpan;
 use rustc_span::symbol::sym;
+use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext};
 use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
 use tracing::debug;
 
@@ -415,21 +415,32 @@ fn report_inline_asm(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
     msg: String,
     level: llvm::DiagnosticLevel,
-    mut cookie: u64,
+    cookie: u64,
     source: Option<(String, Vec<InnerSpan>)>,
 ) {
     // In LTO build we may get srcloc values from other crates which are invalid
     // since they use a different source map. To be safe we just suppress these
     // in LTO builds.
-    if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
-        cookie = 0;
-    }
+    let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
+        SpanData::default()
+    } else {
+        let lo = BytePos::from_u32(cookie as u32);
+        let hi = BytePos::from_u32((cookie >> 32) as u32);
+        SpanData {
+            lo,
+            // LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
+            hi: if hi.to_u32() != 0 { hi } else { lo },
+            ctxt: SyntaxContext::root(),
+            parent: None,
+        }
+    };
     let level = match level {
         llvm::DiagnosticLevel::Error => Level::Error,
         llvm::DiagnosticLevel::Warning => Level::Warning,
         llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
     };
-    cgcx.diag_emitter.inline_asm_error(cookie.try_into().unwrap(), msg, level, source);
+    let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
+    cgcx.diag_emitter.inline_asm_error(span, msg, level, source);
 }
 
 unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index e0506c0c5fd..c602d99ff9d 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -164,6 +164,11 @@ pub(crate) unsafe fn create_module<'ll>(
             // See https://github.com/llvm/llvm-project/pull/118004
             target_data_layout = target_data_layout.replace("-i128:128", "");
         }
+        if sess.target.arch.starts_with("wasm32") || sess.target.arch.starts_with("wasm64") {
+            // LLVM 20 updates the wasm(32|64) layout to correctly align 128 bit integers to 128 bit.
+            // See https://github.com/llvm/llvm-project/pull/119204
+            target_data_layout = target_data_layout.replace("-i128:128", "");
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
index a6e07ea2a60..1f133141c18 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
@@ -152,6 +152,34 @@ impl CoverageSpan {
     }
 }
 
+/// Holds tables of the various region types in one struct.
+///
+/// Don't pass this struct across FFI; pass the individual region tables as
+/// pointer/length pairs instead.
+///
+/// Each field name has a `_regions` suffix for improved readability after
+/// exhaustive destructing, which ensures that all region types are handled.
+#[derive(Clone, Debug, Default)]
+pub(crate) struct Regions {
+    pub(crate) code_regions: Vec<CodeRegion>,
+    pub(crate) branch_regions: Vec<BranchRegion>,
+    pub(crate) mcdc_branch_regions: Vec<MCDCBranchRegion>,
+    pub(crate) mcdc_decision_regions: Vec<MCDCDecisionRegion>,
+}
+
+impl Regions {
+    /// Returns true if none of this structure's tables contain any regions.
+    pub(crate) fn has_no_regions(&self) -> bool {
+        let Self { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
+            self;
+
+        code_regions.is_empty()
+            && branch_regions.is_empty()
+            && mcdc_branch_regions.is_empty()
+            && mcdc_decision_regions.is_empty()
+    }
+}
+
 /// Must match the layout of `LLVMRustCoverageCodeRegion`.
 #[derive(Clone, Debug)]
 #[repr(C)]
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
index 99c2d12b261..086cf1f44a0 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
@@ -62,11 +62,10 @@ pub(crate) fn write_filenames_to_buffer<'a>(
 pub(crate) fn write_function_mappings_to_buffer(
     virtual_file_mapping: &[u32],
     expressions: &[ffi::CounterExpression],
-    code_regions: &[ffi::CodeRegion],
-    branch_regions: &[ffi::BranchRegion],
-    mcdc_branch_regions: &[ffi::MCDCBranchRegion],
-    mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
+    regions: &ffi::Regions,
 ) -> Vec<u8> {
+    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
+        regions;
     llvm::build_byte_buffer(|buffer| unsafe {
         llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer(
             virtual_file_mapping.as_ptr(),
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index a6c3caf9e2b..a573a37beb3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,4 +1,3 @@
-use std::ffi::CString;
 use std::iter;
 
 use itertools::Itertools as _;
@@ -9,21 +8,22 @@ use rustc_codegen_ssa::traits::{
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::IndexVec;
-use rustc_middle::mir::coverage::MappingKind;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_session::RemapFileNameExt;
 use rustc_session::config::RemapPathScopeComponents;
 use rustc_span::def_id::DefIdSet;
 use rustc_span::{Span, Symbol};
-use rustc_target::spec::HasTargetSpec;
 use tracing::debug;
 
 use crate::common::CodegenCx;
+use crate::coverageinfo::llvm_cov;
 use crate::coverageinfo::map_data::FunctionCoverage;
-use crate::coverageinfo::{ffi, llvm_cov};
+use crate::coverageinfo::mapgen::covfun::prepare_covfun_record;
 use crate::llvm;
 
+mod covfun;
+
 /// Generates and exports the coverage map, which is embedded in special
 /// linker sections in the final binary.
 ///
@@ -80,47 +80,28 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
     let filenames_val = cx.const_bytes(&filenames_buffer);
     let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer);
 
-    // Generate the coverage map header, which contains the filenames used by
-    // this CGU's coverage mappings, and store it in a well-known global.
-    generate_covmap_record(cx, covmap_version, filenames_size, filenames_val);
-
     let mut unused_function_names = Vec::new();
 
-    // Encode coverage mappings and generate function records
-    for (instance, function_coverage) in function_coverage_map {
-        debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance);
-
-        let mangled_function_name = tcx.symbol_name(instance).name;
-        let source_hash = function_coverage.source_hash();
-        let is_used = function_coverage.is_used();
-
-        let coverage_mapping_buffer =
-            encode_mappings_for_function(tcx, &global_file_table, &function_coverage);
-
-        if coverage_mapping_buffer.is_empty() {
-            if function_coverage.is_used() {
-                bug!(
-                    "A used function should have had coverage mapping data but did not: {}",
-                    mangled_function_name
-                );
-            } else {
-                debug!("unused function had no coverage mapping data: {}", mangled_function_name);
-                continue;
-            }
-        }
+    let covfun_records = function_coverage_map
+        .into_iter()
+        .filter_map(|(instance, function_coverage)| {
+            prepare_covfun_record(tcx, &global_file_table, instance, &function_coverage)
+        })
+        .collect::<Vec<_>>();
+
+    // If there are no covfun records for this CGU, don't generate a covmap record.
+    // Emitting a covmap record without any covfun records causes `llvm-cov` to
+    // fail when generating coverage reports, and if there are no covfun records
+    // then the covmap record isn't useful anyway.
+    // This should prevent a repeat of <https://github.com/rust-lang/rust/issues/133606>.
+    if covfun_records.is_empty() {
+        return;
+    }
 
-        if !is_used {
-            unused_function_names.push(mangled_function_name);
-        }
+    for covfun in &covfun_records {
+        unused_function_names.extend(covfun.mangled_function_name_if_unused());
 
-        generate_covfun_record(
-            cx,
-            mangled_function_name,
-            source_hash,
-            filenames_ref,
-            coverage_mapping_buffer,
-            is_used,
-        );
+        covfun::generate_covfun_record(cx, filenames_ref, covfun)
     }
 
     // For unused functions, we need to take their mangled names and store them
@@ -141,6 +122,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
         llvm::set_initializer(array, initializer);
     }
+
+    // Generate the coverage map header, which contains the filenames used by
+    // this CGU's coverage mappings, and store it in a well-known global.
+    // (This is skipped if we returned early due to having no covfun records.)
+    generate_covmap_record(cx, covmap_version, filenames_size, filenames_val);
 }
 
 /// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
@@ -208,7 +194,7 @@ rustc_index::newtype_index! {
 
 /// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU)
 /// file IDs.
-#[derive(Default)]
+#[derive(Debug, Default)]
 struct VirtualFileMapping {
     local_to_global: IndexVec<LocalFileId, GlobalFileId>,
     global_to_local: FxIndexMap<GlobalFileId, LocalFileId>,
@@ -222,10 +208,10 @@ impl VirtualFileMapping {
             .or_insert_with(|| self.local_to_global.push(global_file_id))
     }
 
-    fn into_vec(self) -> Vec<u32> {
-        // This conversion should be optimized away to ~zero overhead.
-        // In any case, it's probably not hot enough to worry about.
-        self.local_to_global.into_iter().map(|global| global.as_u32()).collect()
+    fn to_vec(&self) -> Vec<u32> {
+        // This clone could be avoided by transmuting `&[GlobalFileId]` to `&[u32]`,
+        // but it isn't hot or expensive enough to justify the extra unsafety.
+        self.local_to_global.iter().map(|&global| GlobalFileId::as_u32(global)).collect()
     }
 }
 
@@ -236,83 +222,6 @@ fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol {
     Symbol::intern(&name)
 }
 
-/// Using the expressions and counter regions collected for a single function,
-/// generate the variable-sized payload of its corresponding `__llvm_covfun`
-/// entry. The payload is returned as a vector of bytes.
-///
-/// Newly-encountered filenames will be added to the global file table.
-fn encode_mappings_for_function(
-    tcx: TyCtxt<'_>,
-    global_file_table: &GlobalFileTable,
-    function_coverage: &FunctionCoverage<'_>,
-) -> Vec<u8> {
-    let counter_regions = function_coverage.counter_regions();
-    if counter_regions.is_empty() {
-        return Vec::new();
-    }
-
-    let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
-
-    let mut virtual_file_mapping = VirtualFileMapping::default();
-    let mut code_regions = vec![];
-    let mut branch_regions = vec![];
-    let mut mcdc_branch_regions = vec![];
-    let mut mcdc_decision_regions = vec![];
-
-    // Currently a function's mappings must all be in the same file as its body span.
-    let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span);
-
-    // Look up the global file ID for that filename.
-    let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
-
-    // Associate that global file ID with a local file ID for this function.
-    let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id);
-    debug!("  file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'");
-
-    // For each counter/region pair in this function+file, convert it to a
-    // form suitable for FFI.
-    for (mapping_kind, region) in counter_regions {
-        debug!("Adding counter {mapping_kind:?} to map for {region:?}");
-        let span = ffi::CoverageSpan::from_source_region(local_file_id, region);
-        match mapping_kind {
-            MappingKind::Code(term) => {
-                code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
-            }
-            MappingKind::Branch { true_term, false_term } => {
-                branch_regions.push(ffi::BranchRegion {
-                    span,
-                    true_counter: ffi::Counter::from_term(true_term),
-                    false_counter: ffi::Counter::from_term(false_term),
-                });
-            }
-            MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
-                mcdc_branch_regions.push(ffi::MCDCBranchRegion {
-                    span,
-                    true_counter: ffi::Counter::from_term(true_term),
-                    false_counter: ffi::Counter::from_term(false_term),
-                    mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params),
-                });
-            }
-            MappingKind::MCDCDecision(mcdc_decision_params) => {
-                mcdc_decision_regions.push(ffi::MCDCDecisionRegion {
-                    span,
-                    mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params),
-                });
-            }
-        }
-    }
-
-    // Encode the function's coverage mappings into a buffer.
-    llvm_cov::write_function_mappings_to_buffer(
-        &virtual_file_mapping.into_vec(),
-        &expressions,
-        &code_regions,
-        &branch_regions,
-        &mcdc_branch_regions,
-        &mcdc_decision_regions,
-    )
-}
-
 /// Generates the contents of the covmap record for this CGU, which mostly
 /// consists of a header and a list of filenames. The record is then stored
 /// as a global variable in the `__llvm_covmap` section.
@@ -350,61 +259,6 @@ fn generate_covmap_record<'ll>(
     cx.add_used_global(llglobal);
 }
 
-/// Generates the contents of the covfun record for this function, which
-/// contains the function's coverage mapping data. The record is then stored
-/// as a global variable in the `__llvm_covfun` section.
-fn generate_covfun_record(
-    cx: &CodegenCx<'_, '_>,
-    mangled_function_name: &str,
-    source_hash: u64,
-    filenames_ref: u64,
-    coverage_mapping_buffer: Vec<u8>,
-    is_used: bool,
-) {
-    // Concatenate the encoded coverage mappings
-    let coverage_mapping_size = coverage_mapping_buffer.len();
-    let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);
-
-    let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes());
-    let func_name_hash_val = cx.const_u64(func_name_hash);
-    let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
-    let source_hash_val = cx.const_u64(source_hash);
-    let filenames_ref_val = cx.const_u64(filenames_ref);
-    let func_record_val = cx.const_struct(
-        &[
-            func_name_hash_val,
-            coverage_mapping_size_val,
-            source_hash_val,
-            filenames_ref_val,
-            coverage_mapping_val,
-        ],
-        /*packed=*/ true,
-    );
-
-    // Choose a variable name to hold this function's covfun data.
-    // Functions that are used have a suffix ("u") to distinguish them from
-    // unused copies of the same function (from different CGUs), so that if a
-    // linker sees both it won't discard the used copy's data.
-    let func_record_var_name =
-        CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }))
-            .unwrap();
-    debug!("function record var name: {:?}", func_record_var_name);
-
-    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
-    llvm::set_initializer(llglobal, func_record_val);
-    llvm::set_global_constant(llglobal, true);
-    llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
-    llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
-    llvm::set_section(llglobal, cx.covfun_section_name());
-    // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
-    // <https://llvm.org/docs/CoverageMappingFormat.html>
-    llvm::set_alignment(llglobal, Align::EIGHT);
-    if cx.target_spec().supports_comdat() {
-        llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
-    }
-    cx.add_used_global(llglobal);
-}
-
 /// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
 /// But since we don't want unused functions to disappear from coverage reports, we also scan for
 /// functions that were instrumented but are not participating in codegen.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
new file mode 100644
index 00000000000..530e6827f55
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -0,0 +1,200 @@
+//! For each function that was instrumented for coverage, we need to embed its
+//! corresponding coverage mapping metadata inside the `__llvm_covfun`[^win]
+//! linker section of the final binary.
+//!
+//! [^win]: On Windows the section name is `.lcovfun`.
+
+use std::ffi::CString;
+
+use rustc_abi::Align;
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
+};
+use rustc_middle::bug;
+use rustc_middle::mir::coverage::MappingKind;
+use rustc_middle::ty::{Instance, TyCtxt};
+use rustc_target::spec::HasTargetSpec;
+use tracing::debug;
+
+use crate::common::CodegenCx;
+use crate::coverageinfo::map_data::FunctionCoverage;
+use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, span_file_name};
+use crate::coverageinfo::{ffi, llvm_cov};
+use crate::llvm;
+
+/// Intermediate coverage metadata for a single function, used to help build
+/// the final record that will be embedded in the `__llvm_covfun` section.
+#[derive(Debug)]
+pub(crate) struct CovfunRecord<'tcx> {
+    mangled_function_name: &'tcx str,
+    source_hash: u64,
+    is_used: bool,
+
+    virtual_file_mapping: VirtualFileMapping,
+    expressions: Vec<ffi::CounterExpression>,
+    regions: ffi::Regions,
+}
+
+impl<'tcx> CovfunRecord<'tcx> {
+    /// FIXME(Zalathar): Make this the responsibility of the code that determines
+    /// which functions are unused.
+    pub(crate) fn mangled_function_name_if_unused(&self) -> Option<&'tcx str> {
+        (!self.is_used).then_some(self.mangled_function_name)
+    }
+}
+
+pub(crate) fn prepare_covfun_record<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    global_file_table: &GlobalFileTable,
+    instance: Instance<'tcx>,
+    function_coverage: &FunctionCoverage<'tcx>,
+) -> Option<CovfunRecord<'tcx>> {
+    let mut covfun = CovfunRecord {
+        mangled_function_name: tcx.symbol_name(instance).name,
+        source_hash: function_coverage.source_hash(),
+        is_used: function_coverage.is_used(),
+        virtual_file_mapping: VirtualFileMapping::default(),
+        expressions: function_coverage.counter_expressions().collect::<Vec<_>>(),
+        regions: ffi::Regions::default(),
+    };
+
+    fill_region_tables(tcx, global_file_table, function_coverage, &mut covfun);
+
+    if covfun.regions.has_no_regions() {
+        if covfun.is_used {
+            bug!("a used function should have had coverage mapping data but did not: {covfun:?}");
+        } else {
+            debug!(?covfun, "unused function had no coverage mapping data");
+            return None;
+        }
+    }
+
+    Some(covfun)
+}
+
+/// Populates the mapping region tables in the current function's covfun record.
+fn fill_region_tables<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    global_file_table: &GlobalFileTable,
+    function_coverage: &FunctionCoverage<'tcx>,
+    covfun: &mut CovfunRecord<'tcx>,
+) {
+    let counter_regions = function_coverage.counter_regions();
+    if counter_regions.is_empty() {
+        return;
+    }
+
+    // Currently a function's mappings must all be in the same file as its body span.
+    let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span);
+
+    // Look up the global file ID for that filename.
+    let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
+
+    // Associate that global file ID with a local file ID for this function.
+    let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
+    debug!("  file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'");
+
+    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
+        &mut covfun.regions;
+
+    // For each counter/region pair in this function+file, convert it to a
+    // form suitable for FFI.
+    for (mapping_kind, region) in counter_regions {
+        debug!("Adding counter {mapping_kind:?} to map for {region:?}");
+        let span = ffi::CoverageSpan::from_source_region(local_file_id, region);
+        match mapping_kind {
+            MappingKind::Code(term) => {
+                code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
+            }
+            MappingKind::Branch { true_term, false_term } => {
+                branch_regions.push(ffi::BranchRegion {
+                    span,
+                    true_counter: ffi::Counter::from_term(true_term),
+                    false_counter: ffi::Counter::from_term(false_term),
+                });
+            }
+            MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
+                mcdc_branch_regions.push(ffi::MCDCBranchRegion {
+                    span,
+                    true_counter: ffi::Counter::from_term(true_term),
+                    false_counter: ffi::Counter::from_term(false_term),
+                    mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params),
+                });
+            }
+            MappingKind::MCDCDecision(mcdc_decision_params) => {
+                mcdc_decision_regions.push(ffi::MCDCDecisionRegion {
+                    span,
+                    mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params),
+                });
+            }
+        }
+    }
+}
+
+/// Generates the contents of the covfun record for this function, which
+/// contains the function's coverage mapping data. The record is then stored
+/// as a global variable in the `__llvm_covfun` section.
+pub(crate) fn generate_covfun_record<'tcx>(
+    cx: &CodegenCx<'_, 'tcx>,
+    filenames_ref: u64,
+    covfun: &CovfunRecord<'tcx>,
+) {
+    let &CovfunRecord {
+        mangled_function_name,
+        source_hash,
+        is_used,
+        ref virtual_file_mapping,
+        ref expressions,
+        ref regions,
+    } = covfun;
+
+    // Encode the function's coverage mappings into a buffer.
+    let coverage_mapping_buffer = llvm_cov::write_function_mappings_to_buffer(
+        &virtual_file_mapping.to_vec(),
+        expressions,
+        regions,
+    );
+
+    // Concatenate the encoded coverage mappings
+    let coverage_mapping_size = coverage_mapping_buffer.len();
+    let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);
+
+    let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes());
+    let func_name_hash_val = cx.const_u64(func_name_hash);
+    let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
+    let source_hash_val = cx.const_u64(source_hash);
+    let filenames_ref_val = cx.const_u64(filenames_ref);
+    let func_record_val = cx.const_struct(
+        &[
+            func_name_hash_val,
+            coverage_mapping_size_val,
+            source_hash_val,
+            filenames_ref_val,
+            coverage_mapping_val,
+        ],
+        /*packed=*/ true,
+    );
+
+    // Choose a variable name to hold this function's covfun data.
+    // Functions that are used have a suffix ("u") to distinguish them from
+    // unused copies of the same function (from different CGUs), so that if a
+    // linker sees both it won't discard the used copy's data.
+    let func_record_var_name =
+        CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }))
+            .unwrap();
+    debug!("function record var name: {:?}", func_record_var_name);
+
+    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
+    llvm::set_initializer(llglobal, func_record_val);
+    llvm::set_global_constant(llglobal, true);
+    llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
+    llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
+    llvm::set_section(llglobal, cx.covfun_section_name());
+    // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
+    // <https://llvm.org/docs/CoverageMappingFormat.html>
+    llvm::set_alignment(llglobal, Align::EIGHT);
+    if cx.target_spec().supports_comdat() {
+        llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
+    }
+    cx.add_used_global(llglobal);
+}
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
index a4cb5a25d1b..11043b664f5 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -151,7 +151,7 @@ impl InlineAsmDiagnostic {
             unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
         InlineAsmDiagnostic {
             level: smdiag.level,
-            cookie: cookie.into(),
+            cookie,
             message: smdiag.message,
             source: smdiag.source,
         }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index b1ace0033ba..d62632d1431 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -17,7 +17,9 @@ use super::debuginfo::{
     DebugEmissionKind, DebugNameTableKind,
 };
 
-pub type Bool = c_uint;
+/// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
+/// which has a different ABI from Rust or C++ `bool`.
+pub type Bool = c_int;
 
 pub const True: Bool = 1 as Bool;
 pub const False: Bool = 0 as Bool;
@@ -2317,7 +2319,7 @@ unsafe extern "C" {
 
     pub fn LLVMRustGetSMDiagnostic<'a>(
         DI: &'a DiagnosticInfo,
-        cookie_out: &mut c_uint,
+        cookie_out: &mut u64,
     ) -> &'a SMDiagnostic;
 
     pub fn LLVMRustUnpackSMDiagnostic(
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 05dfbd40a0a..4c5eb98e890 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1694,6 +1694,8 @@ impl<'a> Linker for AixLinker<'a> {
 
     fn pgo_gen(&mut self) {
         self.link_arg("-bdbg:namedsects:ss");
+        self.link_arg("-u");
+        self.link_arg("__llvm_profile_runtime");
     }
 
     fn control_flow_guard(&mut self) {}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 90d48d6ee7e..501f7517919 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -34,7 +34,7 @@ use rustc_session::config::{
 };
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
-use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
+use rustc_span::{FileName, InnerSpan, Span, SpanData};
 use rustc_target::spec::{MergeFunctions, SanitizerSet};
 use tracing::debug;
 
@@ -1837,7 +1837,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
 
 enum SharedEmitterMessage {
     Diagnostic(Diagnostic),
-    InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
+    InlineAsmError(SpanData, String, Level, Option<(String, Vec<InnerSpan>)>),
     Fatal(String),
 }
 
@@ -1859,12 +1859,12 @@ impl SharedEmitter {
 
     pub fn inline_asm_error(
         &self,
-        cookie: u32,
+        span: SpanData,
         msg: String,
         level: Level,
         source: Option<(String, Vec<InnerSpan>)>,
     ) {
-        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
+        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source)));
     }
 
     fn fatal(&self, msg: &str) {
@@ -1953,17 +1953,12 @@ impl SharedEmitterMain {
                     dcx.emit_diagnostic(d);
                     sess.dcx().abort_if_errors();
                 }
-                Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
+                Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => {
                     assert_matches!(level, Level::Error | Level::Warning | Level::Note);
-                    let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
                     let mut err = Diag::<()>::new(sess.dcx(), level, msg);
-
-                    // If the cookie is 0 then we don't have span information.
-                    if cookie != 0 {
-                        let pos = BytePos::from_u32(cookie);
-                        let span = Span::with_root_ctxt(pos, pos);
-                        err.span(span);
-                    };
+                    if !span.is_dummy() {
+                        err.span(span.span());
+                    }
 
                     // Point to the generated assembly if it is available.
                     if let Some((buffer, spans)) = source {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 11744eabab0..ab2d24e8d2d 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -550,6 +550,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         }
     });
 
+    // naked function MUST NOT be inlined! This attribute is required for the rust compiler itself,
+    // but not for the code generation backend because at that point the naked function will just be
+    // a declaration, with a definition provided in global assembly.
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+        codegen_fn_attrs.inline = InlineAttr::Never;
+    }
+
     codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
         if !attr.has_name(sym::optimize) {
             return ia;
@@ -634,10 +641,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         }
     }
 
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-        codegen_fn_attrs.inline = InlineAttr::Never;
-    }
-
     // Weak lang items have the same semantics as "std internal" symbols in the
     // sense that they're preserved through all our LTO passes and only
     // strippable by the linker.
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 0cbc5c45736..62f69af3f2f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -20,6 +20,7 @@ mod coverageinfo;
 pub mod debuginfo;
 mod intrinsic;
 mod locals;
+mod naked_asm;
 pub mod operand;
 pub mod place;
 mod rvalue;
@@ -176,6 +177,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
     debug!("fn_abi: {:?}", fn_abi);
 
+    if cx.tcx().codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
+        crate::mir::naked_asm::codegen_naked_asm::<Bx>(cx, &mir, instance);
+        return;
+    }
+
     let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir);
 
     let start_llbb = Bx::append_block(cx, llfn, "start");
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
new file mode 100644
index 00000000000..c08758a9796
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -0,0 +1,266 @@
+use rustc_attr::InstructionSetAttr;
+use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
+use rustc_middle::mir::{Body, InlineAsmOperand};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf};
+use rustc_middle::ty::{Instance, TyCtxt};
+use rustc_middle::{bug, ty};
+use rustc_span::sym;
+
+use crate::common;
+use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
+
+pub(crate) fn codegen_naked_asm<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx,
+    mir: &Body<'tcx>,
+    instance: Instance<'tcx>,
+) {
+    let rustc_middle::mir::TerminatorKind::InlineAsm {
+        asm_macro: _,
+        template,
+        ref operands,
+        options,
+        line_spans,
+        targets: _,
+        unwind: _,
+    } = mir.basic_blocks.iter().next().unwrap().terminator().kind
+    else {
+        bug!("#[naked] functions should always terminate with an asm! block")
+    };
+
+    let operands: Vec<_> =
+        operands.iter().map(|op| inline_to_global_operand::<Bx>(cx, instance, op)).collect();
+
+    let item_data = cx.codegen_unit().items().get(&MonoItem::Fn(instance)).unwrap();
+    let name = cx.mangled_name(instance);
+    let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data);
+
+    let mut template_vec = Vec::new();
+    template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin.into()));
+    template_vec.extend(template.iter().cloned());
+    template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(end.into()));
+
+    cx.codegen_global_asm(&template_vec, &operands, options, line_spans);
+}
+
+fn inline_to_global_operand<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    cx: &'a Bx::CodegenCx,
+    instance: Instance<'tcx>,
+    op: &InlineAsmOperand<'tcx>,
+) -> GlobalAsmOperandRef<'tcx> {
+    match op {
+        InlineAsmOperand::Const { value } => {
+            let const_value = instance
+                .instantiate_mir_and_normalize_erasing_regions(
+                    cx.tcx(),
+                    cx.typing_env(),
+                    ty::EarlyBinder::bind(value.const_),
+                )
+                .eval(cx.tcx(), cx.typing_env(), value.span)
+                .expect("erroneous constant missed by mono item collection");
+
+            let mono_type = instance.instantiate_mir_and_normalize_erasing_regions(
+                cx.tcx(),
+                cx.typing_env(),
+                ty::EarlyBinder::bind(value.ty()),
+            );
+
+            let string = common::asm_const_to_str(
+                cx.tcx(),
+                value.span,
+                const_value,
+                cx.layout_of(mono_type),
+            );
+
+            GlobalAsmOperandRef::Const { string }
+        }
+        InlineAsmOperand::SymFn { value } => {
+            let mono_type = instance.instantiate_mir_and_normalize_erasing_regions(
+                cx.tcx(),
+                cx.typing_env(),
+                ty::EarlyBinder::bind(value.ty()),
+            );
+
+            let instance = match mono_type.kind() {
+                &ty::FnDef(def_id, args) => Instance::new(def_id, args),
+                _ => bug!("asm sym is not a function"),
+            };
+
+            GlobalAsmOperandRef::SymFn { instance }
+        }
+        InlineAsmOperand::SymStatic { def_id } => {
+            GlobalAsmOperandRef::SymStatic { def_id: *def_id }
+        }
+        InlineAsmOperand::In { .. }
+        | InlineAsmOperand::Out { .. }
+        | InlineAsmOperand::InOut { .. }
+        | InlineAsmOperand::Label { .. } => {
+            bug!("invalid operand type for naked_asm!")
+        }
+    }
+}
+
+enum AsmBinaryFormat {
+    Elf,
+    Macho,
+    Coff,
+}
+
+impl AsmBinaryFormat {
+    fn from_target(target: &rustc_target::spec::Target) -> Self {
+        if target.is_like_windows {
+            Self::Coff
+        } else if target.is_like_osx {
+            Self::Macho
+        } else {
+            Self::Elf
+        }
+    }
+}
+
+fn prefix_and_suffix<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    asm_name: &str,
+    item_data: &MonoItemData,
+) -> (String, String) {
+    use std::fmt::Write;
+
+    let asm_binary_format = AsmBinaryFormat::from_target(&tcx.sess.target);
+
+    let is_arm = tcx.sess.target.arch == "arm";
+    let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode);
+
+    let attrs = tcx.codegen_fn_attrs(instance.def_id());
+    let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string());
+    let align = attrs.alignment.map(|a| a.bytes()).unwrap_or(4);
+
+    // See https://sourceware.org/binutils/docs/as/ARM-Directives.html for info on these directives.
+    // In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`.
+    let (arch_prefix, arch_suffix) = if is_arm {
+        (
+            match attrs.instruction_set {
+                None => match is_thumb {
+                    true => ".thumb\n.thumb_func",
+                    false => ".arm",
+                },
+                Some(InstructionSetAttr::ArmT32) => ".thumb\n.thumb_func",
+                Some(InstructionSetAttr::ArmA32) => ".arm",
+            },
+            match is_thumb {
+                true => ".thumb",
+                false => ".arm",
+            },
+        )
+    } else {
+        ("", "")
+    };
+
+    let emit_fatal = |msg| tcx.dcx().span_fatal(tcx.def_span(instance.def_id()), msg);
+
+    // see https://godbolt.org/z/cPK4sxKor.
+    let write_linkage = |w: &mut String| -> std::fmt::Result {
+        match item_data.linkage {
+            Linkage::External => {
+                writeln!(w, ".globl {asm_name}")?;
+            }
+            Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => {
+                match asm_binary_format {
+                    AsmBinaryFormat::Elf | AsmBinaryFormat::Coff => {
+                        writeln!(w, ".weak {asm_name}")?;
+                    }
+                    AsmBinaryFormat::Macho => {
+                        writeln!(w, ".globl {asm_name}")?;
+                        writeln!(w, ".weak_definition {asm_name}")?;
+                    }
+                }
+            }
+            Linkage::Internal | Linkage::Private => {
+                // write nothing
+            }
+            Linkage::Appending => emit_fatal("Only global variables can have appending linkage!"),
+            Linkage::Common => emit_fatal("Functions may not have common linkage"),
+            Linkage::AvailableExternally => {
+                // this would make the function equal an extern definition
+                emit_fatal("Functions may not have available_externally linkage")
+            }
+            Linkage::ExternalWeak => {
+                // FIXME: actually this causes a SIGILL in LLVM
+                emit_fatal("Functions may not have external weak linkage")
+            }
+        }
+
+        Ok(())
+    };
+
+    let mut begin = String::new();
+    let mut end = String::new();
+    match asm_binary_format {
+        AsmBinaryFormat::Elf => {
+            let section = link_section.unwrap_or(format!(".text.{asm_name}"));
+
+            let progbits = match is_arm {
+                true => "%progbits",
+                false => "@progbits",
+            };
+
+            let function = match is_arm {
+                true => "%function",
+                false => "@function",
+            };
+
+            writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap();
+            writeln!(begin, ".balign {align}").unwrap();
+            write_linkage(&mut begin).unwrap();
+            if let Visibility::Hidden = item_data.visibility {
+                writeln!(begin, ".hidden {asm_name}").unwrap();
+            }
+            writeln!(begin, ".type {asm_name}, {function}").unwrap();
+            if !arch_prefix.is_empty() {
+                writeln!(begin, "{}", arch_prefix).unwrap();
+            }
+            writeln!(begin, "{asm_name}:").unwrap();
+
+            writeln!(end).unwrap();
+            writeln!(end, ".size {asm_name}, . - {asm_name}").unwrap();
+            writeln!(end, ".popsection").unwrap();
+            if !arch_suffix.is_empty() {
+                writeln!(end, "{}", arch_suffix).unwrap();
+            }
+        }
+        AsmBinaryFormat::Macho => {
+            let section = link_section.unwrap_or("__TEXT,__text".to_string());
+            writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap();
+            writeln!(begin, ".balign {align}").unwrap();
+            write_linkage(&mut begin).unwrap();
+            if let Visibility::Hidden = item_data.visibility {
+                writeln!(begin, ".private_extern {asm_name}").unwrap();
+            }
+            writeln!(begin, "{asm_name}:").unwrap();
+
+            writeln!(end).unwrap();
+            writeln!(end, ".popsection").unwrap();
+            if !arch_suffix.is_empty() {
+                writeln!(end, "{}", arch_suffix).unwrap();
+            }
+        }
+        AsmBinaryFormat::Coff => {
+            let section = link_section.unwrap_or(format!(".text.{asm_name}"));
+            writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
+            writeln!(begin, ".balign {align}").unwrap();
+            write_linkage(&mut begin).unwrap();
+            writeln!(begin, ".def {asm_name}").unwrap();
+            writeln!(begin, ".scl 2").unwrap();
+            writeln!(begin, ".type 32").unwrap();
+            writeln!(begin, ".endef {asm_name}").unwrap();
+            writeln!(begin, "{asm_name}:").unwrap();
+
+            writeln!(end).unwrap();
+            writeln!(end, ".popsection").unwrap();
+            if !arch_suffix.is_empty() {
+                writeln!(end, "{}", arch_suffix).unwrap();
+            }
+        }
+    }
+
+    (begin, end)
+}
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 038c5857fac..6749bc63327 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -1,4 +1,5 @@
 use rustc_hir as hir;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
 use rustc_middle::ty::Instance;
@@ -135,7 +136,13 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
                 cx.predefine_static(def_id, linkage, visibility, symbol_name);
             }
             MonoItem::Fn(instance) => {
-                cx.predefine_fn(instance, linkage, visibility, symbol_name);
+                let attrs = cx.tcx().codegen_fn_attrs(instance.def_id());
+
+                if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+                    // do not define this function; it will become a global assembly block
+                } else {
+                    cx.predefine_fn(instance, linkage, visibility, symbol_name);
+                };
             }
             MonoItem::GlobalAsm(..) => {}
         }
diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs
index f4853da1156..7767bffbfbf 100644
--- a/compiler/rustc_codegen_ssa/src/traits/asm.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs
@@ -68,4 +68,11 @@ pub trait AsmCodegenMethods<'tcx> {
         options: InlineAsmOptions,
         line_spans: &[Span],
     );
+
+    /// The mangled name of this instance
+    ///
+    /// Additional mangling is used on
+    /// some targets to add a leading underscore (Mach-O)
+    /// or byte count suffixes (x86 Windows).
+    fn mangled_name(&self, instance: Instance<'tcx>) -> String;
 }
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 0f9a460ca1b..763c37a41af 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -329,7 +329,7 @@ where
         self.transfer_function(state).initialize_state();
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
@@ -338,7 +338,7 @@ where
         self.transfer_function(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 56325eaa1be..23683851799 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -249,10 +249,9 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
-            // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here.
             let new_instance = ty::Instance::expect_resolve(
                 *self.tcx,
-                ty::TypingEnv::fully_monomorphized(),
+                self.typing_env(),
                 const_def_id,
                 instance.args,
                 self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 0157e6c2125..2db6322ba06 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -297,6 +297,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
+        // Can use any typing env, since `bool` is always monomorphic.
         let layout = tcx
             .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
             .unwrap();
@@ -305,17 +306,18 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
+        // Can use any typing env, since `Ordering` is always monomorphic.
         let ty = tcx.ty_ordering_enum(None);
         let layout =
             tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
         Self::from_scalar(Scalar::from_i8(c as i8), layout)
     }
 
-    pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self {
-        let layout = tcx
+    pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self {
+        let layout = cx
+            .tcx()
             .layout_of(
-                ty::TypingEnv::fully_monomorphized()
-                    .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
+                cx.typing_env().as_query_input(Ty::new_tup(cx.tcx(), &[a.layout.ty, b.layout.ty])),
             )
             .unwrap();
         Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 1fa5dcbd24f..8b7b78c7129 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -222,7 +222,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let res = ImmTy::from_scalar_int(result, left.layout);
                 return interp_ok(if with_overflow {
                     let overflow = ImmTy::from_bool(overflow, *self.tcx);
-                    ImmTy::from_pair(res, overflow, *self.tcx)
+                    ImmTy::from_pair(res, overflow, self)
                 } else {
                     res
                 });
@@ -279,7 +279,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let res = ImmTy::from_scalar_int(result, left.layout);
                 if with_overflow {
                     let overflow = ImmTy::from_bool(overflow, *self.tcx);
-                    ImmTy::from_pair(res, overflow, *self.tcx)
+                    ImmTy::from_pair(res, overflow, self)
                 } else {
                     res
                 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0307.md b/compiler/rustc_error_codes/src/error_codes/E0307.md
index 0d29d56ea1a..b9c0493e8d6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0307.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0307.md
@@ -65,8 +65,10 @@ impl Trait for Foo {
 ```
 
 The nightly feature [Arbitrary self types][AST] extends the accepted
-set of receiver types to also include any type that can dereference to
-`Self`:
+set of receiver types to also include any type that implements the
+`Receiver` trait and can follow its chain of `Target` types to `Self`.
+There's a blanket implementation of `Receiver` for `T: Deref`, so any
+type which dereferences to `Self` can be used.
 
 ```
 #![feature(arbitrary_self_types)]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0708.md b/compiler/rustc_error_codes/src/error_codes/E0708.md
index 61a853ac446..f793470bafd 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0708.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0708.md
@@ -5,8 +5,6 @@
 Erroneous code example:
 
 ```edition2018
-#![feature(async_closure)]
-
 fn main() {
     let add_one = async |num: u8| {
         num + 1
@@ -18,8 +16,6 @@ fn main() {
 version, you can use successfully by using move:
 
 ```edition2018
-#![feature(async_closure)]
-
 fn main() {
     let add_one = async move |num: u8| { // ok!
         num + 1
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 6232c875ee8..25d41462556 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -94,8 +94,7 @@ mod styled_buffer;
 mod tests;
 pub mod translation;
 
-pub type PErr<'a> = Diag<'a>;
-pub type PResult<'a, T> = Result<T, PErr<'a>>;
+pub type PResult<'a, T> = Result<T, Diag<'a>>;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
@@ -576,6 +575,10 @@ pub enum StashKey {
     UndeterminedMacroResolution,
     /// Used by `Parser::maybe_recover_trailing_expr`
     ExprInPat,
+    /// If in the parser we detect a field expr with turbofish generic params it's possible that
+    /// it's a method call without parens. If later on in `hir_typeck` we find out that this is
+    /// the case we suppress this message and we give a better suggestion.
+    GenericInFieldExpr,
 }
 
 fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
@@ -1291,7 +1294,7 @@ impl<'a> DiagCtxtHandle<'a> {
         Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
     }
 
-    /// Ensures that an error is printed. See `Level::DelayedBug`.
+    /// Ensures that an error is printed. See [`Level::DelayedBug`].
     ///
     /// Note: this function used to be called `delay_span_bug`. It was renamed
     /// to match similar functions like `span_err`, `span_warn`, etc.
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 6a6496f9827..690e080fbfc 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -723,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     item_inner.kind,
                                     ItemKind::Mod(
                                         _,
-                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
+                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
                                     )
                                 ) =>
                         {
@@ -889,7 +889,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ItemKind::Mod(_, mod_kind)
-                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
+                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
                     {
                         feature_err(
                             self.sess,
@@ -1195,7 +1195,7 @@ impl InvocationCollectorNode for P<ast::Item> {
 
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
-            ModKind::Loaded(_, inline, _) => {
+            ModKind::Loaded(_, inline, _, _) => {
                 // Inline `mod foo { ... }`, but we still need to push directories.
                 let (dir_path, dir_ownership) = mod_dir_path(
                     ecx.sess,
@@ -1217,15 +1217,21 @@ impl InvocationCollectorNode for P<ast::Item> {
             ModKind::Unloaded => {
                 // We have an outline `mod foo;` so we need to parse the file.
                 let old_attrs_len = attrs.len();
-                let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } =
-                    parse_external_mod(
-                        ecx.sess,
-                        ident,
-                        span,
-                        &ecx.current_expansion.module,
-                        ecx.current_expansion.dir_ownership,
-                        &mut attrs,
-                    );
+                let ParsedExternalMod {
+                    items,
+                    spans,
+                    file_path,
+                    dir_path,
+                    dir_ownership,
+                    had_parse_error,
+                } = parse_external_mod(
+                    ecx.sess,
+                    ident,
+                    span,
+                    &ecx.current_expansion.module,
+                    ecx.current_expansion.dir_ownership,
+                    &mut attrs,
+                );
 
                 if let Some(lint_store) = ecx.lint_store {
                     lint_store.pre_expansion_lint(
@@ -1239,7 +1245,7 @@ impl InvocationCollectorNode for P<ast::Item> {
                     );
                 }
 
-                *mod_kind = ModKind::Loaded(items, Inline::No, spans);
+                *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error);
                 node.attrs = attrs;
                 if node.attrs.len() > old_attrs_len {
                     // If we loaded an out-of-line module and added some inner attributes,
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 614f52bbd28..85ea42e78ad 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -37,6 +37,7 @@ pub(crate) struct ParsedExternalMod {
     pub file_path: PathBuf,
     pub dir_path: PathBuf,
     pub dir_ownership: DirOwnership,
+    pub had_parse_error: Result<(), ErrorGuaranteed>,
 }
 
 pub enum ModError<'a> {
@@ -74,14 +75,17 @@ pub(crate) fn parse_external_mod(
         attrs.extend(inner_attrs);
         (items, inner_span, mp.file_path)
     };
+
     // (1) ...instead, we return a dummy module.
-    let (items, spans, file_path) =
-        result.map_err(|err| err.report(sess, span)).unwrap_or_default();
+    let ((items, spans, file_path), had_parse_error) = match result {
+        Err(err) => (Default::default(), Err(err.report(sess, span))),
+        Ok(result) => (result, Ok(())),
+    };
 
     // Extract the directory path for submodules of the module.
     let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
 
-    ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership }
+    ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership, had_parse_error }
 }
 
 pub(crate) fn mod_dir_path(
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 53362cb2529..c5913ed27cf 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -72,6 +72,8 @@ declare_features! (
     (accepted, associated_types, "1.0.0", None),
     /// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
     (accepted, async_await, "1.39.0", Some(50547)),
+    /// Allows `async || body` closures.
+    (accepted, async_closure, "CURRENT_RUSTC_VERSION", Some(62290)),
     /// Allows async functions to be declared, implemented, and used in traits.
     (accepted, async_fn_in_trait, "1.75.0", Some(91611)),
     /// Allows all literals in attribute lists and values of key-value pairs.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 93a605e197c..3c9115be7f5 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -388,8 +388,8 @@ declare_features! (
     (unstable, associated_const_equality, "1.58.0", Some(92827)),
     /// Allows associated type defaults.
     (unstable, associated_type_defaults, "1.2.0", Some(29661)),
-    /// Allows `async || body` closures.
-    (unstable, async_closure, "1.37.0", Some(62290)),
+    /// Allows async functions to be called from `dyn Trait`.
+    (incomplete, async_fn_in_dyn_trait, "CURRENT_RUSTC_VERSION", Some(133119)),
     /// Allows `#[track_caller]` on async functions.
     (unstable, async_fn_track_caller, "1.73.0", Some(110011)),
     /// Allows `for await` loops.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 0b7ffc4af45..705de389e07 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -9,7 +9,6 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::Symbol;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::kw;
 
 use crate::definitions::DefPathData;
 use crate::hir;
@@ -256,7 +255,6 @@ impl DefKind {
 
     pub fn def_path_data(self, name: Symbol) -> DefPathData {
         match self {
-            DefKind::Struct | DefKind::Union if name == kw::Empty => DefPathData::AnonAdt,
             DefKind::Mod
             | DefKind::Struct
             | DefKind::Union
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 9873a58cfe9..d85f9586d42 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -289,8 +289,6 @@ pub enum DefPathData {
     /// An existential `impl Trait` type node.
     /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
     OpaqueTy,
-    /// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { bar: Type }`
-    AnonAdt,
 }
 
 impl Definitions {
@@ -415,7 +413,7 @@ impl DefPathData {
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
 
             Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
-            | OpaqueTy | AnonAdt => None,
+            | OpaqueTy => None,
         }
     }
 
@@ -438,7 +436,6 @@ impl DefPathData {
             Ctor => DefPathDataName::Anon { namespace: sym::constructor },
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
             OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
-            AnonAdt => DefPathDataName::Anon { namespace: sym::anon_adt },
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 365e4cbb556..4800a479ff4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2882,8 +2882,6 @@ pub enum TyKind<'hir> {
     Never,
     /// A tuple (`(A, B, C, D, ...)`).
     Tup(&'hir [Ty<'hir>]),
-    /// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { foo: Type }`
-    AnonAdt(ItemId),
     /// A path to a type definition (`module::module::...::Type`), or an
     /// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`).
     ///
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 9abb0870bf0..8dbfefffee4 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -904,9 +904,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
         }
         TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
         TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {}
-        TyKind::AnonAdt(item_id) => {
-            try_visit!(visitor.visit_nested_item(item_id));
-        }
         TyKind::Pat(ty, pat) => {
             try_visit!(visitor.visit_ty(ty));
             try_visit!(visitor.visit_pattern_type_pattern(pat));
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 5c10fa46971..953e48a6d33 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use rustc_data_structures::stable_hasher::Hash64;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 use rustc_span::edition::Edition;
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 32498d9c5ab..25feb95d5df 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -241,10 +241,10 @@ hir_analysis_invalid_generic_receiver_ty_help =
     use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
-    .note = type of `self` must be `Self` or a type that dereferences to it
+    .note = type of `self` must be `Self` or some type implementing `Receiver`
 
 hir_analysis_invalid_receiver_ty_help =
-    consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+    consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 hir_analysis_invalid_union_field =
     field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 5a66c31a0cc..d8e9227a87c 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -18,7 +18,6 @@ pub enum AutoderefKind {
     /// A type which must dispatch to a `Deref` implementation.
     Overloaded,
 }
-
 struct AutoderefSnapshot<'tcx> {
     at_start: bool,
     reached_recursion_limit: bool,
@@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> {
     obligations: PredicateObligations<'tcx>,
 }
 
+/// Recursively dereference a type, considering both built-in
+/// dereferences (`*`) and the `Deref` trait.
+/// Although called `Autoderef` it can be configured to use the
+/// `Receiver` trait instead of the `Deref` trait.
 pub struct Autoderef<'a, 'tcx> {
     // Meta infos:
     infcx: &'a InferCtxt<'tcx>,
@@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> {
 
     // Configurations:
     include_raw_pointers: bool,
+    use_receiver_trait: bool,
     silence_errors: bool,
 }
 
@@ -69,6 +73,10 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // Otherwise, deref if type is derefable:
+        // NOTE: in the case of self.use_receiver_trait = true, you might think it would
+        // be better to skip this clause and use the Overloaded case only, since &T
+        // and &mut T implement Receiver. But built-in derefs apply equally to Receiver
+        // and Deref, and this has benefits for const and the emitted MIR.
         let (kind, new_ty) =
             if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
                 debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
@@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         body_def_id: LocalDefId,
         span: Span,
         base_ty: Ty<'tcx>,
-    ) -> Autoderef<'a, 'tcx> {
+    ) -> Self {
         Autoderef {
             infcx,
             span,
@@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
                 reached_recursion_limit: false,
             },
             include_raw_pointers: false,
+            use_receiver_trait: false,
             silence_errors: false,
         }
     }
@@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        // <ty as Deref>
-        let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
+        // <ty as Deref>, or whatever the equivalent trait is that we've been asked to walk.
+        let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait {
+            (tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?)
+        } else {
+            (tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?)
+        };
+        let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
         let obligation = traits::Obligation::new(
             tcx,
@@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
-            tcx,
-            tcx.lang_items().deref_target()?,
-            [ty],
-        ))?;
+        let (normalized_ty, obligations) =
+            self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
         debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
         self.state.obligations.extend(obligations);
 
@@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         self
     }
 
+    /// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as
+    /// the trait and associated type to iterate, instead of
+    /// `core::ops::Deref` and `core::ops::Deref::Target`
+    pub fn use_receiver_trait(mut self) -> Self {
+        self.use_receiver_trait = true;
+        self
+    }
+
     pub fn silence_errors(mut self) -> Self {
         self.silence_errors = true;
         self
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index df4da03f0f5..90e93bdbb50 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -3,6 +3,7 @@ use std::assert_matches::debug_assert_matches;
 use rustc_abi::FieldIdx;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, LangItem};
 use rustc_middle::bug;
 use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
@@ -21,6 +22,12 @@ pub struct InlineAsmCtxt<'a, 'tcx> {
     get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
 }
 
+enum NonAsmTypeReason<'tcx> {
+    UnevaluatedSIMDArrayLength(DefId, ty::Const<'tcx>),
+    Invalid(Ty<'tcx>),
+    InvalidElement(DefId, Ty<'tcx>),
+}
+
 impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
     pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
         InlineAsmCtxt {
@@ -56,7 +63,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         false
     }
 
-    fn get_asm_ty(&self, ty: Ty<'tcx>) -> Option<InlineAsmType> {
+    fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> {
         let asm_ty_isize = match self.tcx.sess.target.pointer_width {
             16 => InlineAsmType::I16,
             32 => InlineAsmType::I32,
@@ -65,64 +72,62 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         };
 
         match *ty.kind() {
-            ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
-            ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
-            ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
-            ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
-            ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
-            ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
-            ty::Float(FloatTy::F16) => Some(InlineAsmType::F16),
-            ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
-            ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
-            ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
-            ty::FnPtr(..) => Some(asm_ty_isize),
-            ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
+            ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::I8),
+            ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::I16),
+            ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::I32),
+            ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::I64),
+            ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Ok(InlineAsmType::I128),
+            ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Ok(asm_ty_isize),
+            ty::Float(FloatTy::F16) => Ok(InlineAsmType::F16),
+            ty::Float(FloatTy::F32) => Ok(InlineAsmType::F32),
+            ty::Float(FloatTy::F64) => Ok(InlineAsmType::F64),
+            ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128),
+            ty::FnPtr(..) => Ok(asm_ty_isize),
+            ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Ok(asm_ty_isize),
             ty::Adt(adt, args) if adt.repr().simd() => {
                 let fields = &adt.non_enum_variant().fields;
-                let elem_ty = fields[FieldIdx::ZERO].ty(self.tcx, args);
+                let field = &fields[FieldIdx::ZERO];
+                let elem_ty = field.ty(self.tcx, args);
 
                 let (size, ty) = match elem_ty.kind() {
                     ty::Array(ty, len) => {
+                        let len = self.tcx.normalize_erasing_regions(self.typing_env, *len);
                         if let Some(len) = len.try_to_target_usize(self.tcx) {
                             (len, *ty)
                         } else {
-                            return None;
+                            return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
+                                field.did, len,
+                            ));
                         }
                     }
                     _ => (fields.len() as u64, elem_ty),
                 };
 
                 match ty.kind() {
-                    ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)),
-                    ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => {
-                        Some(InlineAsmType::VecI16(size))
-                    }
-                    ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => {
-                        Some(InlineAsmType::VecI32(size))
-                    }
-                    ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => {
-                        Some(InlineAsmType::VecI64(size))
-                    }
+                    ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::VecI8(size)),
+                    ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::VecI16(size)),
+                    ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::VecI32(size)),
+                    ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::VecI64(size)),
                     ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => {
-                        Some(InlineAsmType::VecI128(size))
+                        Ok(InlineAsmType::VecI128(size))
                     }
                     ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => {
-                        Some(match self.tcx.sess.target.pointer_width {
+                        Ok(match self.tcx.sess.target.pointer_width {
                             16 => InlineAsmType::VecI16(size),
                             32 => InlineAsmType::VecI32(size),
                             64 => InlineAsmType::VecI64(size),
                             width => bug!("unsupported pointer width: {width}"),
                         })
                     }
-                    ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)),
-                    ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
-                    ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
-                    ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)),
-                    _ => None,
+                    ty::Float(FloatTy::F16) => Ok(InlineAsmType::VecF16(size)),
+                    ty::Float(FloatTy::F32) => Ok(InlineAsmType::VecF32(size)),
+                    ty::Float(FloatTy::F64) => Ok(InlineAsmType::VecF64(size)),
+                    ty::Float(FloatTy::F128) => Ok(InlineAsmType::VecF128(size)),
+                    _ => Err(NonAsmTypeReason::InvalidElement(field.did, ty)),
                 }
             }
             ty::Infer(_) => bug!("unexpected infer ty in asm operand"),
-            _ => None,
+            _ => Err(NonAsmTypeReason::Invalid(ty)),
         }
     }
 
@@ -163,17 +168,42 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             }
             _ => self.get_asm_ty(ty),
         };
-        let Some(asm_ty) = asm_ty else {
-            let msg = format!("cannot use value of type `{ty}` for inline assembly");
-            self.tcx
-                .dcx()
-                .struct_span_err(expr.span, msg)
-                .with_note(
-                    "only integers, floats, SIMD vectors, pointers and function pointers \
-                     can be used as arguments for inline assembly",
-                )
-                .emit();
-            return None;
+        let asm_ty = match asm_ty {
+            Ok(asm_ty) => asm_ty,
+            Err(reason) => {
+                match reason {
+                    NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => {
+                        let msg = format!("cannot evaluate SIMD vector length `{len}`");
+                        self.tcx
+                            .dcx()
+                            .struct_span_err(self.tcx.def_span(did), msg)
+                            .with_span_note(
+                                expr.span,
+                                "SIMD vector length needs to be known statically for use in `asm!`",
+                            )
+                            .emit();
+                    }
+                    NonAsmTypeReason::Invalid(ty) => {
+                        let msg = format!("cannot use value of type `{ty}` for inline assembly");
+                        self.tcx.dcx().struct_span_err(expr.span, msg).with_note(
+                            "only integers, floats, SIMD vectors, pointers and function pointers \
+                            can be used as arguments for inline assembly",
+                        ).emit();
+                    }
+                    NonAsmTypeReason::InvalidElement(did, ty) => {
+                        let msg = format!(
+                            "cannot use SIMD vector with element type `{ty}` for inline assembly"
+                        );
+                        self.tcx.dcx()
+                        .struct_span_err(self.tcx.def_span(did), msg).with_span_note(
+                            expr.span,
+                            "only integers, floats, SIMD vectors, pointers and function pointers \
+                            can be used as arguments for inline assembly",
+                        ).emit();
+                    }
+                }
+                return None;
+            }
         };
 
         // Check that the type implements Copy. The only case where this can
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c9773972d9a..57264d0bd2a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1821,13 +1821,18 @@ fn receiver_is_valid<'tcx>(
 
     let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
 
+    // The `arbitrary_self_types` feature allows custom smart pointer
+    // types to be method receivers, as identified by following the Receiver<Target=T>
+    // chain.
+    if arbitrary_self_types_enabled.is_some() {
+        autoderef = autoderef.use_receiver_trait();
+    }
+
     // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
     if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
         autoderef = autoderef.include_raw_pointers();
     }
 
-    let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
-
     // Keep dereferencing `receiver_ty` until we get to `self_ty`.
     while let Some((potential_self_ty, _)) = autoderef.next() {
         debug!(
@@ -1849,11 +1854,13 @@ fn receiver_is_valid<'tcx>(
         }
 
         // Without `feature(arbitrary_self_types)`, we require that each step in the
-        // deref chain implement `receiver`.
+        // deref chain implement `LegacyReceiver`.
         if arbitrary_self_types_enabled.is_none() {
-            if !receiver_is_implemented(
+            let legacy_receiver_trait_def_id =
+                tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
+            if !legacy_receiver_is_implemented(
                 wfcx,
-                receiver_trait_def_id,
+                legacy_receiver_trait_def_id,
                 cause.clone(),
                 potential_self_ty,
             ) {
@@ -1866,7 +1873,7 @@ fn receiver_is_valid<'tcx>(
                 cause.clone(),
                 wfcx.param_env,
                 potential_self_ty,
-                receiver_trait_def_id,
+                legacy_receiver_trait_def_id,
             );
         }
     }
@@ -1875,14 +1882,14 @@ fn receiver_is_valid<'tcx>(
     Err(ReceiverValidityError::DoesNotDeref)
 }
 
-fn receiver_is_implemented<'tcx>(
+fn legacy_receiver_is_implemented<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
-    receiver_trait_def_id: DefId,
+    legacy_receiver_trait_def_id: DefId,
     cause: ObligationCause<'tcx>,
     receiver_ty: Ty<'tcx>,
 ) -> bool {
     let tcx = wfcx.tcx();
-    let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
+    let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);
 
     let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
 
@@ -1890,7 +1897,7 @@ fn receiver_is_implemented<'tcx>(
         true
     } else {
         debug!(
-            "receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
+            "receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",
             receiver_ty
         );
         false
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index ca2597e79fd..1a6c0a93436 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -711,12 +711,19 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
                             `{filter:?}` implied bounds: {clause:?}"
                         );
                     }
+                    ty::ClauseKind::HostEffect(host_effect_predicate) => {
+                        assert_eq!(
+                            host_effect_predicate.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
 
                     ty::ClauseKind::RegionOutlives(_)
                     | ty::ClauseKind::ConstArgHasType(_, _)
                     | ty::ClauseKind::WellFormed(_)
-                    | ty::ClauseKind::ConstEvaluatable(_)
-                    | ty::ClauseKind::HostEffect(..) => {
+                    | ty::ClauseKind::ConstEvaluatable(_) => {
                         bug!(
                             "unexpected non-`Self` predicate when computing \
                             `{filter:?}` implied bounds: {clause:?}"
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 321a8aba7f7..d3c86989440 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -203,7 +203,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // corresponding `Projection` clause
         for def_ids in associated_types.values_mut() {
             for (projection_bound, span) in &projection_bounds {
-                let def_id = projection_bound.projection_def_id();
+                let def_id = projection_bound.item_def_id();
                 def_ids.swap_remove(&def_id);
                 if tcx.generics_require_sized_self(def_id) {
                     tcx.emit_node_span_lint(
@@ -413,7 +413,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             late_bound_in_projection_term,
             late_bound_in_term,
             |br_name| {
-                let item_name = tcx.item_name(pred.projection_def_id());
+                let item_name = tcx.item_name(pred.item_def_id());
                 struct_span_code_err!(
                     self.dcx(),
                     span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 09e46517cea..7683c87168b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -50,7 +50,7 @@ use rustc_span::{DUMMY_SP, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
-use tracing::{debug, debug_span, instrument};
+use tracing::{debug, instrument};
 
 use crate::bounds::Bounds;
 use crate::check::check_abi_fn_ptr;
@@ -2304,19 +2304,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::TyKind::Tup(fields) => {
                 Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t)))
             }
-            hir::TyKind::AnonAdt(item_id) => {
-                let _guard = debug_span!("AnonAdt");
-
-                let did = item_id.owner_id.def_id;
-                let adt_def = tcx.adt_def(did);
-
-                let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| {
-                    tcx.mk_param_from_def(param)
-                });
-                debug!(?args);
-
-                Ty::new_adt(tcx, adt_def, tcx.mk_args(args))
-            }
             hir::TyKind::BareFn(bf) => {
                 require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span);
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a74e36c45c6..20ba9ae2632 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -330,7 +330,6 @@ impl<'a> State<'a> {
             hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => {
                 self.word("_");
             }
-            hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"),
             hir::TyKind::Pat(ty, pat) => {
                 self.print_type(ty);
                 self.word(" is ");
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 9037caf0066..b8652d82d91 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -454,7 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         closure_kind: hir::ClosureKind,
         projection: ty::PolyProjectionPredicate<'tcx>,
     ) -> Option<ExpectedSig<'tcx>> {
-        let def_id = projection.projection_def_id();
+        let def_id = projection.item_def_id();
 
         // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
         // for closures and async closures, respectively.
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 3399a9fe880..d0272651c08 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -917,7 +917,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             [candidate] => format!(
                 "the method of the same name on {} `{}`",
                 match candidate.kind {
-                    probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
+                    probe::CandidateKind::InherentImplCandidate { .. } => "the inherent impl for",
                     _ => "trait",
                 },
                 self.tcx.def_path_str(candidate.item.container_id(self.tcx))
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 30f02b80ea6..56903865277 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2692,33 +2692,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         None
     }
 
-    // Check field access expressions
+    /// Check field access expressions, this works for both structs and tuples.
+    /// Returns the Ty of the field.
+    ///
+    /// ```not_rust
+    ///  base.field
+    ///  ^^^^^^^^^^ expr
+    ///  ^^^^       base
+    ///       ^^^^^ field
+    ///  ```
     fn check_expr_field(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         base: &'tcx hir::Expr<'tcx>,
         field: Ident,
+        // The expected type hint of the field.
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field);
         let base_ty = self.check_expr(base);
         let base_ty = self.structurally_resolve_type(base.span, base_ty);
+
+        // Whether we are trying to access a private field. Used for error reporting.
         let mut private_candidate = None;
+
+        // Field expressions automatically deref
         let mut autoderef = self.autoderef(expr.span, base_ty);
         while let Some((deref_base_ty, _)) = autoderef.next() {
             debug!("deref_base_ty: {:?}", deref_base_ty);
             match deref_base_ty.kind() {
                 ty::Adt(base_def, args) if !base_def.is_enum() => {
                     debug!("struct named {:?}", deref_base_ty);
-                    let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
-                    let (ident, def_scope) =
-                        self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
-
                     // we don't care to report errors for a struct if the struct itself is tainted
                     if let Err(guar) = base_def.non_enum_variant().has_errors() {
                         return Ty::new_error(self.tcx(), guar);
                     }
 
+                    let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
+                    let (ident, def_scope) =
+                        self.tcx.adjust_ident_and_get_scope(field, base_def.did(), fn_body_hir_id);
+
                     if let Some((idx, field)) = self.find_adt_field(*base_def, ident) {
                         self.write_field_index(expr.hir_id, idx);
 
@@ -2752,6 +2765,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => {}
             }
         }
+        // We failed to check the expression, report an error.
+
+        // Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
         self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
 
         if let Some((adjustments, did)) = private_candidate {
@@ -2776,6 +2792,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr.hir_id,
             expected.only_has_type(self),
         ) {
+            // If taking a method instead of calling it
             self.ban_take_value_of_method(expr, base_ty, field)
         } else if !base_ty.is_primitive_ty() {
             self.ban_nonexisting_field(field, base, expr, base_ty)
@@ -3059,7 +3076,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.help("methods are immutable and cannot be assigned to");
         }
 
-        err.emit()
+        // See `StashKey::GenericInFieldExpr` for more info
+        self.dcx().try_steal_replace_and_emit_err(field.span, StashKey::GenericInFieldExpr, err)
     }
 
     fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) {
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index ddd146fe785..b57c248ed2b 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -613,19 +613,16 @@ impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> {
         if arg_segment.args.is_none()
             && let Some(all_args) = self.fcx.typeck_results.borrow().node_args_opt(id)
             && let generics = self.fcx.tcx.generics_of(def_id)
-            && let args = &all_args[generics.parent_count..]
+            && let args = all_args[generics.parent_count..].iter().zip(&generics.own_params)
             // We can't turbofish consts :(
-            && args.iter().all(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_) | ty::GenericArgKind::Lifetime(_)))
+            && args.clone().all(|(_, param)| matches!(param.kind, ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Lifetime))
         {
-            let n_tys = args
-                .iter()
-                .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
-                .count();
-            for (idx, arg) in args
-                .iter()
-                .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
-                .enumerate()
-            {
+            // We filter out APITs, which are not turbofished.
+            let non_apit_type_args = args.filter(|(_, param)| {
+                matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: false, .. })
+            });
+            let n_tys = non_apit_type_args.clone().count();
+            for (idx, (arg, _)) in non_apit_type_args.enumerate() {
                 if let Some(ty) = arg.as_type()
                     && let Some(vid) = self.fcx.root_vid(ty)
                     && self.reachable_vids.contains(&vid)
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 039c117c099..3b377076545 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -79,12 +79,6 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
     /// used for error reporting
     static_candidates: RefCell<Vec<CandidateSource>>,
 
-    /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
-    /// for error reporting
-    unsatisfied_predicates: RefCell<
-        Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
-    >,
-
     scope_expr_id: HirId,
 
     /// Is this probe being done for a diagnostic? This will skip some error reporting
@@ -109,7 +103,7 @@ pub(crate) struct Candidate<'tcx> {
 
 #[derive(Debug, Clone)]
 pub(crate) enum CandidateKind<'tcx> {
-    InherentImplCandidate(DefId),
+    InherentImplCandidate { impl_def_id: DefId, receiver_steps: usize },
     ObjectCandidate(ty::PolyTraitRef<'tcx>),
     TraitCandidate(ty::PolyTraitRef<'tcx>),
     WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
@@ -162,6 +156,52 @@ impl AutorefOrPtrAdjustment {
     }
 }
 
+/// Extra information required only for error reporting.
+#[derive(Debug)]
+struct PickDiagHints<'a, 'tcx> {
+    /// Unstable candidates alongside the stable ones.
+    unstable_candidates: Option<Vec<(Candidate<'tcx>, Symbol)>>,
+
+    /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
+    /// for error reporting
+    unsatisfied_predicates: &'a mut Vec<(
+        ty::Predicate<'tcx>,
+        Option<ty::Predicate<'tcx>>,
+        Option<ObligationCause<'tcx>>,
+    )>,
+}
+
+/// Criteria to apply when searching for a given Pick. This is used during
+/// the search for potentially shadowed methods to ensure we don't search
+/// more candidates than strictly necessary.
+#[derive(Debug)]
+struct PickConstraintsForShadowed {
+    autoderefs: usize,
+    receiver_steps: Option<usize>,
+    def_id: DefId,
+}
+
+impl PickConstraintsForShadowed {
+    fn may_shadow_based_on_autoderefs(&self, autoderefs: usize) -> bool {
+        autoderefs == self.autoderefs
+    }
+
+    fn candidate_may_shadow(&self, candidate: &Candidate<'_>) -> bool {
+        // An item never shadows itself
+        candidate.item.def_id != self.def_id
+            // and we're only concerned about inherent impls doing the shadowing.
+            // Shadowing can only occur if the shadowed is further along
+            // the Receiver dereferencing chain than the shadowed.
+            && match candidate.kind {
+                CandidateKind::InherentImplCandidate { receiver_steps, .. } => match self.receiver_steps {
+                    Some(shadowed_receiver_steps) => receiver_steps > shadowed_receiver_steps,
+                    _ => false
+                },
+                _ => false
+            }
+    }
+}
+
 #[derive(Debug, Clone)]
 pub(crate) struct Pick<'tcx> {
     pub item: ty::AssocItem,
@@ -181,6 +221,11 @@ pub(crate) struct Pick<'tcx> {
 
     /// Unstable candidates alongside the stable ones.
     unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
+
+    /// Number of jumps along the `Receiver::Target` chain we followed
+    /// to identify this method. Used only for deshadowing errors.
+    /// Only applies for inherent impls.
+    pub receiver_steps: Option<usize>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -366,6 +411,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         autoderefs: 0,
                         from_unsafe_deref: false,
                         unsize: false,
+                        reachable_via_deref: true,
                     }]),
                     opt_bad_ty: None,
                     reached_recursion_limit: false,
@@ -516,47 +562,93 @@ fn method_autoderef_steps<'tcx>(
     let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
     let ParamEnvAnd { param_env, value: self_ty } = goal;
 
-    let mut autoderef =
+    // If arbitrary self types is not enabled, we follow the chain of
+    // `Deref<Target=T>`. If arbitrary self types is enabled, we instead
+    // follow the chain of `Receiver<Target=T>`, but we also record whether
+    // such types are reachable by following the (potentially shorter)
+    // chain of `Deref<Target=T>`. We will use the first list when finding
+    // potentially relevant function implementations (e.g. relevant impl blocks)
+    // but the second list when determining types that the receiver may be
+    // converted to, in order to find out which of those methods might actually
+    // be callable.
+    let mut autoderef_via_deref =
         Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
             .include_raw_pointers()
             .silence_errors();
-    let mut reached_raw_pointer = false;
-    let mut steps: Vec<_> = autoderef
-        .by_ref()
-        .map(|(ty, d)| {
-            let step = CandidateStep {
-                self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty),
-                autoderefs: d,
-                from_unsafe_deref: reached_raw_pointer,
-                unsize: false,
-            };
-            if let ty::RawPtr(_, _) = ty.kind() {
-                // all the subsequent steps will be from_unsafe_deref
-                reached_raw_pointer = true;
-            }
-            step
-        })
-        .collect();
 
-    let final_ty = autoderef.final_ty(true);
+    let mut reached_raw_pointer = false;
+    let arbitrary_self_types_enabled =
+        tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers();
+    let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled {
+        let reachable_via_deref =
+            autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
+
+        let mut autoderef_via_receiver =
+            Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
+                .include_raw_pointers()
+                .use_receiver_trait()
+                .silence_errors();
+        let steps = autoderef_via_receiver
+            .by_ref()
+            .zip(reachable_via_deref)
+            .map(|((ty, d), reachable_via_deref)| {
+                let step = CandidateStep {
+                    self_ty: infcx
+                        .make_query_response_ignoring_pending_obligations(inference_vars, ty),
+                    autoderefs: d,
+                    from_unsafe_deref: reached_raw_pointer,
+                    unsize: false,
+                    reachable_via_deref,
+                };
+                if ty.is_unsafe_ptr() {
+                    // all the subsequent steps will be from_unsafe_deref
+                    reached_raw_pointer = true;
+                }
+                step
+            })
+            .collect();
+        (steps, autoderef_via_receiver.reached_recursion_limit())
+    } else {
+        let steps = autoderef_via_deref
+            .by_ref()
+            .map(|(ty, d)| {
+                let step = CandidateStep {
+                    self_ty: infcx
+                        .make_query_response_ignoring_pending_obligations(inference_vars, ty),
+                    autoderefs: d,
+                    from_unsafe_deref: reached_raw_pointer,
+                    unsize: false,
+                    reachable_via_deref: true,
+                };
+                if ty.is_unsafe_ptr() {
+                    // all the subsequent steps will be from_unsafe_deref
+                    reached_raw_pointer = true;
+                }
+                step
+            })
+            .collect();
+        (steps, autoderef_via_deref.reached_recursion_limit())
+    };
+    let final_ty = autoderef_via_deref.final_ty(true);
     let opt_bad_ty = match final_ty.kind() {
         ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
             reached_raw_pointer,
             ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
         }),
         ty::Array(elem_ty, _) => {
-            let dereferences = steps.len() - 1;
-
+            let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
             steps.push(CandidateStep {
                 self_ty: infcx.make_query_response_ignoring_pending_obligations(
                     inference_vars,
                     Ty::new_slice(infcx.tcx, *elem_ty),
                 ),
-                autoderefs: dereferences,
+                autoderefs,
                 // this could be from an unsafe deref if we had
                 // a *mut/const [T; N]
                 from_unsafe_deref: reached_raw_pointer,
                 unsize: true,
+                reachable_via_deref: true, // this is always the final type from
+                                           // autoderef_via_deref
             });
 
             None
@@ -569,7 +661,7 @@ fn method_autoderef_steps<'tcx>(
     MethodAutoderefStepsResult {
         steps: tcx.arena.alloc_from_iter(steps),
         opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
-        reached_recursion_limit: autoderef.reached_recursion_limit(),
+        reached_recursion_limit,
     }
 }
 
@@ -600,7 +692,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             private_candidates: Vec::new(),
             private_candidate: Cell::new(None),
             static_candidates: RefCell::new(Vec::new()),
-            unsatisfied_predicates: RefCell::new(Vec::new()),
             scope_expr_id,
             is_suggestion,
         }
@@ -613,7 +704,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         self.private_candidates.clear();
         self.private_candidate.set(None);
         self.static_candidates.borrow_mut().clear();
-        self.unsatisfied_predicates.borrow_mut().clear();
     }
 
     /// When we're looking up a method by path (UFCS), we relate the receiver
@@ -652,12 +742,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn assemble_inherent_candidates(&mut self) {
         for step in self.steps.iter() {
-            self.assemble_probe(&step.self_ty);
+            self.assemble_probe(&step.self_ty, step.autoderefs);
         }
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
+    fn assemble_probe(
+        &mut self,
+        self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
+        receiver_steps: usize,
+    ) {
         let raw_self_ty = self_ty.value.value;
         match *raw_self_ty.kind() {
             ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -682,22 +776,31 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     self.fcx.instantiate_canonical(self.span, self_ty);
 
                 self.assemble_inherent_candidates_from_object(generalized_self_ty);
-                self.assemble_inherent_impl_candidates_for_type(p.def_id());
+                self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps);
                 if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
+                    self.assemble_inherent_candidates_for_incoherent_ty(
+                        raw_self_ty,
+                        receiver_steps,
+                    );
                 }
             }
             ty::Adt(def, _) => {
                 let def_id = def.did();
-                self.assemble_inherent_impl_candidates_for_type(def_id);
+                self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps);
                 if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
+                    self.assemble_inherent_candidates_for_incoherent_ty(
+                        raw_self_ty,
+                        receiver_steps,
+                    );
                 }
             }
             ty::Foreign(did) => {
-                self.assemble_inherent_impl_candidates_for_type(did);
+                self.assemble_inherent_impl_candidates_for_type(did, receiver_steps);
                 if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
+                    self.assemble_inherent_candidates_for_incoherent_ty(
+                        raw_self_ty,
+                        receiver_steps,
+                    );
                 }
             }
             ty::Param(p) => {
@@ -714,29 +817,35 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             | ty::RawPtr(_, _)
             | ty::Ref(..)
             | ty::Never
-            | ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty),
+            | ty::Tuple(..) => {
+                self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps)
+            }
             _ => {}
         }
     }
 
-    fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
+    fn assemble_inherent_candidates_for_incoherent_ty(
+        &mut self,
+        self_ty: Ty<'tcx>,
+        receiver_steps: usize,
+    ) {
         let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
             bug!("unexpected incoherent type: {:?}", self_ty)
         };
         for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() {
-            self.assemble_inherent_impl_probe(impl_def_id);
+            self.assemble_inherent_impl_probe(impl_def_id, receiver_steps);
         }
     }
 
-    fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
+    fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId, receiver_steps: usize) {
         let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter();
         for &impl_def_id in impl_def_ids {
-            self.assemble_inherent_impl_probe(impl_def_id);
+            self.assemble_inherent_impl_probe(impl_def_id, receiver_steps);
         }
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
+    fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId, receiver_steps: usize) {
         if !self.impl_dups.insert(impl_def_id) {
             return; // already visited
         }
@@ -750,7 +859,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             self.push_candidate(
                 Candidate {
                     item,
-                    kind: InherentImplCandidate(impl_def_id),
+                    kind: InherentImplCandidate { impl_def_id, receiver_steps },
                     import_ids: smallvec![],
                 },
                 true,
@@ -989,7 +1098,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     fn pick(mut self) -> PickResult<'tcx> {
         assert!(self.method_name.is_some());
 
-        if let Some(r) = self.pick_core() {
+        let mut unsatisfied_predicates = Vec::new();
+
+        if let Some(r) = self.pick_core(&mut unsatisfied_predicates) {
             return r;
         }
 
@@ -1009,7 +1120,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
         let static_candidates = std::mem::take(self.static_candidates.get_mut());
         let private_candidate = self.private_candidate.take();
-        let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut());
 
         // things failed, so lets look at all traits, for diagnostic purposes now:
         self.reset();
@@ -1019,7 +1129,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
         self.assemble_extension_candidates_for_all_traits();
 
-        let out_of_scope_traits = match self.pick_core() {
+        let out_of_scope_traits = match self.pick_core(&mut Vec::new()) {
             Some(Ok(p)) => vec![p.item.container_id(self.tcx)],
             Some(Err(MethodError::Ambiguity(v))) => v
                 .into_iter()
@@ -1054,17 +1164,48 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }))
     }
 
-    fn pick_core(&self) -> Option<PickResult<'tcx>> {
+    fn pick_core(
+        &self,
+        unsatisfied_predicates: &mut Vec<(
+            ty::Predicate<'tcx>,
+            Option<ty::Predicate<'tcx>>,
+            Option<ObligationCause<'tcx>>,
+        )>,
+    ) -> Option<PickResult<'tcx>> {
         // Pick stable methods only first, and consider unstable candidates if not found.
-        self.pick_all_method(Some(&mut vec![])).or_else(|| self.pick_all_method(None))
+        self.pick_all_method(&mut PickDiagHints {
+            // This first cycle, maintain a list of unstable candidates which
+            // we encounter. This will end up in the Pick for diagnostics.
+            unstable_candidates: Some(Vec::new()),
+            // Contribute to the list of unsatisfied predicates which may
+            // also be used for diagnostics.
+            unsatisfied_predicates,
+        })
+        .or_else(|| {
+            self.pick_all_method(&mut PickDiagHints {
+                // On the second search, don't provide a special list of unstable
+                // candidates. This indicates to the picking code that it should
+                // in fact include such unstable candidates in the actual
+                // search.
+                unstable_candidates: None,
+                // And there's no need to duplicate ourselves in the
+                // unsatisifed predicates list. Provide a throwaway list.
+                unsatisfied_predicates: &mut Vec::new(),
+            })
+        })
     }
 
-    fn pick_all_method(
+    fn pick_all_method<'b>(
         &self,
-        mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'b, 'tcx>,
     ) -> Option<PickResult<'tcx>> {
+        let track_unstable_candidates = pick_diag_hints.unstable_candidates.is_some();
         self.steps
             .iter()
+            // At this point we're considering the types to which the receiver can be converted,
+            // so we want to follow the `Deref` chain not the `Receiver` chain. Filter out
+            // steps which can only be reached by following the (longer) `Receiver` chain.
+            .filter(|step| step.reachable_via_deref)
             .filter(|step| {
                 debug!("pick_all_method: step={:?}", step);
                 // skip types that are from a type error or that would require dereferencing
@@ -1082,40 +1223,188 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     .unwrap_or_else(|_| {
                         span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty)
                     });
-                self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut())
-                    .or_else(|| {
-                        self.pick_autorefd_method(
-                            step,
-                            self_ty,
-                            hir::Mutability::Not,
-                            unstable_candidates.as_deref_mut(),
-                        )
-                        .or_else(|| {
-                            self.pick_autorefd_method(
+
+                let by_value_pick = self.pick_by_value_method(step, self_ty, pick_diag_hints);
+
+                // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing)
+                if let Some(by_value_pick) = by_value_pick {
+                    if let Ok(by_value_pick) = by_value_pick.as_ref() {
+                        if by_value_pick.kind == PickKind::InherentImplPick {
+                            if let Err(e) = self.check_for_shadowed_autorefd_method(
+                                by_value_pick,
                                 step,
                                 self_ty,
-                                hir::Mutability::Mut,
-                                unstable_candidates.as_deref_mut(),
-                            )
-                        })
-                        .or_else(|| {
-                            self.pick_const_ptr_method(
+                                hir::Mutability::Not,
+                                track_unstable_candidates,
+                            ) {
+                                return Some(Err(e));
+                            }
+                            if let Err(e) = self.check_for_shadowed_autorefd_method(
+                                by_value_pick,
                                 step,
                                 self_ty,
-                                unstable_candidates.as_deref_mut(),
-                            )
-                        })
-                        .or_else(|| {
-                            self.pick_reborrow_pin_method(
+                                hir::Mutability::Mut,
+                                track_unstable_candidates,
+                            ) {
+                                return Some(Err(e));
+                            }
+                        }
+                    }
+                    return Some(by_value_pick);
+                }
+
+                let autoref_pick = self.pick_autorefd_method(
+                    step,
+                    self_ty,
+                    hir::Mutability::Not,
+                    pick_diag_hints,
+                    None,
+                );
+                // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
+                if let Some(autoref_pick) = autoref_pick {
+                    if let Ok(autoref_pick) = autoref_pick.as_ref() {
+                        // Check we're not shadowing others
+                        if autoref_pick.kind == PickKind::InherentImplPick {
+                            if let Err(e) = self.check_for_shadowed_autorefd_method(
+                                autoref_pick,
                                 step,
                                 self_ty,
-                                unstable_candidates.as_deref_mut(),
-                            )
-                        })
-                    })
+                                hir::Mutability::Mut,
+                                track_unstable_candidates,
+                            ) {
+                                return Some(Err(e));
+                            }
+                        }
+                    }
+                    return Some(autoref_pick);
+                }
+
+                // Note that no shadowing errors are produced from here on,
+                // as we consider const ptr methods.
+                // We allow new methods that take *mut T to shadow
+                // methods which took *const T, so there is no entry in
+                // this list for the results of `pick_const_ptr_method`.
+                // The reason is that the standard pointer cast method
+                // (on a mutable pointer) always already shadows the
+                // cast method (on a const pointer). So, if we added
+                // `pick_const_ptr_method` to this method, the anti-
+                // shadowing algorithm would always complain about
+                // the conflict between *const::cast and *mut::cast.
+                // In practice therefore this does constrain us:
+                // we cannot add new
+                //   self: *mut Self
+                // methods to types such as NonNull or anything else
+                // which implements Receiver, because this might in future
+                // shadow existing methods taking
+                //   self: *const NonNull<Self>
+                // in the pointee. In practice, methods taking raw pointers
+                // are rare, and it seems that it should be easily possible
+                // to avoid such compatibility breaks.
+                // We also don't check for reborrowed pin methods which
+                // may be shadowed; these also seem unlikely to occur.
+                self.pick_autorefd_method(
+                    step,
+                    self_ty,
+                    hir::Mutability::Mut,
+                    pick_diag_hints,
+                    None,
+                )
+                .or_else(|| self.pick_const_ptr_method(step, self_ty, pick_diag_hints))
+                .or_else(|| self.pick_reborrow_pin_method(step, self_ty, pick_diag_hints))
             })
     }
 
+    /// Check for cases where arbitrary self types allows shadowing
+    /// of methods that might be a compatibility break. Specifically,
+    /// we have something like:
+    /// ```ignore (illustrative)
+    /// struct A;
+    /// impl A {
+    ///   fn foo(self: &NonNull<A>) {}
+    ///      // note this is by reference
+    /// }
+    /// ```
+    /// then we've come along and added this method to `NonNull`:
+    /// ```ignore (illustrative)
+    ///   fn foo(self)  // note this is by value
+    /// ```
+    /// Report an error in this case.
+    fn check_for_shadowed_autorefd_method(
+        &self,
+        possible_shadower: &Pick<'tcx>,
+        step: &CandidateStep<'tcx>,
+        self_ty: Ty<'tcx>,
+        mutbl: hir::Mutability,
+        track_unstable_candidates: bool,
+    ) -> Result<(), MethodError<'tcx>> {
+        // We don't want to remember any of the diagnostic hints from this
+        // shadow search, but we do need to provide Some/None for the
+        // unstable_candidates in order to reflect the behavior of the
+        // main search.
+        let mut pick_diag_hints = PickDiagHints {
+            unstable_candidates: if track_unstable_candidates { Some(Vec::new()) } else { None },
+            unsatisfied_predicates: &mut Vec::new(),
+        };
+        // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
+        let pick_constraints = PickConstraintsForShadowed {
+            // It's the same `self` type...
+            autoderefs: possible_shadower.autoderefs,
+            // ... but the method was found in an impl block determined
+            // by searching further along the Receiver chain than the other,
+            // showing that it's a smart pointer type causing the problem...
+            receiver_steps: possible_shadower.receiver_steps,
+            // ... and they don't end up pointing to the same item in the
+            // first place (could happen with things like blanket impls for T)
+            def_id: possible_shadower.item.def_id,
+        };
+        // A note on the autoderefs above. Within pick_by_value_method, an extra
+        // autoderef may be applied in order to reborrow a reference with
+        // a different lifetime. That seems as though it would break the
+        // logic of these constraints, since the number of autoderefs could
+        // no longer be used to identify the fundamental type of the receiver.
+        // However, this extra autoderef is applied only to by-value calls
+        // where the receiver is already a reference. So this situation would
+        // only occur in cases where the shadowing looks like this:
+        // ```
+        // struct A;
+        // impl A {
+        //   fn foo(self: &&NonNull<A>) {}
+        //      // note this is by DOUBLE reference
+        // }
+        // ```
+        // then we've come along and added this method to `NonNull`:
+        // ```
+        //   fn foo(&self)  // note this is by single reference
+        // ```
+        // and the call is:
+        // ```
+        // let bar = NonNull<Foo>;
+        // let bar = &foo;
+        // bar.foo();
+        // ```
+        // In these circumstances, the logic is wrong, and we wouldn't spot
+        // the shadowing, because the autoderef-based maths wouldn't line up.
+        // This is a niche case and we can live without generating an error
+        // in the case of such shadowing.
+        let potentially_shadowed_pick = self.pick_autorefd_method(
+            step,
+            self_ty,
+            mutbl,
+            &mut pick_diag_hints,
+            Some(&pick_constraints),
+        );
+        // Look for actual pairs of shadower/shadowed which are
+        // the sort of shadowing case we want to avoid. Specifically...
+        if let Some(Ok(possible_shadowed)) = potentially_shadowed_pick.as_ref() {
+            let sources = [possible_shadower, possible_shadowed]
+                .into_iter()
+                .map(|p| self.candidate_source_from_pick(p))
+                .collect();
+            return Err(MethodError::Ambiguity(sources));
+        }
+        Ok(())
+    }
+
     /// For each type `T` in the step list, this attempts to find a method where
     /// the (transformed) self type is exactly `T`. We do however do one
     /// transformation on the adjustment: if we are passing a region pointer in,
@@ -1126,13 +1415,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
-        unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
     ) -> Option<PickResult<'tcx>> {
         if step.unsize {
             return None;
         }
 
-        self.pick_method(self_ty, unstable_candidates).map(|r| {
+        self.pick_method(self_ty, pick_diag_hints, None).map(|r| {
             r.map(|mut pick| {
                 pick.autoderefs = step.autoderefs;
 
@@ -1170,15 +1459,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         mutbl: hir::Mutability,
-        unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
+        pick_constraints: Option<&PickConstraintsForShadowed>,
     ) -> Option<PickResult<'tcx>> {
         let tcx = self.tcx;
 
+        if let Some(pick_constraints) = pick_constraints {
+            if !pick_constraints.may_shadow_based_on_autoderefs(step.autoderefs) {
+                return None;
+            }
+        }
+
         // In general, during probing we erase regions.
         let region = tcx.lifetimes.re_erased;
 
         let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl);
-        self.pick_method(autoref_ty, unstable_candidates).map(|r| {
+        self.pick_method(autoref_ty, pick_diag_hints, pick_constraints).map(|r| {
             r.map(|mut pick| {
                 pick.autoderefs = step.autoderefs;
                 pick.autoref_or_ptr_adjustment =
@@ -1189,12 +1485,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     }
 
     /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
-    #[instrument(level = "debug", skip(self, step, unstable_candidates))]
+    #[instrument(level = "debug", skip(self, step, pick_diag_hints))]
     fn pick_reborrow_pin_method(
         &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
-        unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
     ) -> Option<PickResult<'tcx>> {
         if !self.tcx.features().pin_ergonomics() {
             return None;
@@ -1215,7 +1511,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
         let region = self.tcx.lifetimes.re_erased;
         let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not);
-        self.pick_method(autopin_ty, unstable_candidates).map(|r| {
+        self.pick_method(autopin_ty, pick_diag_hints, None).map(|r| {
             r.map(|mut pick| {
                 pick.autoderefs = step.autoderefs;
                 pick.autoref_or_ptr_adjustment =
@@ -1232,7 +1528,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
-        unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
     ) -> Option<PickResult<'tcx>> {
         // Don't convert an unsized reference to ptr
         if step.unsize {
@@ -1244,7 +1540,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         };
 
         let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty);
-        self.pick_method(const_ptr_ty, unstable_candidates).map(|r| {
+        self.pick_method(const_ptr_ty, pick_diag_hints, None).map(|r| {
             r.map(|mut pick| {
                 pick.autoderefs = step.autoderefs;
                 pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
@@ -1256,40 +1552,35 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     fn pick_method(
         &self,
         self_ty: Ty<'tcx>,
-        mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
+        pick_constraints: Option<&PickConstraintsForShadowed>,
     ) -> Option<PickResult<'tcx>> {
         debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
 
-        let mut possibly_unsatisfied_predicates = Vec::new();
-
         for (kind, candidates) in
             [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
         {
             debug!("searching {} candidates", kind);
-            let res = self.consider_candidates(
-                self_ty,
-                candidates,
-                &mut possibly_unsatisfied_predicates,
-                unstable_candidates.as_deref_mut(),
-            );
+            let res =
+                self.consider_candidates(self_ty, candidates, pick_diag_hints, pick_constraints);
             if let Some(pick) = res {
                 return Some(pick);
             }
         }
 
         if self.private_candidate.get().is_none() {
-            if let Some(Ok(pick)) =
-                self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None)
-            {
+            if let Some(Ok(pick)) = self.consider_candidates(
+                self_ty,
+                &self.private_candidates,
+                &mut PickDiagHints {
+                    unstable_candidates: None,
+                    unsatisfied_predicates: &mut vec![],
+                },
+                None,
+            ) {
                 self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
             }
         }
-
-        // `pick_method` may be called twice for the same self_ty if no stable methods
-        // match. Only extend once.
-        if unstable_candidates.is_some() {
-            self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
-        }
         None
     }
 
@@ -1297,17 +1588,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         self_ty: Ty<'tcx>,
         candidates: &[Candidate<'tcx>],
-        possibly_unsatisfied_predicates: &mut Vec<(
-            ty::Predicate<'tcx>,
-            Option<ty::Predicate<'tcx>>,
-            Option<ObligationCause<'tcx>>,
-        )>,
-        mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
+        pick_diag_hints: &mut PickDiagHints<'_, 'tcx>,
+        pick_constraints: Option<&PickConstraintsForShadowed>,
     ) -> Option<PickResult<'tcx>> {
         let mut applicable_candidates: Vec<_> = candidates
             .iter()
+            .filter(|candidate| {
+                pick_constraints
+                    .map(|pick_constraints| pick_constraints.candidate_may_shadow(&candidate))
+                    .unwrap_or(true)
+            })
             .map(|probe| {
-                (probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
+                (
+                    probe,
+                    self.consider_probe(
+                        self_ty,
+                        probe,
+                        &mut pick_diag_hints.unsatisfied_predicates,
+                    ),
+                )
             })
             .filter(|&(_, status)| status != ProbeResult::NoMatch)
             .collect();
@@ -1322,7 +1621,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             }
         }
 
-        if let Some(uc) = &mut unstable_candidates {
+        if let Some(uc) = &mut pick_diag_hints.unstable_candidates {
             applicable_candidates.retain(|&(candidate, _)| {
                 if let stability::EvalResult::Deny { feature, .. } =
                     self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
@@ -1340,10 +1639,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
 
         applicable_candidates.pop().map(|(probe, status)| match status {
-            ProbeResult::Match => {
-                Ok(probe
-                    .to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default()))
-            }
+            ProbeResult::Match => Ok(probe.to_unadjusted_pick(
+                self_ty,
+                pick_diag_hints.unstable_candidates.clone().unwrap_or_default(),
+            )),
             ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType),
         })
     }
@@ -1372,6 +1671,7 @@ impl<'tcx> Pick<'tcx> {
             autoref_or_ptr_adjustment: _,
             self_ty,
             unstable_candidates: _,
+            receiver_steps: _,
         } = *self;
         self_ty != other.self_ty || def_id != other.item.def_id
     }
@@ -1447,7 +1747,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// so do not use to make a decision that may lead to a successful compilation.
     fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
         match candidate.kind {
-            InherentImplCandidate(_) => {
+            InherentImplCandidate { .. } => {
                 CandidateSource::Impl(candidate.item.container_id(self.tcx))
             }
             ObjectCandidate(_) | WhereClauseCandidate(_) => {
@@ -1477,6 +1777,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource {
+        match pick.kind {
+            InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)),
+            ObjectPick | WhereClausePick(_) | TraitPick => {
+                CandidateSource::Trait(pick.item.container_id(self.tcx))
+            }
+        }
+    }
+
     #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
     fn consider_probe(
         &self,
@@ -1501,7 +1810,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             let (mut xform_self_ty, mut xform_ret_ty);
 
             match probe.kind {
-                InherentImplCandidate(impl_def_id) => {
+                InherentImplCandidate { impl_def_id, .. } => {
                     let impl_args = self.fresh_args_for_item(self.span, impl_def_id);
                     let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
                     (xform_self_ty, xform_ret_ty) =
@@ -1693,7 +2002,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 // We don't normalize the other candidates for perf/backwards-compat reasons...
                 // but `self.return_type` is only set on the diagnostic-path, so we
                 // should be okay doing it here.
-                if !matches!(probe.kind, InherentImplCandidate(_)) {
+                if !matches!(probe.kind, InherentImplCandidate { .. }) {
                     xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty);
                 }
 
@@ -1771,6 +2080,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             autoref_or_ptr_adjustment: None,
             self_ty,
             unstable_candidates: vec![],
+            receiver_steps: None,
         })
     }
 
@@ -1808,7 +2118,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     pcx.method_name = Some(method_name);
                     pcx.assemble_inherent_candidates();
                     pcx.assemble_extension_candidates_for_all_traits();
-                    pcx.pick_core().and_then(|pick| pick.ok()).map(|pick| pick.item)
+                    pcx.pick_core(&mut Vec::new()).and_then(|pick| pick.ok()).map(|pick| pick.item)
                 })
                 .collect();
 
@@ -2042,7 +2352,7 @@ impl<'tcx> Candidate<'tcx> {
         Pick {
             item: self.item,
             kind: match self.kind {
-                InherentImplCandidate(_) => InherentImplPick,
+                InherentImplCandidate { .. } => InherentImplPick,
                 ObjectCandidate(_) => ObjectPick,
                 TraitCandidate(_) => TraitPick,
                 WhereClauseCandidate(trait_ref) => {
@@ -2064,6 +2374,10 @@ impl<'tcx> Candidate<'tcx> {
             autoref_or_ptr_adjustment: None,
             self_ty,
             unstable_candidates,
+            receiver_steps: match self.kind {
+                InherentImplCandidate { receiver_steps, .. } => Some(receiver_steps),
+                _ => None,
+            },
         }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index b0c020dd7cb..4f283644cbe 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1840,7 +1840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 /// captured by move.
 ///
 /// ```rust
-/// #![feature(async_closure)]
 /// let x = &1i32; // Let's call this lifetime `'1`.
 /// let c = async move || {
 ///     println!("{:?}", *x);
@@ -1855,7 +1854,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 /// child capture with the lifetime of the parent coroutine-closure's env.
 ///
 /// ```rust
-/// #![feature(async_closure)]
 /// let mut x = 1i32;
 /// let c = async || {
 ///     x = 1;
diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs
index 2a821b71103..5d40b8ab2ee 100644
--- a/compiler/rustc_lint/src/async_closures.rs
+++ b/compiler/rustc_lint/src/async_closures.rs
@@ -12,7 +12,6 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// #![feature(async_closure)]
     /// #![warn(closure_returning_async_block)]
     /// let c = |x: &str| async {};
     /// ```
@@ -40,8 +39,6 @@ declare_lint! {
     /// But it does work with async closures:
     ///
     /// ```rust
-    /// #![feature(async_closure)]
-    ///
     /// async fn callback(x: &str) {}
     ///
     /// let captured_str = String::new();
@@ -52,7 +49,6 @@ declare_lint! {
     pub CLOSURE_RETURNING_ASYNC_BLOCK,
     Allow,
     "closure that returns `async {}` could be rewritten as an async closure",
-    @feature_gate = async_closure;
 }
 
 declare_lint_pass!(
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 093cc16fb4c..3543784bc72 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3038,7 +3038,7 @@ impl EarlyLintPass for SpecialModuleName {
         for item in &krate.items {
             if let ast::ItemKind::Mod(
                 _,
-                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
+                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
             ) = item.kind
             {
                 if item.attrs.iter().any(|a| a.has_name(sym::path)) {
diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs
index 7fbf381a8d3..186dec5904b 100644
--- a/compiler/rustc_lint/src/tests.rs
+++ b/compiler/rustc_lint/src/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use rustc_span::{Symbol, create_default_session_globals_then};
 
 use crate::levels::parse_lint_and_tool_name;
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 06550728f0f..b79205ff946 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1535,7 +1535,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
 
 extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI,
-                                                       unsigned *Cookie) {
+                                                       uint64_t *Cookie) {
   llvm::DiagnosticInfoSrcMgr *SM =
       static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
   *Cookie = SM->getLocCookie();
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 161716610fe..1f50b67cb50 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -19,6 +19,7 @@ use rustc_target::spec::SymbolVisibility;
 use tracing::debug;
 
 use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
+use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
 
 /// Describes how a monomorphization will be instantiated in object files.
@@ -104,7 +105,9 @@ impl<'tcx> MonoItem<'tcx> {
                 let entry_def_id = tcx.entry_fn(()).map(|(id, _)| id);
                 // If this function isn't inlined or otherwise has an extern
                 // indicator, then we'll be creating a globally shared version.
-                if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
+                let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
+                if codegen_fn_attrs.contains_extern_indicator()
+                    || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
                     || !instance.def.generates_cgu_internal_copy(tcx)
                     || Some(instance.def_id()) == entry_def_id
                 {
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index eeed5118592..f049da95f29 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -149,11 +149,21 @@ pub struct CandidateStep<'tcx> {
     /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
     pub from_unsafe_deref: bool,
     pub unsize: bool,
+    /// We will generate CandidateSteps which are reachable via a chain
+    /// of following `Receiver`. The first 'n' of those will be reachable
+    /// by following a chain of 'Deref' instead (since there's a blanket
+    /// implementation of Receiver for Deref).
+    /// We use the entire set of steps when identifying method candidates
+    /// (e.g. identifying relevant `impl` blocks) but only those that are
+    /// reachable via Deref when examining what the receiver type can
+    /// be converted into by autodereffing.
+    pub reachable_via_deref: bool,
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be found.
+    /// The valid autoderef steps that could be found by following a chain
+    /// of `Receiver<Target=T>` or `Deref<Target=T>` trait implementations.
     pub steps: &'tcx [CandidateStep<'tcx>],
     /// If Some(T), a type autoderef reported an error on.
     pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 65c909e70f6..1dd564d9798 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -677,23 +677,26 @@ impl<'tcx> Instance<'tcx> {
                 //
                 // 1) The underlying method expects a caller location parameter
                 // in the ABI
-                if resolved.def.requires_caller_location(tcx)
-                        // 2) The caller location parameter comes from having `#[track_caller]`
-                        // on the implementation, and *not* on the trait method.
-                        && !tcx.should_inherit_track_caller(def)
-                        // If the method implementation comes from the trait definition itself
-                        // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
-                        // then we don't need to generate a shim. This check is needed because
-                        // `should_inherit_track_caller` returns `false` if our method
-                        // implementation comes from the trait block, and not an impl block
-                        && !matches!(
-                            tcx.opt_associated_item(def),
-                            Some(ty::AssocItem {
-                                container: ty::AssocItemContainer::Trait,
-                                ..
-                            })
-                        )
-                {
+                let needs_track_caller_shim = resolved.def.requires_caller_location(tcx)
+                    // 2) The caller location parameter comes from having `#[track_caller]`
+                    // on the implementation, and *not* on the trait method.
+                    && !tcx.should_inherit_track_caller(def)
+                    // If the method implementation comes from the trait definition itself
+                    // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
+                    // then we don't need to generate a shim. This check is needed because
+                    // `should_inherit_track_caller` returns `false` if our method
+                    // implementation comes from the trait block, and not an impl block
+                    && !matches!(
+                        tcx.opt_associated_item(def),
+                        Some(ty::AssocItem {
+                            container: ty::AssocItemContainer::Trait,
+                            ..
+                        })
+                    );
+                // We also need to generate a shim if this is an AFIT.
+                let needs_rpitit_shim =
+                    tcx.return_position_impl_trait_in_trait_shim_data(def).is_some();
+                if needs_track_caller_shim || needs_rpitit_shim {
                     if tcx.is_closure_like(def) {
                         debug!(
                             " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 70e0568b202..80b11892a42 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -146,6 +146,7 @@ mod opaque_types;
 mod parameterized;
 mod predicate;
 mod region;
+mod return_position_impl_trait_in_trait;
 mod rvalue_scopes;
 mod structural_impls;
 #[allow(hidden_glob_reexports)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index cd4123f0a3f..40e0fb0087f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1020,7 +1020,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
                     self.insert_trait_and_projection(
                         trait_ref,
-                        Some((proj.projection_def_id(), proj.term())),
+                        Some((proj.item_def_id(), proj.term())),
                         &mut traits,
                         &mut fn_traits,
                     );
diff --git a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs
new file mode 100644
index 00000000000..21c605f8296
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs
@@ -0,0 +1,95 @@
+use rustc_hir::def_id::DefId;
+
+use crate::ty::{self, ExistentialPredicateStableCmpExt, TyCtxt};
+
+impl<'tcx> TyCtxt<'tcx> {
+    /// Given a `def_id` of a trait or impl method, compute whether that method needs to
+    /// have an RPITIT shim applied to it for it to be object safe. If so, return the
+    /// `def_id` of the RPITIT, and also the args of trait method that returns the RPITIT.
+    ///
+    /// NOTE that these args are not, in general, the same as than the RPITIT's args. They
+    /// are a subset of those args,  since they do not include the late-bound lifetimes of
+    /// the RPITIT. Depending on the context, these will need to be dealt with in different
+    /// ways -- in codegen, it's okay to fill them with ReErased.
+    pub fn return_position_impl_trait_in_trait_shim_data(
+        self,
+        def_id: DefId,
+    ) -> Option<(DefId, ty::EarlyBinder<'tcx, ty::GenericArgsRef<'tcx>>)> {
+        let assoc_item = self.opt_associated_item(def_id)?;
+
+        let (trait_item_def_id, opt_impl_def_id) = match assoc_item.container {
+            ty::AssocItemContainer::Impl => {
+                (assoc_item.trait_item_def_id?, Some(self.parent(def_id)))
+            }
+            ty::AssocItemContainer::Trait => (def_id, None),
+        };
+
+        let sig = self.fn_sig(trait_item_def_id);
+
+        // Check if the trait returns an RPITIT.
+        let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) =
+            *sig.skip_binder().skip_binder().output().kind()
+        else {
+            return None;
+        };
+        if !self.is_impl_trait_in_trait(def_id) {
+            return None;
+        }
+
+        let args = if let Some(impl_def_id) = opt_impl_def_id {
+            // Rebase the args from the RPITIT onto the impl trait ref, so we can later
+            // substitute them with the method args of the *impl* method, since that's
+            // the instance we're building a vtable shim for.
+            ty::GenericArgs::identity_for_item(self, trait_item_def_id).rebase_onto(
+                self,
+                self.parent(trait_item_def_id),
+                self.impl_trait_ref(impl_def_id)
+                    .expect("expected impl trait ref from parent of impl item")
+                    .instantiate_identity()
+                    .args,
+            )
+        } else {
+            // This is when we have a default trait implementation.
+            ty::GenericArgs::identity_for_item(self, trait_item_def_id)
+        };
+
+        Some((def_id, ty::EarlyBinder::bind(args)))
+    }
+
+    /// Given a `DefId` of an RPITIT and its args, return the existential predicates
+    /// that corresponds to the RPITIT's bounds with the self type erased.
+    pub fn item_bounds_to_existential_predicates(
+        self,
+        def_id: DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
+        let mut bounds: Vec<_> = self
+            .item_super_predicates(def_id)
+            .iter_instantiated(self, args)
+            .filter_map(|clause| {
+                clause
+                    .kind()
+                    .map_bound(|clause| match clause {
+                        ty::ClauseKind::Trait(trait_pred) => Some(ty::ExistentialPredicate::Trait(
+                            ty::ExistentialTraitRef::erase_self_ty(self, trait_pred.trait_ref),
+                        )),
+                        ty::ClauseKind::Projection(projection_pred) => {
+                            Some(ty::ExistentialPredicate::Projection(
+                                ty::ExistentialProjection::erase_self_ty(self, projection_pred),
+                            ))
+                        }
+                        ty::ClauseKind::TypeOutlives(_) => {
+                            // Type outlives bounds don't really turn into anything,
+                            // since we must use an intersection region for the `dyn*`'s
+                            // region anyways.
+                            None
+                        }
+                        _ => unreachable!("unexpected clause in item bounds: {clause:?}"),
+                    })
+                    .transpose()
+            })
+            .collect();
+        bounds.sort_by(|a, b| a.skip_binder().stable_cmp(self, &b.skip_binder()));
+        self.mk_poly_existential_predicates(&bounds)
+    }
+}
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 4a9bcdaddb3..89ff93d9943 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -179,15 +179,15 @@ where
     /// Advances the cursor to hold the dataflow state at `target` before its "primary" effect is
     /// applied.
     ///
-    /// The "before" effect at the target location *will be* applied.
+    /// The "early" effect at the target location *will be* applied.
     pub fn seek_before_primary_effect(&mut self, target: Location) {
-        self.seek_after(target, Effect::Before)
+        self.seek_after(target, Effect::Early)
     }
 
     /// Advances the cursor to hold the dataflow state at `target` after its "primary" effect is
     /// applied.
     ///
-    /// The "before" effect at the target location will be applied as well.
+    /// The "early" effect at the target location will be applied as well.
     pub fn seek_after_primary_effect(&mut self, target: Location) {
         self.seek_after(target, Effect::Primary)
     }
@@ -222,12 +222,12 @@ where
         #[rustfmt::skip]
         let next_effect = if A::Direction::IS_FORWARD {
             self.pos.curr_effect_index.map_or_else(
-                || Effect::Before.at_index(0),
+                || Effect::Early.at_index(0),
                 EffectIndex::next_in_forward_order,
             )
         } else {
             self.pos.curr_effect_index.map_or_else(
-                || Effect::Before.at_index(block_data.statements.len()),
+                || Effect::Early.at_index(block_data.statements.len()),
                 EffectIndex::next_in_backward_order,
             )
         };
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 566a6b09b2b..9d943ebe327 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -66,12 +66,12 @@ impl Direction for Backward {
     {
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.apply_before_terminator_effect(state, terminator, location);
-        analysis.apply_terminator_effect(state, terminator, location);
+        analysis.apply_early_terminator_effect(state, terminator, location);
+        analysis.apply_primary_terminator_effect(state, terminator, location);
         for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
             let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         let exit_state = state;
@@ -159,14 +159,14 @@ impl Direction for Backward {
                 let location = Location { block, statement_index: from.statement_index };
                 let terminator = block_data.terminator();
 
-                if from.effect == Effect::Before {
-                    analysis.apply_before_terminator_effect(state, terminator, location);
-                    if to == Effect::Before.at_index(terminator_index) {
+                if from.effect == Effect::Early {
+                    analysis.apply_early_terminator_effect(state, terminator, location);
+                    if to == Effect::Early.at_index(terminator_index) {
                         return;
                     }
                 }
 
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
                 if to == Effect::Primary.at_index(terminator_index) {
                     return;
                 }
@@ -180,7 +180,7 @@ impl Direction for Backward {
                 let location = Location { block, statement_index: from.statement_index };
                 let statement = &block_data.statements[from.statement_index];
 
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
                 if to == Effect::Primary.at_index(from.statement_index) {
                     return;
                 }
@@ -188,7 +188,7 @@ impl Direction for Backward {
                 from.statement_index - 1
             }
 
-            Effect::Before => from.statement_index,
+            Effect::Early => from.statement_index,
         };
 
         // Handle all statements between `first_unapplied_idx` and `to.statement_index`.
@@ -196,21 +196,21 @@ impl Direction for Backward {
         for statement_index in (to.statement_index..next_effect).rev().map(|i| i + 1) {
             let location = Location { block, statement_index };
             let statement = &block_data.statements[statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         // Handle the statement at `to`.
 
         let location = Location { block, statement_index: to.statement_index };
         let statement = &block_data.statements[to.statement_index];
-        analysis.apply_before_statement_effect(state, statement, location);
+        analysis.apply_early_statement_effect(state, statement, location);
 
-        if to.effect == Effect::Before {
+        if to.effect == Effect::Early {
             return;
         }
 
-        analysis.apply_statement_effect(state, statement, location);
+        analysis.apply_primary_statement_effect(state, statement, location);
     }
 
     fn visit_results_in_block<'mir, 'tcx, A>(
@@ -228,17 +228,17 @@ impl Direction for Backward {
 
         let loc = Location { block, statement_index: block_data.statements.len() };
         let term = block_data.terminator();
-        results.analysis.apply_before_terminator_effect(state, term, loc);
-        vis.visit_terminator_before_primary_effect(results, state, term, loc);
-        results.analysis.apply_terminator_effect(state, term, loc);
-        vis.visit_terminator_after_primary_effect(results, state, term, loc);
+        results.analysis.apply_early_terminator_effect(state, term, loc);
+        vis.visit_after_early_terminator_effect(results, state, term, loc);
+        results.analysis.apply_primary_terminator_effect(state, term, loc);
+        vis.visit_after_primary_terminator_effect(results, state, term, loc);
 
         for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
             let loc = Location { block, statement_index };
-            results.analysis.apply_before_statement_effect(state, stmt, loc);
-            vis.visit_statement_before_primary_effect(results, state, stmt, loc);
-            results.analysis.apply_statement_effect(state, stmt, loc);
-            vis.visit_statement_after_primary_effect(results, state, stmt, loc);
+            results.analysis.apply_early_statement_effect(state, stmt, loc);
+            vis.visit_after_early_statement_effect(results, state, stmt, loc);
+            results.analysis.apply_primary_statement_effect(state, stmt, loc);
+            vis.visit_after_primary_statement_effect(results, state, stmt, loc);
         }
 
         vis.visit_block_start(state);
@@ -294,13 +294,13 @@ impl Direction for Forward {
     {
         for (statement_index, statement) in block_data.statements.iter().enumerate() {
             let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.apply_before_terminator_effect(state, terminator, location);
-        let edges = analysis.apply_terminator_effect(state, terminator, location);
+        analysis.apply_early_terminator_effect(state, terminator, location);
+        let edges = analysis.apply_primary_terminator_effect(state, terminator, location);
 
         let exit_state = state;
         match edges {
@@ -368,21 +368,21 @@ impl Direction for Forward {
         // after effect, do so now and start the loop below from the next statement.
 
         let first_unapplied_index = match from.effect {
-            Effect::Before => from.statement_index,
+            Effect::Early => from.statement_index,
 
             Effect::Primary if from.statement_index == terminator_index => {
                 debug_assert_eq!(from, to);
 
                 let location = Location { block, statement_index: terminator_index };
                 let terminator = block_data.terminator();
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
                 return;
             }
 
             Effect::Primary => {
                 let location = Location { block, statement_index: from.statement_index };
                 let statement = &block_data.statements[from.statement_index];
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
 
                 // If we only needed to apply the after effect of the statement at `idx`, we are
                 // done.
@@ -399,8 +399,8 @@ impl Direction for Forward {
         for statement_index in first_unapplied_index..to.statement_index {
             let location = Location { block, statement_index };
             let statement = &block_data.statements[statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         // Handle the statement or terminator at `to`.
@@ -408,17 +408,17 @@ impl Direction for Forward {
         let location = Location { block, statement_index: to.statement_index };
         if to.statement_index == terminator_index {
             let terminator = block_data.terminator();
-            analysis.apply_before_terminator_effect(state, terminator, location);
+            analysis.apply_early_terminator_effect(state, terminator, location);
 
             if to.effect == Effect::Primary {
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
             }
         } else {
             let statement = &block_data.statements[to.statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
 
             if to.effect == Effect::Primary {
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
             }
         }
     }
@@ -438,18 +438,18 @@ impl Direction for Forward {
 
         for (statement_index, stmt) in block_data.statements.iter().enumerate() {
             let loc = Location { block, statement_index };
-            results.analysis.apply_before_statement_effect(state, stmt, loc);
-            vis.visit_statement_before_primary_effect(results, state, stmt, loc);
-            results.analysis.apply_statement_effect(state, stmt, loc);
-            vis.visit_statement_after_primary_effect(results, state, stmt, loc);
+            results.analysis.apply_early_statement_effect(state, stmt, loc);
+            vis.visit_after_early_statement_effect(results, state, stmt, loc);
+            results.analysis.apply_primary_statement_effect(state, stmt, loc);
+            vis.visit_after_primary_statement_effect(results, state, stmt, loc);
         }
 
         let loc = Location { block, statement_index: block_data.statements.len() };
         let term = block_data.terminator();
-        results.analysis.apply_before_terminator_effect(state, term, loc);
-        vis.visit_terminator_before_primary_effect(results, state, term, loc);
-        results.analysis.apply_terminator_effect(state, term, loc);
-        vis.visit_terminator_after_primary_effect(results, state, term, loc);
+        results.analysis.apply_early_terminator_effect(state, term, loc);
+        vis.visit_after_early_terminator_effect(results, state, term, loc);
+        results.analysis.apply_primary_terminator_effect(state, term, loc);
+        vis.visit_after_primary_terminator_effect(results, state, term, loc);
 
         vis.visit_block_end(state);
     }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index f844e8fbe03..5b2b128e035 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -724,7 +724,7 @@ where
         }
     }
 
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -737,7 +737,7 @@ where
         }
     }
 
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -748,7 +748,7 @@ where
         self.prev_state.clone_from(state)
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -761,7 +761,7 @@ where
         }
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index e063eaf74bd..cb8159ce37b 100644
--- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
@@ -38,10 +38,8 @@
 //! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
 //! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
 
-use std::iter;
-
+use rustc_index::Idx;
 use rustc_index::bit_set::{BitSet, MixedBitSet};
-use rustc_index::{Idx, IndexVec};
 
 use crate::framework::BitSetExt;
 
@@ -70,53 +68,6 @@ pub trait HasTop {
     const TOP: Self;
 }
 
-/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom:
-///
-/// ```text
-///      true
-///        |
-///      false
-/// ```
-impl JoinSemiLattice for bool {
-    fn join(&mut self, other: &Self) -> bool {
-        if let (false, true) = (*self, *other) {
-            *self = true;
-            return true;
-        }
-
-        false
-    }
-}
-
-impl HasBottom for bool {
-    const BOTTOM: Self = false;
-
-    fn is_bottom(&self) -> bool {
-        !self
-    }
-}
-
-impl HasTop for bool {
-    const TOP: Self = true;
-}
-
-/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation
-/// of the least upper bounds of each element of the tuple (or list).
-///
-/// In other words:
-///     (A₀, A₁, ..., Aₙ) ∨ (B₀, B₁, ..., Bₙ) = (A₀∨B₀, A₁∨B₁, ..., Aₙ∨Bₙ)
-impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> {
-    fn join(&mut self, other: &Self) -> bool {
-        assert_eq!(self.len(), other.len());
-
-        let mut changed = false;
-        for (a, b) in iter::zip(self, other) {
-            changed |= a.join(b);
-        }
-        changed
-    }
-}
-
 /// A `BitSet` represents the lattice formed by the powerset of all possible values of
 /// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices,
 /// one for each possible value of `T`.
@@ -197,18 +148,6 @@ impl<T> MaybeReachable<T> {
     }
 }
 
-impl<T> HasBottom for MaybeReachable<T> {
-    const BOTTOM: Self = MaybeReachable::Unreachable;
-
-    fn is_bottom(&self) -> bool {
-        matches!(self, Self::Unreachable)
-    }
-}
-
-impl<T: HasTop> HasTop for MaybeReachable<T> {
-    const TOP: Self = MaybeReachable::Reachable(T::TOP);
-}
-
 impl<S> MaybeReachable<S> {
     /// Return whether the current state contains the given element. If the state is unreachable,
     /// it does no contain anything.
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 7f5a68e884e..41df5fae0de 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -56,7 +56,7 @@ mod visitor;
 pub use self::cursor::ResultsCursor;
 pub use self::direction::{Backward, Direction, Forward};
 pub use self::lattice::{JoinSemiLattice, MaybeReachable};
-pub use self::results::{EntrySets, Results};
+pub use self::results::{EntryStates, Results};
 pub use self::visitor::{ResultsVisitor, visit_results};
 
 /// Analysis domains are all bitsets of various kinds. This trait holds
@@ -122,8 +122,23 @@ pub trait Analysis<'tcx> {
     // `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);
 
+    /// Updates the current dataflow state with an "early" effect, i.e. one
+    /// that occurs immediately before the given statement.
+    ///
+    /// This method is useful if the consumer of the results of this analysis only needs to observe
+    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without also implementing
+    /// `apply_primary_statement_effect`.
+    fn apply_early_statement_effect(
+        &mut self,
+        _state: &mut Self::Domain,
+        _statement: &mir::Statement<'tcx>,
+        _location: Location,
+    ) {
+    }
+
     /// Updates the current dataflow state with the effect of evaluating a statement.
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
@@ -131,15 +146,16 @@ pub trait Analysis<'tcx> {
     );
 
     /// Updates the current dataflow state with an effect that occurs immediately *before* the
-    /// given statement.
+    /// given terminator.
     ///
-    /// This method is useful if the consumer of the results of this analysis only needs to observe
-    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
-    /// analyses should not implement this without also implementing `apply_statement_effect`.
-    fn apply_before_statement_effect(
+    /// This method is useful if the consumer of the results of this analysis needs only to observe
+    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without also implementing
+    /// `apply_primary_terminator_effect`.
+    fn apply_early_terminator_effect(
         &mut self,
         _state: &mut Self::Domain,
-        _statement: &mir::Statement<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         _location: Location,
     ) {
     }
@@ -150,7 +166,7 @@ pub trait Analysis<'tcx> {
     /// in this function. That should go in `apply_call_return_effect`. For example, in the
     /// `InitializedPlaces` analyses, the return place for a function call is not marked as
     /// initialized here.
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         _state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
@@ -159,27 +175,13 @@ pub trait Analysis<'tcx> {
         terminator.edges()
     }
 
-    /// Updates the current dataflow state with an effect that occurs immediately *before* the
-    /// given terminator.
-    ///
-    /// This method is useful if the consumer of the results of this analysis needs only to observe
-    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
-    /// analyses should not implement this without also implementing `apply_terminator_effect`.
-    fn apply_before_terminator_effect(
-        &mut self,
-        _state: &mut Self::Domain,
-        _terminator: &mir::Terminator<'tcx>,
-        _location: Location,
-    ) {
-    }
-
     /* Edge-specific effects */
 
     /// Updates the current dataflow state with the effect of a successful return from a `Call`
     /// terminator.
     ///
-    /// This is separate from `apply_terminator_effect` to properly track state across unwind
-    /// edges.
+    /// This is separate from `apply_primary_terminator_effect` to properly track state across
+    /// unwind edges.
     fn apply_call_return_effect(
         &mut self,
         _state: &mut Self::Domain,
@@ -234,11 +236,12 @@ pub trait Analysis<'tcx> {
         Self: Sized,
         Self::Domain: DebugWithContext<Self>,
     {
-        let mut entry_sets =
+        let mut entry_states =
             IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
-        self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+        self.initialize_start_block(body, &mut entry_states[mir::START_BLOCK]);
 
-        if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
+        if Self::Direction::IS_BACKWARD && entry_states[mir::START_BLOCK] != self.bottom_value(body)
+        {
             bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
         }
 
@@ -262,9 +265,9 @@ pub trait Analysis<'tcx> {
         let mut state = self.bottom_value(body);
         while let Some(bb) = dirty_queue.pop() {
             // Set the state to the entry state of the block.
-            // This is equivalent to `state = entry_sets[bb].clone()`,
+            // This is equivalent to `state = entry_states[bb].clone()`,
             // but it saves an allocation, thus improving compile times.
-            state.clone_from(&entry_sets[bb]);
+            state.clone_from(&entry_states[bb]);
 
             Self::Direction::apply_effects_in_block(
                 &mut self,
@@ -273,7 +276,7 @@ pub trait Analysis<'tcx> {
                 bb,
                 &body[bb],
                 |target: BasicBlock, state: &Self::Domain| {
-                    let set_changed = entry_sets[target].join(state);
+                    let set_changed = entry_states[target].join(state);
                     if set_changed {
                         dirty_queue.insert(target);
                     }
@@ -281,7 +284,7 @@ pub trait Analysis<'tcx> {
             );
         }
 
-        let mut results = Results { analysis: self, entry_sets };
+        let mut results = Results { analysis: self, entry_states };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
             let res = write_graphviz_results(tcx, body, &mut results, pass_name);
@@ -358,11 +361,10 @@ impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> {
 // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 enum Effect {
-    /// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or
-    /// terminator).
-    Before,
+    /// The "early" effect (e.g., `apply_early_statement_effect`) for a statement/terminator.
+    Early,
 
-    /// The "primary" effect (e.g., `apply_statement_effect`) for a statement (or terminator).
+    /// The "primary" effect (e.g., `apply_primary_statement_effect`) for a statement/terminator.
     Primary,
 }
 
@@ -381,15 +383,15 @@ pub struct EffectIndex {
 impl EffectIndex {
     fn next_in_forward_order(self) -> Self {
         match self.effect {
-            Effect::Before => Effect::Primary.at_index(self.statement_index),
-            Effect::Primary => Effect::Before.at_index(self.statement_index + 1),
+            Effect::Early => Effect::Primary.at_index(self.statement_index),
+            Effect::Primary => Effect::Early.at_index(self.statement_index + 1),
         }
     }
 
     fn next_in_backward_order(self) -> Self {
         match self.effect {
-            Effect::Before => Effect::Primary.at_index(self.statement_index),
-            Effect::Primary => Effect::Before.at_index(self.statement_index - 1),
+            Effect::Early => Effect::Primary.at_index(self.statement_index),
+            Effect::Primary => Effect::Early.at_index(self.statement_index - 1),
         }
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index a7dbd99b8ab..8e2c3afddb3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -6,7 +6,7 @@ use rustc_middle::mir::{BasicBlock, Body, traversal};
 use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results};
 use crate::framework::cursor::ResultsHandle;
 
-pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
+pub type EntryStates<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
 
 /// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the
 /// entry of each basic block. Domain values in other parts of the block are recomputed on the fly
@@ -17,7 +17,7 @@ where
     A: Analysis<'tcx>,
 {
     pub analysis: A,
-    pub entry_sets: EntrySets<'tcx, A>,
+    pub entry_states: EntryStates<'tcx, A>,
 }
 
 impl<'tcx, A> Results<'tcx, A>
@@ -40,7 +40,7 @@ where
 
     /// Gets the dataflow state for the given block.
     pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain {
-        &self.entry_sets[block]
+        &self.entry_states[block]
     }
 
     pub fn visit_with<'mir>(
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 14fb6dfb50c..8e7d4ab0fa3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -73,7 +73,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
 ///
 /// The `102` in the block's entry set is derived from the basic block index and ensures that the
 /// expected state is unique across all basic blocks. Remember, it is generated by
-/// `mock_entry_sets`, not from actually running `MockAnalysis` to fixpoint.
+/// `mock_entry_states`, not from actually running `MockAnalysis` to fixpoint.
 struct MockAnalysis<'tcx, D> {
     body: &'tcx mir::Body<'tcx>,
     dir: PhantomData<D>,
@@ -90,7 +90,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
         ret
     }
 
-    fn mock_entry_sets(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
+    fn mock_entry_states(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
         let empty = self.bottom_value(self.body);
         let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks);
 
@@ -104,7 +104,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
     /// Returns the index that should be added to the dataflow state at the given target.
     fn effect(&self, loc: EffectIndex) -> usize {
         let idx = match loc.effect {
-            Effect::Before => loc.statement_index * 2,
+            Effect::Early => loc.statement_index * 2,
             Effect::Primary => loc.statement_index * 2 + 1,
         };
 
@@ -128,14 +128,14 @@ impl<D: Direction> MockAnalysis<'_, D> {
 
         let target = match target {
             SeekTarget::BlockEntry { .. } => return ret,
-            SeekTarget::Before(loc) => Effect::Before.at_index(loc.statement_index),
+            SeekTarget::Early(loc) => Effect::Early.at_index(loc.statement_index),
             SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index),
         };
 
         let mut pos = if D::IS_FORWARD {
-            Effect::Before.at_index(0)
+            Effect::Early.at_index(0)
         } else {
-            Effect::Before.at_index(self.body[block].statements.len())
+            Effect::Early.at_index(self.body[block].statements.len())
         };
 
         loop {
@@ -168,52 +168,52 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
         unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
     }
 
-    fn apply_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
+        let idx = self.effect(Effect::Early.at_index(location.statement_index));
         assert!(state.insert(idx));
     }
 
-    fn apply_before_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        let idx = self.effect(Effect::Before.at_index(location.statement_index));
+        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
         assert!(state.insert(idx));
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_early_terminator_effect(
         &mut self,
         state: &mut Self::Domain,
-        terminator: &'mir mir::Terminator<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         location: Location,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
+    ) {
+        let idx = self.effect(Effect::Early.at_index(location.statement_index));
         assert!(state.insert(idx));
-        terminator.edges()
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        _terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
-        let idx = self.effect(Effect::Before.at_index(location.statement_index));
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
         assert!(state.insert(idx));
+        terminator.edges()
     }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum SeekTarget {
     BlockEntry(BasicBlock),
-    Before(Location),
+    Early(Location),
     After(Location),
 }
 
@@ -223,7 +223,7 @@ impl SeekTarget {
 
         match *self {
             BlockEntry(block) => block,
-            Before(loc) | After(loc) => loc.block,
+            Early(loc) | After(loc) => loc.block,
         }
     }
 
@@ -235,7 +235,7 @@ impl SeekTarget {
             .map(move |(i, kind)| {
                 let loc = Location { block, statement_index: i };
                 match kind {
-                    0 => SeekTarget::Before(loc),
+                    0 => SeekTarget::Early(loc),
                     1 => SeekTarget::After(loc),
                     _ => unreachable!(),
                 }
@@ -249,7 +249,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
     let body = analysis.body;
 
     let mut cursor =
-        Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
+        Results { entry_states: analysis.mock_entry_states(), analysis }.into_results_cursor(body);
 
     cursor.allow_unreachable();
 
@@ -262,7 +262,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
 
         match targ {
             BlockEntry(block) => cursor.seek_to_block_entry(block),
-            Before(loc) => cursor.seek_before_primary_effect(loc),
+            Early(loc) => cursor.seek_before_primary_effect(loc),
             After(loc) => cursor.seek_after_primary_effect(loc),
         }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index bde41974d47..d18e9fa33f0 100644
--- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -35,9 +35,9 @@ where
 {
     fn visit_block_start(&mut self, _state: &A::Domain) {}
 
-    /// Called with the `before_statement_effect` of the given statement applied to `state` but not
-    /// its `statement_effect`.
-    fn visit_statement_before_primary_effect(
+    /// // njn: grep for "before", "primary", etc.
+    /// Called after the "early" effect of the given statement is applied to `state`.
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -46,9 +46,8 @@ where
     ) {
     }
 
-    /// Called with both the `before_statement_effect` and the `statement_effect` of the given
-    /// statement applied to `state`.
-    fn visit_statement_after_primary_effect(
+    /// Called after the "primary" effect of the given statement is applied to `state`.
+    fn visit_after_primary_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -57,9 +56,8 @@ where
     ) {
     }
 
-    /// Called with the `before_terminator_effect` of the given terminator applied to `state` but
-    /// not its `terminator_effect`.
-    fn visit_terminator_before_primary_effect(
+    /// Called after the "early" effect of the given terminator is applied to `state`.
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -68,11 +66,10 @@ where
     ) {
     }
 
-    /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
-    /// terminator applied to `state`.
+    /// Called after the "primary" effect of the given terminator is applied to `state`.
     ///
     /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index cec654cac72..568d8a5acaf 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -33,22 +33,22 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
         // No locals are aliased on function entry
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &Statement<'tcx>,
         location: Location,
     ) {
-        Self::transfer_function(trans).visit_statement(statement, location);
+        Self::transfer_function(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        Self::transfer_function(trans).visit_terminator(terminator, location);
+        Self::transfer_function(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 91677657602..fb02408e17d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -70,7 +70,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
     pub fn is_unwind_dead(
         &self,
         place: mir::Place<'tcx>,
-        state: &MaybeReachable<MixedBitSet<MovePathIndex>>,
+        state: &<Self as Analysis<'tcx>>::Domain,
     ) -> bool {
         if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
             let mut maybe_live = false;
@@ -218,26 +218,26 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
 impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
     fn update_bits(
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         path: MovePathIndex,
-        state: DropFlagState,
+        dfstate: DropFlagState,
     ) {
-        match state {
-            DropFlagState::Absent => trans.kill(path),
-            DropFlagState::Present => trans.gen_(path),
+        match dfstate {
+            DropFlagState::Absent => state.kill(path),
+            DropFlagState::Present => state.gen_(path),
         }
     }
 }
 
 impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
     fn update_bits(
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         path: MovePathIndex,
-        state: DropFlagState,
+        dfstate: DropFlagState,
     ) {
-        match state {
-            DropFlagState::Absent => trans.gen_(path),
-            DropFlagState::Present => trans.kill(path),
+        match dfstate {
+            DropFlagState::Absent => state.gen_(path),
+            DropFlagState::Present => state.kill(path),
         }
     }
 }
@@ -263,14 +263,14 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         });
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
 
         // Mark all places as "maybe init" if they are mutably borrowed. See #90752.
@@ -282,12 +282,12 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
             && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
         {
             on_all_children_bits(self.move_data(), mpi, |child| {
-                trans.gen_(child);
+                state.gen_(child);
             })
         }
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
@@ -309,7 +309,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -320,7 +320,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 self.move_data().rev_lookup.find(place.as_ref()),
                 |mpi| {
-                    trans.gen_(mpi);
+                    state.gen_(mpi);
                 },
             );
         });
@@ -345,7 +345,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         };
 
         let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
+        edge_effects.apply(|state, edge| {
             let Some(value) = edge.value else {
                 return;
             };
@@ -363,25 +363,27 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 enum_place,
                 variant,
-                |mpi| trans.kill(mpi),
+                |mpi| state.kill(mpi),
             );
         });
     }
 }
 
+/// There can be many more `MovePathIndex` than there are locals in a MIR body.
+/// We use a mixed bitset to avoid paying too high a memory footprint.
+pub type MaybeUninitializedPlacesDomain = MixedBitSet<MovePathIndex>;
+
 impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
-    /// There can be many more `MovePathIndex` than there are locals in a MIR body.
-    /// We use a mixed bitset to avoid paying too high a memory footprint.
-    type Domain = MixedBitSet<MovePathIndex>;
+    type Domain = MaybeUninitializedPlacesDomain;
 
     const NAME: &'static str = "maybe_uninit";
 
     fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = initialized (start_block_effect counters this at outset)
+        // bottom = initialized (`initialize_start_block` overwrites this on first entry)
         MixedBitSet::new_empty(self.move_data().move_paths.len())
     }
 
-    // sets on_entry bits for Arg places
+    // sets state bits for Arg places
     fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
         // set all bits to 1 (uninit) before gathering counter-evidence
         state.insert_all();
@@ -392,28 +394,28 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         });
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
 
         // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a
         // mutable borrow occurs. Places cannot become uninitialized through a mutable reference.
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
         if self.skip_unreachable_unwind.contains(location.block) {
             let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() };
@@ -426,7 +428,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -437,7 +439,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 self.move_data().rev_lookup.find(place.as_ref()),
                 |mpi| {
-                    trans.kill(mpi);
+                    state.kill(mpi);
                 },
             );
         });
@@ -466,7 +468,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         };
 
         let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
+        edge_effects.apply(|state, edge| {
             let Some(value) = edge.value else {
                 return;
             };
@@ -484,16 +486,18 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 enum_place,
                 variant,
-                |mpi| trans.gen_(mpi),
+                |mpi| state.gen_(mpi),
             );
         });
     }
 }
 
+/// There can be many more `InitIndex` than there are locals in a MIR body.
+/// We use a mixed bitset to avoid paying too high a memory footprint.
+pub type EverInitializedPlacesDomain = MixedBitSet<InitIndex>;
+
 impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
-    /// There can be many more `InitIndex` than there are locals in a MIR body.
-    /// We use a mixed bitset to avoid paying too high a memory footprint.
-    type Domain = MixedBitSet<InitIndex>;
+    type Domain = EverInitializedPlacesDomain;
 
     const NAME: &'static str = "ever_init";
 
@@ -508,10 +512,10 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         }
     }
 
-    #[instrument(skip(self, trans), level = "debug")]
-    fn apply_statement_effect(
+    #[instrument(skip(self, state), level = "debug")]
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -521,7 +525,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         let rev_lookup = &move_data.rev_lookup;
 
         debug!("initializes move_indexes {:?}", init_loc_map[location]);
-        trans.gen_all(init_loc_map[location].iter().copied());
+        state.gen_all(init_loc_map[location].iter().copied());
 
         if let mir::StatementKind::StorageDead(local) = stmt.kind {
             // End inits for StorageDead, so that an immutable variable can
@@ -531,15 +535,15 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
                     "clears the ever initialized status of {:?}",
                     init_path_map[move_path_index]
                 );
-                trans.kill_all(init_path_map[move_path_index].iter().copied());
+                state.kill_all(init_path_map[move_path_index].iter().copied());
             }
         }
     }
 
-    #[instrument(skip(self, trans, terminator), level = "debug")]
-    fn apply_terminator_effect<'mir>(
+    #[instrument(skip(self, state, terminator), level = "debug")]
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
@@ -548,7 +552,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         let init_loc_map = &move_data.init_loc_map;
         debug!(?term);
         debug!("initializes move_indexes {:?}", init_loc_map[location]);
-        trans.gen_all(
+        state.gen_all(
             init_loc_map[location]
                 .iter()
                 .filter(|init_index| {
@@ -561,7 +565,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         block: mir::BasicBlock,
         _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -570,7 +574,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
         let call_loc = self.body.terminator_loc(block);
         for init_index in &init_loc_map[call_loc] {
-            trans.gen_(*init_index);
+            state.gen_(*init_index);
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index fd7254a0210..b2050a6adf9 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -40,33 +40,33 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
         // No variables are live until we observe a use
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        TransferFunction(trans).visit_statement(statement, location);
+        TransferFunction(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        TransferFunction(trans).visit_terminator(terminator, location);
+        TransferFunction(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         if let CallReturnPlaces::Yield(resume_place) = return_places {
-            YieldResumeEffect(trans).visit_place(
+            YieldResumeEffect(state).visit_place(
                 &resume_place,
                 PlaceContext::MutatingUse(MutatingUseContext::Yield),
                 Location::START,
@@ -74,7 +74,7 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
         } else {
             return_places.for_each(|place| {
                 if let Some(local) = place.as_local() {
-                    trans.kill(local);
+                    state.kill(local);
                 }
             });
         }
@@ -137,10 +137,10 @@ enum DefUse {
 }
 
 impl DefUse {
-    fn apply(trans: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) {
+    fn apply(state: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) {
         match DefUse::for_place(place, context) {
-            Some(DefUse::Def) => trans.kill(place.local),
-            Some(DefUse::Use) => trans.gen_(place.local),
+            Some(DefUse::Def) => state.kill(place.local),
+            Some(DefUse::Use) => state.gen_(place.local),
             None => {}
         }
     }
@@ -232,9 +232,9 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         // No variables are live until we observe a use
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -258,34 +258,34 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         };
         if let Some(destination) = destination {
             if !destination.is_indirect()
-                && !trans.contains(destination.local)
+                && !state.contains(destination.local)
                 && !self.always_live.contains(destination.local)
             {
                 // This store is dead
                 return;
             }
         }
-        TransferFunction(trans).visit_statement(statement, location);
+        TransferFunction(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        TransferFunction(trans).visit_terminator(terminator, location);
+        TransferFunction(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         if let CallReturnPlaces::Yield(resume_place) = return_places {
-            YieldResumeEffect(trans).visit_place(
+            YieldResumeEffect(state).visit_place(
                 &resume_place,
                 PlaceContext::MutatingUse(MutatingUseContext::Yield),
                 Location::START,
@@ -293,7 +293,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         } else {
             return_places.for_each(|place| {
                 if let Some(local) = place.as_local() {
-                    trans.remove(local);
+                    state.remove(local);
                 }
             });
         }
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index d69a8019c8d..3f29b819a6d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -5,7 +5,8 @@ mod storage_liveness;
 
 pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals};
 pub use self::initialized::{
-    EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
+    EverInitializedPlaces, EverInitializedPlacesDomain, MaybeInitializedPlaces,
+    MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain,
 };
 pub use self::liveness::{
     MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction,
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 1aae06d79d3..65b480d3a5e 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -44,23 +44,23 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
-        on_entry.union(&*self.always_live_locals);
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
+        state.union(&*self.always_live_locals);
 
         for arg in body.args_iter() {
-            on_entry.insert(arg);
+            state.insert(arg);
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
-            StatementKind::StorageLive(l) => trans.gen_(l),
-            StatementKind::StorageDead(l) => trans.kill(l),
+            StatementKind::StorageLive(l) => state.gen_(l),
+            StatementKind::StorageDead(l) => state.kill(l),
             _ => (),
         }
     }
@@ -86,25 +86,25 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
         assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
         // Do not iterate on return place and args, as they are trivially always live.
         for local in body.vars_and_temps_iter() {
             if !self.always_live_locals.contains(local) {
-                on_entry.insert(local);
+                state.insert(local);
             }
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
-            StatementKind::StorageLive(l) => trans.kill(l),
-            StatementKind::StorageDead(l) => trans.gen_(l),
+            StatementKind::StorageLive(l) => state.kill(l),
+            StatementKind::StorageDead(l) => state.gen_(l),
             _ => (),
         }
     }
@@ -134,31 +134,31 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
         // The resume argument is live on function entry (we don't care about
         // the `self` argument)
         for arg in body.args_iter().skip(1) {
-            on_entry.insert(arg);
+            state.insert(arg);
         }
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a statement, it needs storage for that statement.
-        MaybeBorrowedLocals::transfer_function(trans).visit_statement(stmt, loc);
+        MaybeBorrowedLocals::transfer_function(state).visit_statement(stmt, loc);
 
         match &stmt.kind {
-            StatementKind::StorageDead(l) => trans.kill(*l),
+            StatementKind::StorageDead(l) => state.kill(*l),
 
             // If a place is assigned to in a statement, it needs storage for that statement.
             StatementKind::Assign(box (place, _))
             | StatementKind::SetDiscriminant { box place, .. }
             | StatementKind::Deinit(box place) => {
-                trans.gen_(place.local);
+                state.gen_(place.local);
             }
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -176,29 +176,29 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _: &Statement<'tcx>,
         loc: Location,
     ) {
         // If we move from a place then it only stops needing storage *after*
         // that statement.
-        self.check_for_move(trans, loc);
+        self.check_for_move(state, loc);
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &Terminator<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a terminator, it needs storage for that terminator.
-        MaybeBorrowedLocals::transfer_function(trans).visit_terminator(terminator, loc);
+        MaybeBorrowedLocals::transfer_function(state).visit_terminator(terminator, loc);
 
         match &terminator.kind {
             TerminatorKind::Call { destination, .. } => {
-                trans.gen_(destination.local);
+                state.gen_(destination.local);
             }
 
             // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
@@ -213,7 +213,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
                         InlineAsmOperand::Out { place, .. }
                         | InlineAsmOperand::InOut { out_place: place, .. } => {
                             if let Some(place) = place {
-                                trans.gen_(place.local);
+                                state.gen_(place.local);
                             }
                         }
                         InlineAsmOperand::In { .. }
@@ -242,9 +242,9 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         }
     }
 
-    fn apply_terminator_effect<'t>(
+    fn apply_primary_terminator_effect<'t>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'t Terminator<'tcx>,
         loc: Location,
     ) -> TerminatorEdges<'t, 'tcx> {
@@ -254,12 +254,12 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
             // Since `propagate_call_unwind` doesn't exist, we have to kill the
             // destination here, and then gen it again in `call_return_effect`.
             TerminatorKind::Call { destination, .. } => {
-                trans.kill(destination.local);
+                state.kill(destination.local);
             }
 
             // The same applies to InlineAsm outputs.
             TerminatorKind::InlineAsm { ref operands, .. } => {
-                CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local));
+                CallReturnPlaces::InlineAsm(operands).for_each(|place| state.kill(place.local));
             }
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -279,32 +279,32 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
             | TerminatorKind::Unreachable => {}
         }
 
-        self.check_for_move(trans, loc);
+        self.check_for_move(state, loc);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        return_places.for_each(|place| trans.gen_(place.local));
+        return_places.for_each(|place| state.gen_(place.local));
     }
 }
 
 impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
     /// Kill locals that are fully moved and have not been borrowed.
-    fn check_for_move(&mut self, trans: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) {
+    fn check_for_move(&mut self, state: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) {
         let body = self.borrowed_locals.body();
-        let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals };
+        let mut visitor = MoveVisitor { state, borrowed_locals: &mut self.borrowed_locals };
         visitor.visit_location(body, loc);
     }
 }
 
 struct MoveVisitor<'a, 'mir, 'tcx> {
     borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>,
-    trans: &'a mut BitSet<Local>,
+    state: &'a mut BitSet<Local>,
 }
 
 impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
@@ -312,7 +312,7 @@ impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
         if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
             self.borrowed_locals.seek_before_primary_effect(loc);
             if !self.borrowed_locals.get().contains(local) {
-                self.trans.kill(local);
+                self.state.kill(local);
             }
         }
     }
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 2248972cecc..85255db5d9a 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -18,7 +18,7 @@ pub use self::drop_flag_effects::{
     move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
 };
 pub use self::framework::{
-    Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable,
+    Analysis, Backward, Direction, EntryStates, Forward, GenKill, JoinSemiLattice, MaybeReachable,
     Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
     visit_results,
 };
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index df4c0593246..d79d2c316ee 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
@@ -4,52 +4,26 @@
 //! field-deref on a local variable, `x.field`, has the same meaning
 //! in both domains). Indexed projections are the exception: `a[x]`
 //! needs to be treated as mapping to the same move path as `a[y]` as
-//! well as `a[13]`, etc.
+//! well as `a[13]`, etc. So we map these `x`/`y` values to `()`.
 //!
 //! (In theory, the analysis could be extended to work with sets of
 //! paths, so that `a[0]` and `a[13]` could be kept distinct, while
 //! `a[x]` would still overlap them both. But that is not this
 //! representation does today.)
 
-use rustc_middle::mir::{Local, Operand, PlaceElem, ProjectionElem};
-use rustc_middle::ty::Ty;
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub(crate) struct AbstractOperand;
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub(crate) struct AbstractType;
-pub(crate) type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
+use rustc_middle::mir::{PlaceElem, ProjectionElem, ProjectionKind};
 
 pub(crate) trait Lift {
-    type Abstract;
-    fn lift(&self) -> Self::Abstract;
-}
-impl<'tcx> Lift for Operand<'tcx> {
-    type Abstract = AbstractOperand;
-    fn lift(&self) -> Self::Abstract {
-        AbstractOperand
-    }
-}
-impl Lift for Local {
-    type Abstract = AbstractOperand;
-    fn lift(&self) -> Self::Abstract {
-        AbstractOperand
-    }
-}
-impl<'tcx> Lift for Ty<'tcx> {
-    type Abstract = AbstractType;
-    fn lift(&self) -> Self::Abstract {
-        AbstractType
-    }
+    fn lift(&self) -> ProjectionKind;
 }
+
 impl<'tcx> Lift for PlaceElem<'tcx> {
-    type Abstract = AbstractElem;
-    fn lift(&self) -> Self::Abstract {
+    fn lift(&self) -> ProjectionKind {
         match *self {
             ProjectionElem::Deref => ProjectionElem::Deref,
-            ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
-            ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()),
-            ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
+            ProjectionElem::Field(f, _ty) => ProjectionElem::Field(f, ()),
+            ProjectionElem::OpaqueCast(_ty) => ProjectionElem::OpaqueCast(()),
+            ProjectionElem::Index(_i) => ProjectionElem::Index(()),
             ProjectionElem::Subslice { from, to, from_end } => {
                 ProjectionElem::Subslice { from, to, from_end }
             }
@@ -57,7 +31,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
                 ProjectionElem::ConstantIndex { offset, min_length, from_end }
             }
             ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u),
-            ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty.lift()),
+            ProjectionElem::Subtype(_ty) => ProjectionElem::Subtype(()),
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 926bd187431..8aea8d2ae3c 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::Span;
 use smallvec::SmallVec;
 
-use self::abs_domain::{AbstractElem, Lift};
+use self::abs_domain::Lift;
 use crate::un_derefer::UnDerefer;
 
 mod abs_domain;
@@ -300,7 +300,7 @@ pub struct MovePathLookup<'tcx> {
     /// subsequent search so that it is solely relative to that
     /// base-place). For the remaining lookup, we map the projection
     /// elem to the associated MovePathIndex.
-    projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>,
+    projections: FxHashMap<(MovePathIndex, ProjectionKind), MovePathIndex>,
 
     un_derefer: UnDerefer<'tcx>,
 }
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index 10f1e009855..74209da876a 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -125,7 +125,7 @@ where
     A: Analysis<'tcx, Domain = BitSet<N>>,
     N: Idx,
 {
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -139,7 +139,7 @@ where
         });
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 34ef8afdde3..85cf8ca2104 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,6 +1,5 @@
 use rustc_ast::MetaItem;
 use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -254,7 +253,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
         &self,
         tcx: TyCtxt<'tcx>,
         place: mir::Place<'tcx>,
-        state: &BitSet<Local>,
+        state: &Self::Domain,
         call: PeekCall,
     ) {
         info!(?place, "peek_at");
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index ed8678de1eb..9328870c7ae 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -67,7 +67,7 @@ impl<V: Clone> Clone for StateData<V> {
     }
 }
 
-impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for StateData<V> {
+impl<V: JoinSemiLattice + Clone> JoinSemiLattice for StateData<V> {
     fn join(&mut self, other: &Self) -> bool {
         let mut changed = false;
         #[allow(rustc::potential_query_instability)]
@@ -342,7 +342,7 @@ impl<V: Clone + HasBottom> State<V> {
     }
 }
 
-impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for State<V> {
+impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> {
     fn join(&mut self, other: &Self) -> bool {
         match (&mut *self, other) {
             (_, State::Unreachable) => false,
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 858752a3f01..31d5245fb5c 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -878,7 +878,7 @@ struct StorageConflictVisitor<'a, 'tcx> {
 impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
     for StorageConflictVisitor<'a, 'tcx>
 {
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &BitSet<Local>,
@@ -888,7 +888,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
         self.apply_state(state, loc);
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &BitSet<Local>,
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 36eb435c63a..ef61866e902 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -3,8 +3,6 @@
 //!
 //! Consider an async closure like:
 //! ```rust
-//! #![feature(async_closure)]
-//!
 //! let x = vec![1, 2, 3];
 //!
 //! let closure = async move || {
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index b94c925b1db..711cf2edc46 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -106,7 +106,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &Statement<'tcx>,
@@ -117,7 +117,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         }
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir Terminator<'tcx>,
@@ -224,7 +224,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     }
 
     /// The effect of a successful function call return should not be
-    /// applied here, see [`Analysis::apply_terminator_effect`].
+    /// applied here, see [`Analysis::apply_primary_terminator_effect`].
     fn handle_terminator<'mir>(
         &self,
         terminator: &'mir Terminator<'tcx>,
@@ -954,7 +954,7 @@ fn try_write_constant<'tcx>(
 
 impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> {
     #[instrument(level = "trace", skip(self, results, statement))]
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
@@ -976,7 +976,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
     }
 
     #[instrument(level = "trace", skip(self, results, statement))]
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
@@ -1001,7 +1001,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
         }
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 0c0f3b61977..3ebc9113725 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -127,7 +127,7 @@ impl InitializationData<'_, '_> {
         self.uninits.seek_before_primary_effect(loc);
     }
 
-    fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) {
+    fn maybe_init_uninit(&self, path: MovePathIndex) -> (bool, bool) {
         (self.inits.get().contains(path), self.uninits.get().contains(path))
     }
 }
@@ -153,23 +153,23 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self), ret)]
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
-        let ((maybe_live, maybe_dead), multipart) = match mode {
-            DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false),
+        let ((maybe_init, maybe_uninit), multipart) = match mode {
+            DropFlagMode::Shallow => (self.init_data.maybe_init_uninit(path), false),
             DropFlagMode::Deep => {
-                let mut some_live = false;
-                let mut some_dead = false;
+                let mut some_maybe_init = false;
+                let mut some_maybe_uninit = false;
                 let mut children_count = 0;
                 on_all_children_bits(self.move_data(), path, |child| {
-                    let (live, dead) = self.init_data.maybe_live_dead(child);
-                    debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
-                    some_live |= live;
-                    some_dead |= dead;
+                    let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child);
+                    debug!("elaborate_drop: state({:?}) = {:?}", child, (maybe_init, maybe_uninit));
+                    some_maybe_init |= maybe_init;
+                    some_maybe_uninit |= maybe_uninit;
                     children_count += 1;
                 });
-                ((some_live, some_dead), children_count != 1)
+                ((some_maybe_init, some_maybe_uninit), children_count != 1)
             }
         };
-        match (maybe_live, maybe_dead, multipart) {
+        match (maybe_init, maybe_uninit, multipart) {
             (false, _, _) => DropStyle::Dead,
             (true, false, _) => DropStyle::Static,
             (true, true, false) => DropStyle::Conditional,
@@ -283,15 +283,15 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                 LookupResult::Exact(path) => {
                     self.init_data.seek_before(self.body.terminator_loc(bb));
                     on_all_children_bits(self.move_data(), path, |child| {
-                        let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child);
+                        let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child);
                         debug!(
                             "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
                             child,
                             place,
                             path,
-                            (maybe_live, maybe_dead)
+                            (maybe_init, maybe_uninit)
                         );
-                        if maybe_live && maybe_dead {
+                        if maybe_init && maybe_uninit {
                             self.create_drop_flag(child, terminator.source_info.span)
                         }
                     });
@@ -303,8 +303,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                     }
 
                     self.init_data.seek_before(self.body.terminator_loc(bb));
-                    let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent);
-                    if maybe_dead {
+                    let (_maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(parent);
+                    if maybe_uninit {
                         self.tcx.dcx().span_delayed_bug(
                             terminator.source_info.span,
                             format!(
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index f0fcb44603b..5c090bf7cad 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -189,6 +189,7 @@ declare_passes! {
     mod simplify_comparison_integral : SimplifyComparisonIntegral;
     mod single_use_consts : SingleUseConsts;
     mod sroa : ScalarReplacementOfAggregates;
+    mod strip_debuginfo : StripDebugInfo;
     mod unreachable_enum_branching : UnreachableEnumBranching;
     mod unreachable_prop : UnreachablePropagation;
     mod validate : Validator;
@@ -699,6 +700,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
+            // After the last SimplifyCfg, because this wants one-block functions.
+            &strip_debuginfo::StripDebugInfo,
             &copy_prop::CopyProp,
             &dead_store_elimination::DeadStoreElimination::Final,
             &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index b8383e734e2..722da3c420d 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -9,6 +9,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{
     self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt,
 };
@@ -710,6 +711,13 @@ fn build_call_shim<'tcx>(
     };
 
     let def_id = instance.def_id();
+
+    let rpitit_shim = if let ty::InstanceKind::ReifyShim(..) = instance {
+        tcx.return_position_impl_trait_in_trait_shim_data(def_id)
+    } else {
+        None
+    };
+
     let sig = tcx.fn_sig(def_id);
     let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
 
@@ -765,9 +773,34 @@ fn build_call_shim<'tcx>(
     let mut local_decls = local_decls_for_sig(&sig, span);
     let source_info = SourceInfo::outermost(span);
 
+    let mut destination = Place::return_place();
+    if let Some((rpitit_def_id, fn_args)) = rpitit_shim {
+        let rpitit_args =
+            fn_args.instantiate_identity().extend_to(tcx, rpitit_def_id, |param, _| {
+                match param.kind {
+                    ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                    ty::GenericParamDefKind::Type { .. }
+                    | ty::GenericParamDefKind::Const { .. } => {
+                        unreachable!("rpitit should have no addition ty/ct")
+                    }
+                }
+            });
+        let dyn_star_ty = Ty::new_dynamic(
+            tcx,
+            tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args),
+            tcx.lifetimes.re_erased,
+            ty::DynStar,
+        );
+        destination = local_decls.push(local_decls[RETURN_PLACE].clone()).into();
+        local_decls[RETURN_PLACE].ty = dyn_star_ty;
+        let mut inputs_and_output = sig.inputs_and_output.to_vec();
+        *inputs_and_output.last_mut().unwrap() = dyn_star_ty;
+        sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
+    }
+
     let rcvr_place = || {
         assert!(rcvr_adjustment.is_some());
-        Place::from(Local::new(1 + 0))
+        Place::from(Local::new(1))
     };
     let mut statements = vec![];
 
@@ -854,7 +887,7 @@ fn build_call_shim<'tcx>(
         TerminatorKind::Call {
             func: callee,
             args,
-            destination: Place::return_place(),
+            destination,
             target: Some(BasicBlock::new(1)),
             unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
                 UnwindAction::Cleanup(BasicBlock::new(3))
@@ -882,7 +915,24 @@ fn build_call_shim<'tcx>(
         );
     }
     // BB #1/#2 - return
-    block(&mut blocks, vec![], TerminatorKind::Return, false);
+    // NOTE: If this is an RPITIT in dyn, we also want to coerce
+    // the return type of the function into a `dyn*`.
+    let stmts = if rpitit_shim.is_some() {
+        vec![Statement {
+            source_info,
+            kind: StatementKind::Assign(Box::new((
+                Place::return_place(),
+                Rvalue::Cast(
+                    CastKind::PointerCoercion(PointerCoercion::DynStar, CoercionSource::Implicit),
+                    Operand::Move(destination),
+                    sig.output(),
+                ),
+            ))),
+        }]
+    } else {
+        vec![]
+    };
+    block(&mut blocks, stmts, TerminatorKind::Return, false);
     if let Some(Adjustment::RefMut) = rcvr_adjustment {
         // BB #3 - drop if closure panics
         block(
diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
new file mode 100644
index 00000000000..438c75726bb
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
@@ -0,0 +1,34 @@
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::config::MirStripDebugInfo;
+
+/// Conditionally remove some of the VarDebugInfo in MIR.
+///
+/// In particular, stripping non-parameter debug info for tiny, primitive-like
+/// methods in core saves work later, and nobody ever wanted to use it anyway.
+pub(super) struct StripDebugInfo;
+
+impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        match tcx.sess.opts.unstable_opts.mir_strip_debuginfo {
+            MirStripDebugInfo::None => return,
+            MirStripDebugInfo::AllLocals => {}
+            MirStripDebugInfo::LocalsInTinyFunctions
+                if let TerminatorKind::Return { .. } =
+                    body.basic_blocks[START_BLOCK].terminator().kind => {}
+            MirStripDebugInfo::LocalsInTinyFunctions => return,
+        }
+
+        body.var_debug_info.retain(|vdi| {
+            matches!(
+                vdi.value,
+                VarDebugInfoContents::Place(place)
+                    if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE,
+            )
+        });
+    }
+}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index caae54cd559..714b64b3a23 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -42,7 +42,10 @@ fn custom_coerce_unsize_info<'tcx>(
             ..
         })) => Ok(tcx.coerce_unsized_info(impl_def_id)?.custom_kind.unwrap()),
         impl_source => {
-            bug!("invalid `CoerceUnsized` impl_source: {:?}", impl_source);
+            bug!(
+                "invalid `CoerceUnsized` from {source_ty} to {target_ty}: impl_source: {:?}",
+                impl_source
+            );
         }
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index f5b1b23b8e9..63dbee2640b 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -144,7 +144,7 @@ where
         then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
     ) -> Result<Candidate<I>, NoSolution> {
         if let Some(projection_pred) = assumption.as_projection_clause() {
-            if projection_pred.projection_def_id() == goal.predicate.def_id() {
+            if projection_pred.item_def_id() == goal.predicate.def_id() {
                 let cx = ecx.cx();
                 if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
                     goal.predicate.alias.args,
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index c6c9eb3b0b2..ee38f16d4ec 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,7 +1,7 @@
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
-use rustc_errors::{Applicability, PErr};
+use rustc_errors::{Applicability, Diag};
 use rustc_span::symbol::kw;
 
 use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level};
@@ -14,7 +14,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
     pub(super) fn lex_token_trees(
         &mut self,
         is_delimited: bool,
-    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'psess>>>) {
+    ) -> (Spacing, TokenStream, Result<(), Vec<Diag<'psess>>>) {
         // Move past the opening delimiter.
         let open_spacing = self.bump_minimal();
 
@@ -56,7 +56,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         }
     }
 
-    fn eof_err(&mut self) -> PErr<'psess> {
+    fn eof_err(&mut self) -> Diag<'psess> {
         let msg = "this file contains an unclosed delimiter";
         let mut err = self.dcx().struct_span_err(self.token.span, msg);
 
@@ -98,7 +98,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
     fn lex_token_tree_open_delim(
         &mut self,
         open_delim: Delimiter,
-    ) -> Result<TokenTree, Vec<PErr<'psess>>> {
+    ) -> Result<TokenTree, Vec<Diag<'psess>>> {
         // The span for beginning of the delimited section.
         let pre_span = self.token.span;
 
@@ -250,8 +250,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
     fn unclosed_delim_err(
         &mut self,
         tts: TokenStream,
-        mut errs: Vec<PErr<'psess>>,
-    ) -> Vec<PErr<'psess>> {
+        mut errs: Vec<Diag<'psess>>,
+    ) -> Vec<Diag<'psess>> {
         // If there are unclosed delims, see if there are diff markers and if so, point them
         // out instead of complaining about the unclosed delims.
         let mut parser = Parser::new(self.psess, tts, None);
@@ -308,7 +308,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         errs
     }
 
-    fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> {
+    fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> {
         // An unexpected closing delimiter (i.e., there is no matching opening delimiter).
         let token_str = token_to_string(&self.token);
         let msg = format!("unexpected closing delimiter: `{token_str}`");
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 34131e3af6e..e5edf605d82 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -16,7 +16,7 @@ use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic,
+    Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PResult, Subdiagnostic,
     Suggestions, pluralize,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
@@ -2132,7 +2132,7 @@ impl<'a> Parser<'a> {
         &mut self,
         delim: Delimiter,
         lo: Span,
-        err: PErr<'a>,
+        err: Diag<'a>,
     ) -> P<Expr> {
         let guar = err.emit();
         // Recover from parse error, callers expect the closing delim to be consumed.
@@ -3014,7 +3014,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Check for exclusive ranges written as `..<`
-    pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
+    pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: Diag<'a>) -> Diag<'a> {
         if maybe_lt == token::Lt
             && (self.expected_tokens.contains(&TokenType::Token(token::Gt))
                 || matches!(self.token.kind, token::Literal(..)))
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index eeb83a85e59..44f42e5fbf2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1369,11 +1369,14 @@ impl<'a> Parser<'a> {
             ))
         } else {
             // Field access `expr.f`
+            let span = lo.to(self.prev_token.span);
             if let Some(args) = seg.args {
-                self.dcx().emit_err(errors::FieldExpressionWithGeneric(args.span()));
+                // See `StashKey::GenericInFieldExpr` for more info on why we stash this.
+                self.dcx()
+                    .create_err(errors::FieldExpressionWithGeneric(args.span()))
+                    .stash(seg.ident.span, StashKey::GenericInFieldExpr);
             }
 
-            let span = lo.to(self.prev_token.span);
             Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
         }
     }
@@ -2363,10 +2366,7 @@ impl<'a> Parser<'a> {
         };
 
         match coroutine_kind {
-            Some(CoroutineKind::Async { span, .. }) => {
-                // Feature-gate `async ||` closures.
-                self.psess.gated_spans.gate(sym::async_closure, span);
-            }
+            Some(CoroutineKind::Async { .. }) => {}
             Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
                 // Feature-gate `gen ||` and `async gen ||` closures.
                 // FIXME(gen_blocks): This perhaps should be a different gate.
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 58b4bf8980b..e27fc963eb9 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -45,7 +45,7 @@ impl<'a> Parser<'a> {
             let (inner_attrs, items, inner_span) =
                 self.parse_mod(&token::CloseDelim(Delimiter::Brace))?;
             attrs.extend(inner_attrs);
-            ModKind::Loaded(items, Inline::Yes, inner_span)
+            ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
         };
         Ok((id, ItemKind::Mod(safety, mod_kind)))
     }
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index decaecd2682..1813960dad0 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use std::assert_matches::assert_matches;
 use std::io::prelude::*;
 use std::iter::Peekable;
diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
index efe266f5290..b13b68c266a 100644
--- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs
+++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use rustc_ast::token::{self, IdentIsRaw};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_span::{BytePos, Span, Symbol, create_default_session_globals_then};
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index f2a37307cee..76edb51c0bc 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -337,7 +337,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
             BareFn,
             Never,
             Tup,
-            AnonAdt,
             Path,
             OpaqueDef,
             TraitObject,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 293cee500bb..924b8afa329 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -770,7 +770,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::Mod(..) => {
+            ItemKind::Mod(.., ref mod_kind) => {
                 let module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, ident.name),
@@ -781,6 +781,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
 
+                if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
+                    self.r.mods_with_parse_errors.insert(def_id);
+                }
+
                 // Descend into the module.
                 self.parent_scope.module = module;
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4c76617a391..368eb3c26c7 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -3056,7 +3056,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
 
     fn visit_item(&mut self, item: &'tcx ast::Item) {
         if self.target_module == item.id {
-            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
+            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
                 let inject = mod_spans.inject_use_span;
                 if is_span_suitable_for_use_injection(inject) {
                     self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 466e190028a..5906a682f3e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1428,6 +1428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         ignore_import: Option<Import<'ra>>,
     ) -> PathResult<'ra> {
         let mut module = None;
+        let mut module_had_parse_errors = false;
         let mut allow_super = true;
         let mut second_binding = None;
 
@@ -1471,9 +1472,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             continue;
                         }
                     }
-                    return PathResult::failed(ident, false, finalize.is_some(), module, || {
-                        ("there are too many leading `super` keywords".to_string(), None)
-                    });
+                    return PathResult::failed(
+                        ident,
+                        false,
+                        finalize.is_some(),
+                        module_had_parse_errors,
+                        module,
+                        || ("there are too many leading `super` keywords".to_string(), None),
+                    );
                 }
                 if segment_idx == 0 {
                     if name == kw::SelfLower {
@@ -1511,19 +1517,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             // Report special messages for path segment keywords in wrong positions.
             if ident.is_path_segment_keyword() && segment_idx != 0 {
-                return PathResult::failed(ident, false, finalize.is_some(), module, || {
-                    let name_str = if name == kw::PathRoot {
-                        "crate root".to_string()
-                    } else {
-                        format!("`{name}`")
-                    };
-                    let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
-                        format!("global paths cannot start with {name_str}")
-                    } else {
-                        format!("{name_str} in paths can only be used in start position")
-                    };
-                    (label, None)
-                });
+                return PathResult::failed(
+                    ident,
+                    false,
+                    finalize.is_some(),
+                    module_had_parse_errors,
+                    module,
+                    || {
+                        let name_str = if name == kw::PathRoot {
+                            "crate root".to_string()
+                        } else {
+                            format!("`{name}`")
+                        };
+                        let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
+                            format!("global paths cannot start with {name_str}")
+                        } else {
+                            format!("{name_str} in paths can only be used in start position")
+                        };
+                        (label, None)
+                    },
+                );
             }
 
             let binding = if let Some(module) = module {
@@ -1589,6 +1602,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
                     if let Some(next_module) = binding.module() {
+                        if self.mods_with_parse_errors.contains(&next_module.def_id()) {
+                            module_had_parse_errors = true;
+                        }
                         module = Some(ModuleOrUniformRoot::Module(next_module));
                         record_segment_res(self, res);
                     } else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
@@ -1614,6 +1630,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             ident,
                             is_last,
                             finalize.is_some(),
+                            module_had_parse_errors,
                             module,
                             || {
                                 let label = format!(
@@ -1637,19 +1654,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                     }
 
-                    return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
-                        self.report_path_resolution_error(
-                            path,
-                            opt_ns,
-                            parent_scope,
-                            ribs,
-                            ignore_binding,
-                            ignore_import,
-                            module,
-                            segment_idx,
-                            ident,
-                        )
-                    });
+                    return PathResult::failed(
+                        ident,
+                        is_last,
+                        finalize.is_some(),
+                        module_had_parse_errors,
+                        module,
+                        || {
+                            self.report_path_resolution_error(
+                                path,
+                                opt_ns,
+                                parent_scope,
+                                ribs,
+                                ignore_binding,
+                                ignore_import,
+                                module,
+                                segment_idx,
+                                ident,
+                            )
+                        },
+                    );
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 51fbcb8ebb8..2ed3f4d2c4f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -670,9 +670,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     fn throw_unresolved_import_error(
         &mut self,
-        errors: Vec<(Import<'_>, UnresolvedImportError)>,
+        mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
         glob_error: bool,
     ) {
+        errors.retain(|(_import, err)| match err.module {
+            // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
+            Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
+            _ => true,
+        });
         if errors.is_empty() {
             return;
         }
@@ -898,6 +903,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 label,
                 suggestion,
                 module,
+                error_implied_by_parse_error: _,
             } => {
                 if no_ambiguity {
                     assert!(import.imported_module.get().is_none());
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 789d74876f7..5cb7bb9b461 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4395,6 +4395,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
                 PartialRes::new(module.res().unwrap())
             }
+            // A part of this path references a `mod` that had a parse error. To avoid resolution
+            // errors for each reference to that module, we don't emit an error for them until the
+            // `mod` is fixed. this can have a significant cascade effect.
+            PathResult::Failed { error_implied_by_parse_error: true, .. } => {
+                PartialRes::new(Res::Err)
+            }
             // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
             // don't report an error right away, but try to fallback to a primitive type.
             // So, we are still able to successfully resolve something like
@@ -4443,6 +4449,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 suggestion,
                 module,
                 segment_name,
+                error_implied_by_parse_error: _,
             } => {
                 return Err(respan(span, ResolutionError::FailedToResolve {
                     segment: Some(segment_name),
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ca4adce37ce..94adfcd3b91 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -450,6 +450,7 @@ enum PathResult<'ra> {
         module: Option<ModuleOrUniformRoot<'ra>>,
         /// The segment name of target
         segment_name: Symbol,
+        error_implied_by_parse_error: bool,
     },
 }
 
@@ -458,6 +459,7 @@ impl<'ra> PathResult<'ra> {
         ident: Ident,
         is_error_from_last_segment: bool,
         finalize: bool,
+        error_implied_by_parse_error: bool,
         module: Option<ModuleOrUniformRoot<'ra>>,
         label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>),
     ) -> PathResult<'ra> {
@@ -470,6 +472,7 @@ impl<'ra> PathResult<'ra> {
             suggestion,
             is_error_from_last_segment,
             module,
+            error_implied_by_parse_error,
         }
     }
 }
@@ -1198,6 +1201,8 @@ pub struct Resolver<'ra, 'tcx> {
     /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo`
     /// could be a crate that wasn't imported. For diagnostics use only.
     current_crate_outer_attr_insert_span: Span,
+
+    mods_with_parse_errors: FxHashSet<DefId>,
 }
 
 /// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1543,6 +1548,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             impl_unexpanded_invocations: Default::default(),
             impl_binding_keys: Default::default(),
             current_crate_outer_attr_insert_span,
+            mods_with_parse_errors: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 0b4d0e04c29..669a9c2428f 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -166,7 +166,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo
         [seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => {
             if let InvocationKind::Attr { item, .. } = &invoc.kind {
                 if let Annotatable::Item(item) = item {
-                    if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind {
+                    if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _, _)) = item.kind {
                         return true;
                     }
                 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 2f4387e412d..34e1c31683a 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -716,8 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             | hir::definitions::DefPathData::Use
             | hir::definitions::DefPathData::GlobalAsm
             | hir::definitions::DefPathData::MacroNs(..)
-            | hir::definitions::DefPathData::LifetimeNs(..)
-            | hir::definitions::DefPathData::AnonAdt => {
+            | hir::definitions::DefPathData::LifetimeNs(..) => {
                 bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
             }
         });
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index cb6d539cdf9..936c2ca87d6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -472,6 +472,13 @@ impl ToString for DebugInfoCompression {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+pub enum MirStripDebugInfo {
+    None,
+    LocalsInTinyFunctions,
+    AllLocals,
+}
+
 /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
 /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
 /// uses DWARF for debug-information.
@@ -2900,10 +2907,10 @@ pub(crate) mod dep_tracking {
         BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
         CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
-        LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
-        PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
-        SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
-        WasiExecModel,
+        LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName,
+        OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents,
+        ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
+        SymbolManglingVersion, WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -2971,6 +2978,7 @@ pub(crate) mod dep_tracking {
         LtoCli,
         DebugInfo,
         DebugInfoCompression,
+        MirStripDebugInfo,
         CollapseMacroDebuginfo,
         UnstableFeatures,
         NativeLib,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b01d9e5e8e3..3873a203bd3 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -391,6 +391,8 @@ mod desc {
     pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
     pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`";
     pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`";
+    pub(crate) const parse_mir_strip_debuginfo: &str =
+        "one of `none`, `locals-in-tiny-functions`, or `all-locals`";
     pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`";
     pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
     pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
@@ -925,6 +927,16 @@ pub mod parse {
         true
     }
 
+    pub(crate) fn parse_mir_strip_debuginfo(slot: &mut MirStripDebugInfo, v: Option<&str>) -> bool {
+        match v {
+            Some("none") => *slot = MirStripDebugInfo::None,
+            Some("locals-in-tiny-functions") => *slot = MirStripDebugInfo::LocalsInTinyFunctions,
+            Some("all-locals") => *slot = MirStripDebugInfo::AllLocals,
+            _ => return false,
+        };
+        true
+    }
+
     pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
         match v.and_then(LinkerFlavorCli::from_str) {
             Some(lf) => *slot = Some(lf),
@@ -1893,6 +1905,8 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
+    mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED],
+        "Whether to remove some of the MIR debug info from methods.  Default: None"),
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: bool = (true, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/edit_distance/tests.rs b/compiler/rustc_span/src/edit_distance/tests.rs
index c9c7a1f1bf2..9540f934d7e 100644
--- a/compiler/rustc_span/src/edit_distance/tests.rs
+++ b/compiler/rustc_span/src/edit_distance/tests.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+
 use super::*;
 
 #[test]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 958d4f0c251..bd8b93bb4d1 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -523,6 +523,12 @@ impl SpanData {
     }
 }
 
+impl Default for SpanData {
+    fn default() -> Self {
+        Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None }
+    }
+}
+
 impl PartialOrd for Span {
     fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
         PartialOrd::partial_cmp(&self.data(), &rhs.data())
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d30b17c9cd8..9b499c71603 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -461,6 +461,7 @@ symbols! {
         async_drop_slice,
         async_drop_surface_drop_in_place,
         async_fn,
+        async_fn_in_dyn_trait,
         async_fn_in_trait,
         async_fn_kind_helper,
         async_fn_kind_upvars,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 1a10ab8829c..def741e3546 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -772,8 +772,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             | DefPathData::GlobalAsm
             | DefPathData::Impl
             | DefPathData::MacroNs(_)
-            | DefPathData::LifetimeNs(_)
-            | DefPathData::AnonAdt => {
+            | DefPathData::LifetimeNs(_) => {
                 bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
             }
         };
diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
index d5acd37092a..4f370ec8bd0 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
@@ -42,6 +42,8 @@ pub(crate) fn opts() -> TargetOptions {
         eh_frame_header: false,
         no_default_libraries: false,
         has_thread_local: true,
+        crt_static_allows_dylibs: true,
+        crt_static_respected: true,
         // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
         // output DWO, despite using DWARF, doesn't use ELF..
         debuginfo_kind: DebuginfoKind::Pdb,
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
index a70cebbd9c8..bdb1fc55711 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
@@ -32,7 +32,8 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
+            .into(),
         arch: "wasm32".into(),
         options: opts,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
index e7165533b9c..96237f20891 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
@@ -37,7 +37,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index 1cd30f21bec..0862958d05d 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -55,7 +55,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
index 19bc5db4d9b..0c2e2bfeda6 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
@@ -66,7 +66,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index f06112160d1..3f4618fad5a 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -66,7 +66,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs b/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
index bf35ae009c6..5c35e9c21d3 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
@@ -44,7 +44,7 @@ pub(crate) fn target() -> Target {
             std: Some(false),
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
index 5ba0fca9f64..22fa26d3cdb 100644
--- a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
@@ -40,7 +40,7 @@ pub(crate) fn target() -> Target {
             std: None, // ?
         },
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm64".into(),
         options,
     }
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 3a130607265..c89045c93e3 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -611,6 +611,8 @@ const HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
     &[/*(512, "hvx-length64b"),*/ (1024, "hvx-length128b")];
 const MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")];
 const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vdspv1")];
+const LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
+    &[(128, "lsx"), (256, "lasx")];
 
 impl super::spec::Target {
     pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
@@ -638,7 +640,7 @@ impl super::spec::Target {
             "aarch64" | "arm64ec" => AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI,
             "arm" => ARM_FEATURES_FOR_CORRECT_VECTOR_ABI,
             "powerpc" | "powerpc64" => POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI,
-            "loongarch64" => &[], // on-stack ABI, so we complain about all by-val vectors
+            "loongarch64" => LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI,
             "riscv32" | "riscv64" => RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI,
             "wasm32" | "wasm64" => WASM_FEATURES_FOR_CORRECT_VECTOR_ABI,
             "s390x" => S390X_FEATURES_FOR_CORRECT_VECTOR_ABI,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index afac6fc6004..68fe90f0de2 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{Visitor, walk_ty};
-use rustc_hir::{FnRetTy, GenericParamKind};
+use rustc_hir::{FnRetTy, GenericParamKind, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
 use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
@@ -1888,10 +1888,35 @@ pub fn impl_trait_overcapture_suggestion<'tcx>(
         .collect::<Vec<_>>()
         .join(", ");
 
-    suggs.push((
-        tcx.def_span(opaque_def_id).shrink_to_hi(),
-        format!(" + use<{concatenated_bounds}>"),
-    ));
+    let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
+    // FIXME: This is a bit too conservative, since it ignores parens already written in AST.
+    let (lparen, rparen) = match tcx
+        .hir()
+        .parent_iter(opaque_hir_id)
+        .nth(1)
+        .expect("expected ty to have a parent always")
+        .1
+    {
+        Node::PathSegment(segment)
+            if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
+        {
+            ("(", ")")
+        }
+        Node::Ty(ty) => match ty.kind {
+            rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
+            // FIXME: RPITs are not allowed to be nested in `impl Fn() -> ...`,
+            // but we eventually could support that, and that would necessitate
+            // making this more sophisticated.
+            _ => ("", ""),
+        },
+        _ => ("", ""),
+    };
+
+    let rpit_span = tcx.def_span(opaque_def_id);
+    if !lparen.is_empty() {
+        suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
+    }
+    suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
 
     Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
 }
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index c9297027519..d2abd881c45 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -11,6 +11,7 @@ use rustc_abi::BackendRepr;
 use rustc_errors::FatalError;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
@@ -901,23 +902,59 @@ fn contains_illegal_impl_trait_in_trait<'tcx>(
     fn_def_id: DefId,
     ty: ty::Binder<'tcx, Ty<'tcx>>,
 ) -> Option<MethodViolationCode> {
-    // This would be caught below, but rendering the error as a separate
-    // `async-specific` message is better.
+    let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
+
     if tcx.asyncness(fn_def_id).is_async() {
-        return Some(MethodViolationCode::AsyncFn);
+        // FIXME(async_fn_in_dyn_trait): Think of a better way to unify these code paths
+        // to issue an appropriate feature suggestion when users try to use AFIDT.
+        // Obviously we must only do this once AFIDT is finished enough to actually be usable.
+        if tcx.features().async_fn_in_dyn_trait() {
+            let ty::Alias(ty::Projection, proj) = *ty.kind() else {
+                bug!("expected async fn in trait to return an RPITIT");
+            };
+            assert!(tcx.is_impl_trait_in_trait(proj.def_id));
+
+            // FIXME(async_fn_in_dyn_trait): We should check that this bound is legal too,
+            // and stop relying on `async fn` in the definition.
+            for bound in tcx.item_bounds(proj.def_id).instantiate(tcx, proj.args) {
+                if let Some(violation) = bound
+                    .visit_with(&mut IllegalRpititVisitor { tcx, allowed: Some(proj) })
+                    .break_value()
+                {
+                    return Some(violation);
+                }
+            }
+
+            None
+        } else {
+            // Rendering the error as a separate `async-specific` message is better.
+            Some(MethodViolationCode::AsyncFn)
+        }
+    } else {
+        ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
     }
+}
+
+struct IllegalRpititVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    allowed: Option<ty::AliasTy<'tcx>>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
+    type Result = ControlFlow<MethodViolationCode>;
 
-    // FIXME(RPITIT): Perhaps we should use a visitor here?
-    ty.skip_binder().walk().find_map(|arg| {
-        if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Alias(ty::Projection, proj) = ty.kind()
-            && tcx.is_impl_trait_in_trait(proj.def_id)
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        if let ty::Alias(ty::Projection, proj) = *ty.kind()
+            && Some(proj) != self.allowed
+            && self.tcx.is_impl_trait_in_trait(proj.def_id)
         {
-            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
+            ControlFlow::Break(MethodViolationCode::ReferencesImplTraitInTrait(
+                self.tcx.def_span(proj.def_id),
+            ))
         } else {
-            None
+            ty.super_visit_with(self)
         }
-    })
+    }
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 49c34550f8e..5f1dbfeedfb 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -7,8 +7,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
+use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
 use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
@@ -18,6 +18,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
+use thin_vec::thin_vec;
 use tracing::{debug, instrument};
 
 use super::{
@@ -61,6 +62,9 @@ enum ProjectionCandidate<'tcx> {
     /// Bounds specified on an object type
     Object(ty::PolyProjectionPredicate<'tcx>),
 
+    /// Built-in bound for a dyn async fn in trait
+    ObjectRpitit,
+
     /// From an "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
 }
@@ -744,7 +748,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
             let Some(clause) = clause.as_projection_clause() else {
                 return ControlFlow::Continue(());
             };
-            if clause.projection_def_id() != obligation.predicate.def_id {
+            if clause.item_def_id() != obligation.predicate.def_id {
                 return ControlFlow::Continue(());
             }
 
@@ -827,6 +831,17 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
         env_predicates,
         false,
     );
+
+    // `dyn Trait` automagically project their AFITs to `dyn* Future`.
+    if tcx.is_impl_trait_in_trait(obligation.predicate.def_id)
+        && let Some(out_trait_def_id) = data.principal_def_id()
+        && let rpitit_trait_def_id = tcx.parent(obligation.predicate.def_id)
+        && tcx
+            .supertrait_def_ids(out_trait_def_id)
+            .any(|trait_def_id| trait_def_id == rpitit_trait_def_id)
+    {
+        candidate_set.push_candidate(ProjectionCandidate::ObjectRpitit);
+    }
 }
 
 #[instrument(
@@ -847,7 +862,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
         let bound_predicate = predicate.kind();
         if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
             let data = bound_predicate.rebind(data);
-            if data.projection_def_id() != obligation.predicate.def_id {
+            if data.item_def_id() != obligation.predicate.def_id {
                 continue;
             }
 
@@ -1247,6 +1262,8 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
+
+        ProjectionCandidate::ObjectRpitit => confirm_object_rpitit_candidate(selcx, obligation),
     };
 
     // When checking for cycle during evaluation, we compare predicates with
@@ -2034,6 +2051,45 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     }
 }
 
+fn confirm_object_rpitit_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+    let mut obligations = thin_vec![];
+
+    // Compute an intersection lifetime for all the input components of this GAT.
+    let intersection =
+        selcx.infcx.next_region_var(RegionVariableOrigin::MiscVariable(obligation.cause.span));
+    for component in obligation.predicate.args {
+        match component.unpack() {
+            ty::GenericArgKind::Lifetime(lt) => {
+                obligations.push(obligation.with(tcx, ty::OutlivesPredicate(lt, intersection)));
+            }
+            ty::GenericArgKind::Type(ty) => {
+                obligations.push(obligation.with(tcx, ty::OutlivesPredicate(ty, intersection)));
+            }
+            ty::GenericArgKind::Const(_ct) => {
+                // Consts have no outlives...
+            }
+        }
+    }
+
+    Progress {
+        term: Ty::new_dynamic(
+            tcx,
+            tcx.item_bounds_to_existential_predicates(
+                obligation.predicate.def_id,
+                obligation.predicate.args,
+            ),
+            intersection,
+            ty::DynStar,
+        )
+        .into(),
+        obligations,
+    }
+}
+
 // Get obligations corresponding to the predicates from the where-clause of the
 // associated type itself.
 fn assoc_ty_own_obligations<'cx, 'tcx>(
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 2fbe2e1e323..962b6b94fa6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -19,6 +19,7 @@ use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
 use rustc_middle::ty::{self, GenericArgsRef, ToPolyTraitRef, Ty, TyCtxt, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
+use rustc_type_ir::elaborate;
 use tracing::{debug, instrument};
 
 use super::SelectionCandidate::{self, *};
@@ -624,6 +625,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         for assoc_type in assoc_types {
             let defs: &ty::Generics = tcx.generics_of(assoc_type);
 
+            // When `async_fn_in_dyn_trait` is enabled, we don't need to check the
+            // RPITIT for compatibility, since it's not provided by the user.
+            if tcx.features().async_fn_in_dyn_trait() && tcx.is_impl_trait_in_trait(assoc_type) {
+                continue;
+            }
+
             if !defs.own_params.is_empty() {
                 tcx.dcx().span_delayed_bug(
                     obligation.cause.span,
@@ -1175,6 +1182,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::ClauseKind::TypeOutlives(outlives).upcast(tcx),
                 ));
 
+                // Require that all AFIT will return something that can be coerced into `dyn*`
+                // -- a shim will be responsible for doing the actual coercion to `dyn*`.
+                if let Some(principal) = data.principal() {
+                    for supertrait in
+                        elaborate::supertraits(tcx, principal.with_self_ty(tcx, source))
+                    {
+                        if tcx.is_trait_alias(supertrait.def_id()) {
+                            continue;
+                        }
+
+                        for &assoc_item in tcx.associated_item_def_ids(supertrait.def_id()) {
+                            if !tcx.is_impl_trait_in_trait(assoc_item) {
+                                continue;
+                            }
+
+                            // RPITITs with `Self: Sized` don't need to be checked.
+                            if tcx.generics_require_sized_self(assoc_item) {
+                                continue;
+                            }
+
+                            let pointer_like_goal = pointer_like_goal_for_rpitit(
+                                tcx,
+                                supertrait,
+                                assoc_item,
+                                &obligation.cause,
+                            );
+
+                            nested.push(predicate_to_obligation(pointer_like_goal.upcast(tcx)));
+                        }
+                    }
+                }
+
                 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
             }
 
@@ -1280,3 +1319,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 }
+
+/// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)
+/// implements the `PointerLike` trait, which is a requirement for the RPITIT to be
+/// coercible to `dyn* Future`, which is itself a requirement for the RPITIT's parent
+/// trait to be coercible to `dyn Trait`.
+///
+/// We do this given a supertrait's substitutions, and then augment the substitutions
+/// with bound variables to compute the goal universally. Given that `PointerLike` has
+/// no region requirements (at least for the built-in pointer types), this shouldn't
+/// *really* matter, but it is the best choice for soundness.
+fn pointer_like_goal_for_rpitit<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    supertrait: ty::PolyTraitRef<'tcx>,
+    rpitit_item: DefId,
+    cause: &ObligationCause<'tcx>,
+) -> ty::PolyTraitRef<'tcx> {
+    let mut bound_vars = supertrait.bound_vars().to_vec();
+
+    let args = supertrait.skip_binder().args.extend_to(tcx, rpitit_item, |arg, _| match arg.kind {
+        ty::GenericParamDefKind::Lifetime => {
+            let kind = ty::BoundRegionKind::Named(arg.def_id, tcx.item_name(arg.def_id));
+            bound_vars.push(ty::BoundVariableKind::Region(kind));
+            ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
+                var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+                kind,
+            })
+            .into()
+        }
+        ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => {
+            unreachable!()
+        }
+    });
+
+    ty::Binder::bind_with_vars(
+        ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::PointerLike, Some(cause.span)), [
+            Ty::new_projection_from_args(tcx, rpitit_item, args),
+        ]),
+        tcx.mk_bound_variable_kinds(&bound_vars),
+    )
+}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index d362866cbc3..25fe43e3a0e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1737,7 +1737,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         env_predicate: PolyProjectionPredicate<'tcx>,
         potentially_unnormalized_candidates: bool,
     ) -> ProjectionMatchesProjection {
-        debug_assert_eq!(obligation.predicate.def_id, env_predicate.projection_def_id());
+        debug_assert_eq!(obligation.predicate.def_id, env_predicate.item_def_id());
 
         let mut nested_obligations = PredicateObligations::new();
         let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars(
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index ae6d697794f..b63534880d1 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -48,12 +48,38 @@ fn fn_sig_for_fn_abi<'tcx>(
             let mut sig = tcx
                 .instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args));
 
+            // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
             if let ty::InstanceKind::VTableShim(..) = instance.def {
                 let mut inputs_and_output = sig.inputs_and_output.to_vec();
                 inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
                 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
             }
 
+            // Modify `fn() -> impl Future` to `fn() -> dyn* Future`.
+            if let ty::InstanceKind::ReifyShim(def_id, _) = instance.def
+                && let Some((rpitit_def_id, fn_args)) =
+                    tcx.return_position_impl_trait_in_trait_shim_data(def_id)
+            {
+                let fn_args = fn_args.instantiate(tcx, args);
+                let rpitit_args =
+                    fn_args.extend_to(tcx, rpitit_def_id, |param, _| match param.kind {
+                        ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                        ty::GenericParamDefKind::Type { .. }
+                        | ty::GenericParamDefKind::Const { .. } => {
+                            unreachable!("rpitit should have no addition ty/ct")
+                        }
+                    });
+                let dyn_star_ty = Ty::new_dynamic(
+                    tcx,
+                    tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args),
+                    tcx.lifetimes.re_erased,
+                    ty::DynStar,
+                );
+                let mut inputs_and_output = sig.inputs_and_output.to_vec();
+                *inputs_and_output.last_mut().unwrap() = dyn_star_ty;
+                sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
+            }
+
             sig
         }
         ty::Closure(def_id, args) => {
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 4213ef4803b..9a80f97e274 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -692,7 +692,7 @@ impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
     ///
     /// Note that this is not the `DefId` of the `TraitRef` containing this
     /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
-    pub fn projection_def_id(&self) -> I::DefId {
+    pub fn item_def_id(&self) -> I::DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
         self.skip_binder().projection_term.def_id
     }
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 04b7315e650..ae34fc65326 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -10,9 +10,6 @@ use core::hint;
 #[cfg(not(test))]
 use core::ptr::{self, NonNull};
 
-#[cfg(test)]
-mod tests;
-
 extern "Rust" {
     // These are the magic symbols to call the global allocator. rustc generates
     // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index e0f94428cfa..23b85fbd4eb 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1985,7 +1985,8 @@ impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
     }
 }
 
-#[unstable(feature = "async_fn_traits", issue = "none")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args> for Box<F, A> {
     type Output = F::Output;
     type CallOnceFuture = F::CallOnceFuture;
@@ -1995,7 +1996,8 @@ impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args>
     }
 }
 
-#[unstable(feature = "async_fn_traits", issue = "none")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> for Box<F, A> {
     type CallRefFuture<'a>
         = F::CallRefFuture<'a>
@@ -2007,7 +2009,8 @@ impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> f
     }
 }
 
-#[unstable(feature = "async_fn_traits", issue = "none")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box<F, A> {
     extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> {
         F::async_call(self, args)
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 5d3997e14e3..116e0e73e96 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -155,9 +155,6 @@ use crate::collections::TryReserveError;
 use crate::slice;
 use crate::vec::{self, AsVecIntoIter, Vec};
 
-#[cfg(test)]
-mod tests;
-
 /// A priority queue implemented with a binary heap.
 ///
 /// This will be a max-heap.
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index 9c074383a5e..c7d6d8a55c2 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -1,8 +1,5 @@
 //! [`CString`] and its related types.
 
-#[cfg(test)]
-mod tests;
-
 use core::borrow::Borrow;
 use core::ffi::{CStr, c_char};
 use core::num::NonZero;
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 927c3aa23b9..40759cb0ba8 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -91,6 +91,7 @@
 //
 // Library features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(async_closure))]
 #![cfg_attr(test, feature(str_as_str))]
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
@@ -99,7 +100,6 @@
 #![feature(array_windows)]
 #![feature(ascii_char)]
 #![feature(assert_matches)]
-#![feature(async_closure)]
 #![feature(async_fn_traits)]
 #![feature(async_iterator)]
 #![feature(box_uninit_write)]
@@ -239,8 +239,6 @@ pub mod string;
 pub mod sync;
 #[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))]
 pub mod task;
-#[cfg(test)]
-mod tests;
 pub mod vec;
 
 #[doc(hidden)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index e3c7835f1d1..edc8d99f2f9 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -27,6 +27,8 @@ pub use core::slice::ArrayChunksMut;
 pub use core::slice::ArrayWindows;
 #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
 pub use core::slice::EscapeAscii;
+#[unstable(feature = "get_many_mut", issue = "104642")]
+pub use core::slice::GetManyMutError;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
 #[cfg(not(no_global_oom_handling))]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index b8bdd298c27..6cf41a3fa4e 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -39,9 +39,6 @@ use crate::string::String;
 #[cfg(not(no_global_oom_handling))]
 use crate::vec::Vec;
 
-#[cfg(test)]
-mod tests;
-
 /// A soft limit on the amount of references that may be made to an `Arc`.
 ///
 /// Going above this limit will abort your program (although not
diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/tests/alloc.rs
index 5d6077f057a..1e722d66795 100644
--- a/library/alloc/src/alloc/tests.rs
+++ b/library/alloc/tests/alloc.rs
@@ -1,10 +1,9 @@
-use super::*;
+use alloc::alloc::*;
+use alloc::boxed::Box;
 
 extern crate test;
 use test::Bencher;
 
-use crate::boxed::Box;
-
 #[test]
 fn allocate_zeroed() {
     unsafe {
diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/tests/c_str2.rs
index d6b797347c2..0f4c27fa123 100644
--- a/library/alloc/src/ffi/c_str/tests.rs
+++ b/library/alloc/tests/c_str2.rs
@@ -1,11 +1,12 @@
+use alloc::ffi::CString;
+use alloc::rc::Rc;
+use alloc::sync::Arc;
 use core::assert_matches::assert_matches;
-use core::ffi::FromBytesUntilNulError;
+use core::ffi::{CStr, FromBytesUntilNulError, c_char};
 #[allow(deprecated)]
 use core::hash::SipHasher13 as DefaultHasher;
 use core::hash::{Hash, Hasher};
 
-use super::*;
-
 #[test]
 fn c_to_rust() {
     let data = b"123\0";
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/tests/collections/binary_heap.rs
index ad0a020a1a9..55405ffe8c4 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/tests/collections/binary_heap.rs
@@ -1,7 +1,9 @@
+use alloc::boxed::Box;
+use alloc::collections::binary_heap::*;
+use std::iter::TrustedLen;
+use std::mem;
 use std::panic::{AssertUnwindSafe, catch_unwind};
 
-use super::*;
-use crate::boxed::Box;
 use crate::testing::crash_test::{CrashTestDummy, Panic};
 
 #[test]
@@ -531,7 +533,7 @@ fn panic_safe() {
             self.0.partial_cmp(&other.0)
         }
     }
-    let mut rng = crate::test_helpers::test_rng();
+    let mut rng = crate::test_rng();
     const DATASZ: usize = 32;
     // Miri is too slow
     let ntest = if cfg!(miri) { 1 } else { 10 };
diff --git a/library/alloc/tests/collections/mod.rs b/library/alloc/tests/collections/mod.rs
new file mode 100644
index 00000000000..e73f3aaef8c
--- /dev/null
+++ b/library/alloc/tests/collections/mod.rs
@@ -0,0 +1 @@
+mod binary_heap;
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index bcab17e7b2d..393bdfe48b7 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -5,8 +5,10 @@
 #![feature(btree_extract_if)]
 #![feature(cow_is_borrowed)]
 #![feature(core_intrinsics)]
+#![feature(downcast_unchecked)]
 #![feature(extract_if)]
 #![feature(exact_size_is_empty)]
+#![feature(hashmap_internals)]
 #![feature(linked_list_cursors)]
 #![feature(map_try_insert)]
 #![feature(pattern)]
@@ -29,9 +31,11 @@
 #![feature(const_str_from_utf8)]
 #![feature(panic_update_hook)]
 #![feature(pointer_is_aligned_to)]
+#![feature(test)]
 #![feature(thin_box)]
 #![feature(drain_keep_rest)]
 #![feature(local_waker)]
+#![feature(str_as_str)]
 #![feature(strict_provenance_lints)]
 #![feature(vec_pop_if)]
 #![feature(unique_rc_arc)]
@@ -40,25 +44,33 @@
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
+extern crate test;
+
 use std::hash::{DefaultHasher, Hash, Hasher};
 
+mod alloc;
 mod arc;
 mod autotraits;
 mod borrow;
 mod boxed;
 mod btree_set_hash;
 mod c_str;
+mod c_str2;
+mod collections;
 mod const_fns;
 mod cow_str;
 mod fmt;
 mod heap;
 mod linked_list;
+mod misc_tests;
 mod rc;
 mod slice;
 mod sort;
 mod str;
 mod string;
+mod sync;
 mod task;
+mod testing;
 mod thin_box;
 mod vec;
 mod vec_deque;
@@ -69,6 +81,18 @@ fn hash<T: Hash>(t: &T) -> u64 {
     s.finish()
 }
 
+/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
+/// seed not being the same for every RNG invocation too.
+fn test_rng() -> rand_xorshift::XorShiftRng {
+    use std::hash::{BuildHasher, Hash, Hasher};
+    let mut hasher = std::hash::RandomState::new().build_hasher();
+    std::panic::Location::caller().hash(&mut hasher);
+    let hc64 = hasher.finish();
+    let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
+    let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+    rand::SeedableRng::from_seed(seed)
+}
+
 // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten.
 // See https://github.com/kripken/emscripten-fastcomp/issues/169
 #[cfg(not(target_os = "emscripten"))]
diff --git a/library/alloc/src/tests.rs b/library/alloc/tests/misc_tests.rs
index b95d11cb07e..b95d11cb07e 100644
--- a/library/alloc/src/tests.rs
+++ b/library/alloc/tests/misc_tests.rs
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/tests/sync.rs
index de5816fda97..7a9a4abfdc6 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/tests/sync.rs
@@ -1,14 +1,16 @@
+use alloc::sync::*;
+use std::alloc::{AllocError, Allocator, Layout};
+use std::any::Any;
 use std::clone::Clone;
 use std::mem::MaybeUninit;
 use std::option::Option::None;
+use std::ptr::NonNull;
 use std::sync::Mutex;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering::SeqCst;
+use std::sync::atomic::Ordering::*;
+use std::sync::atomic::{self, AtomicUsize};
 use std::sync::mpsc::channel;
 use std::thread;
 
-use super::*;
-
 struct Canary(*mut AtomicUsize);
 
 impl Drop for Canary {
diff --git a/library/alloc/tests/testing/crash_test.rs b/library/alloc/tests/testing/crash_test.rs
new file mode 100644
index 00000000000..502fe6c10c6
--- /dev/null
+++ b/library/alloc/tests/testing/crash_test.rs
@@ -0,0 +1,80 @@
+use std::cmp::Ordering;
+use std::fmt::Debug;
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering::SeqCst;
+
+/// A blueprint for crash test dummy instances that monitor drops.
+/// Some instances may be configured to panic at some point.
+///
+/// Crash test dummies are identified and ordered by an id, so they can be used
+/// as keys in a BTreeMap.
+#[derive(Debug)]
+pub struct CrashTestDummy {
+    pub id: usize,
+    dropped: AtomicUsize,
+}
+
+impl CrashTestDummy {
+    /// Creates a crash test dummy design. The `id` determines order and equality of instances.
+    pub fn new(id: usize) -> CrashTestDummy {
+        CrashTestDummy { id, dropped: AtomicUsize::new(0) }
+    }
+
+    /// Creates an instance of a crash test dummy that records what events it experiences
+    /// and optionally panics.
+    pub fn spawn(&self, panic: Panic) -> Instance<'_> {
+        Instance { origin: self, panic }
+    }
+
+    /// Returns how many times instances of the dummy have been dropped.
+    pub fn dropped(&self) -> usize {
+        self.dropped.load(SeqCst)
+    }
+}
+
+#[derive(Debug)]
+pub struct Instance<'a> {
+    origin: &'a CrashTestDummy,
+    panic: Panic,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Panic {
+    Never,
+    InDrop,
+}
+
+impl Instance<'_> {
+    pub fn id(&self) -> usize {
+        self.origin.id
+    }
+}
+
+impl Drop for Instance<'_> {
+    fn drop(&mut self) {
+        self.origin.dropped.fetch_add(1, SeqCst);
+        if self.panic == Panic::InDrop {
+            panic!("panic in `drop`");
+        }
+    }
+}
+
+impl PartialOrd for Instance<'_> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.id().partial_cmp(&other.id())
+    }
+}
+
+impl Ord for Instance<'_> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.id().cmp(&other.id())
+    }
+}
+
+impl PartialEq for Instance<'_> {
+    fn eq(&self, other: &Self) -> bool {
+        self.id().eq(&other.id())
+    }
+}
+
+impl Eq for Instance<'_> {}
diff --git a/library/alloc/tests/testing/mod.rs b/library/alloc/tests/testing/mod.rs
new file mode 100644
index 00000000000..0a3dd191dc8
--- /dev/null
+++ b/library/alloc/tests/testing/mod.rs
@@ -0,0 +1 @@
+pub mod crash_test;
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 95a39cc3aed..91549f49f9f 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1076,4 +1076,4 @@ impl Error for crate::time::TryFromFloatSecsError {}
 impl Error for crate::ffi::FromBytesUntilNulError {}
 
 #[unstable(feature = "get_many_mut", issue = "104642")]
-impl<const N: usize> Error for crate::slice::GetManyMutError<N> {}
+impl Error for crate::slice::GetManyMutError {}
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index dc107c5d22c..7a161f595f4 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -91,59 +91,86 @@ pub type c_ssize_t = isize;
 
 mod c_char_definition {
     cfg_if! {
-        // These are the targets on which c_char is unsigned.
-        if #[cfg(any(
-            all(
-                target_os = "linux",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "hexagon",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "s390x",
-                    target_arch = "riscv64",
-                    target_arch = "riscv32",
-                    target_arch = "csky"
-                )
-            ),
-            all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
-            all(target_os = "l4re", target_arch = "x86_64"),
-            all(
-                any(target_os = "freebsd", target_os = "openbsd", target_os = "rtems"),
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "riscv64"
-                )
-            ),
-            all(
-                target_os = "netbsd",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc",
-                    target_arch = "riscv64"
-                )
-            ),
-            all(
-                target_os = "vxworks",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc64",
-                    target_arch = "powerpc"
-                )
-            ),
-            all(
-                target_os = "fuchsia",
-                any(target_arch = "aarch64", target_arch = "riscv64")
-            ),
-            all(target_os = "nto", target_arch = "aarch64"),
-            target_os = "horizon",
-            target_os = "aix",
+        // These are the targets on which c_char is unsigned. Usually the
+        // signedness is the same for all target_os values on a given architecture
+        // but there are some exceptions (see isSignedCharDefault() in clang).
+        //
+        // aarch64:
+        //   Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm®
+        //   64-bit Architecture (AArch64) says C/C++ char is unsigned byte.
+        //   https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings
+        // arm:
+        //   Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm®
+        //   Architecture says C/C++ char is unsigned byte.
+        //   https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings
+        // csky:
+        //   Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface
+        //   Standards Manual says ANSI C char is unsigned byte.
+        //   https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf
+        //   Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945).
+        // hexagon:
+        //   Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application
+        //   Binary Interface User Guide says "By default, the `char` data type is unsigned."
+        //   https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf
+        // msp430:
+        //   Section 2.1 "Basic Types" in MSP430 Embedded Application Binary
+        //   Interface says "The char type is unsigned by default".
+        //   https://www.ti.com/lit/an/slaa534a/slaa534a.pdf
+        //   Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945).
+        // powerpc/powerpc64:
+        //   - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC
+        //     Processor Supplement says ANSI C char is unsigned byte
+        //     https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
+        //   - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application
+        //     Binary Interface Supplement 1.9 says ANSI C is unsigned byte
+        //     https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE
+        //   - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification
+        //     says char is unsigned byte
+        //     https://openpowerfoundation.org/specifications/64bitelfabi/
+        //   - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char."
+        //     https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types
+        // riscv32/riscv64:
+        //   C/C++ type representations section in RISC-V Calling Conventions
+        //   page in RISC-V ELF psABI Document says "char is unsigned."
+        //   https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations
+        // s390x:
+        //   - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement
+        //     Version 1.6.1 categorize ISO C char in unsigned integer
+        //     https://github.com/IBM/s390x-abi/releases/tag/v1.6.1
+        //   - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char."
+        //     https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types
+        // Xtensa:
+        //   - "The char type is unsigned by default for Xtensa processors."
+        //
+        // On the following operating systems, c_char is signed by default, regardless of architecture.
+        // Darwin (macOS, iOS, etc.):
+        //   Apple targets' c_char is signed by default even on arm
+        //   https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly
+        // Windows:
+        //   Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char
+        //   are promoted to int as if from type signed char by default, unless the /J compilation
+        //   option is used."
+        //   https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types)
+        // L4RE:
+        //   The kernel builds with -funsigned-char on all targets (but useserspace follows the
+        //   architecture defaults). As we only have a target for userspace apps so there are no
+        //   special cases for L4RE below.
+        if #[cfg(all(
+            not(windows),
+            not(target_vendor = "apple"),
+            any(
+                target_arch = "aarch64",
+                target_arch = "arm",
+                target_arch = "csky",
+                target_arch = "hexagon",
+                target_arch = "msp430",
+                target_arch = "powerpc",
+                target_arch = "powerpc64",
+                target_arch = "riscv64",
+                target_arch = "riscv32",
+                target_arch = "s390x",
+                target_arch = "xtensa",
+            )
         ))] {
             pub type c_char = u8;
         } else {
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index af6f0da88de..94341a4da66 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -19,7 +19,7 @@ pub struct Placeholder {
 }
 
 impl Placeholder {
-    #[inline(always)]
+    #[inline]
     pub const fn new(
         position: usize,
         fill: char,
@@ -95,7 +95,7 @@ pub struct Argument<'a> {
 
 #[rustc_diagnostic_item = "ArgumentMethods"]
 impl Argument<'_> {
-    #[inline(always)]
+    #[inline]
     fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
         Argument {
             // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
@@ -109,47 +109,47 @@ impl Argument<'_> {
         }
     }
 
-    #[inline(always)]
+    #[inline]
     pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
         Self::new(x, Display::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
         Self::new(x, Debug::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
         Self::new(x, |_, _| Ok(()))
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
         Self::new(x, Octal::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
         Self::new(x, LowerHex::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
         Self::new(x, UpperHex::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
         Self::new(x, Pointer::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
         Self::new(x, Binary::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
         Self::new(x, LowerExp::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
         Self::new(x, UpperExp::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn from_usize(x: &usize) -> Argument<'_> {
         Argument { ty: ArgumentType::Count(*x) }
     }
@@ -164,7 +164,7 @@ impl Argument<'_> {
     // it here is an explicit CFI violation.
     #[allow(inline_no_sanitize)]
     #[no_sanitize(cfi, kcfi)]
-    #[inline(always)]
+    #[inline]
     pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
         match self.ty {
             // SAFETY:
@@ -180,7 +180,7 @@ impl Argument<'_> {
         }
     }
 
-    #[inline(always)]
+    #[inline]
     pub(super) fn as_usize(&self) -> Option<usize> {
         match self.ty {
             ArgumentType::Count(count) => Some(count),
@@ -198,7 +198,7 @@ impl Argument<'_> {
     /// let f = format_args!("{}", "a");
     /// println!("{f}");
     /// ```
-    #[inline(always)]
+    #[inline]
     pub fn none() -> [Self; 0] {
         []
     }
@@ -215,7 +215,7 @@ pub struct UnsafeArg {
 impl UnsafeArg {
     /// See documentation where `UnsafeArg` is required to know when it is safe to
     /// create and use `UnsafeArg`.
-    #[inline(always)]
+    #[inline]
     pub unsafe fn new() -> Self {
         Self { _private: () }
     }
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index e36f20fd576..357a85ae843 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -77,6 +77,31 @@ pub use saturating::Saturating;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use wrapping::Wrapping;
 
+macro_rules! u8_xe_bytes_doc {
+    () => {
+        "
+
+**Note**: This function is meaningless on `u8`. Byte order does not exist as a
+concept for byte-sized integers. This function is only provided in symmetry
+with larger integer types.
+
+"
+    };
+}
+
+macro_rules! i8_xe_bytes_doc {
+    () => {
+        "
+
+**Note**: This function is meaningless on `i8`. Byte order does not exist as a
+concept for byte-sized integers. This function is only provided in symmetry
+with larger integer types. You can cast from and to `u8` using `as i8` and `as
+u8`.
+
+"
+    };
+}
+
 macro_rules! usize_isize_to_xe_bytes_doc {
     () => {
         "
@@ -348,8 +373,8 @@ impl i8 {
         reversed = "0x48",
         le_bytes = "[0x12]",
         be_bytes = "[0x12]",
-        to_xe_bytes_doc = "",
-        from_xe_bytes_doc = "",
+        to_xe_bytes_doc = i8_xe_bytes_doc!(),
+        from_xe_bytes_doc = i8_xe_bytes_doc!(),
         bound_condition = "",
     }
     midpoint_impl! { i8, i16, signed }
@@ -547,8 +572,8 @@ impl u8 {
         reversed = "0x48",
         le_bytes = "[0x12]",
         be_bytes = "[0x12]",
-        to_xe_bytes_doc = "",
-        from_xe_bytes_doc = "",
+        to_xe_bytes_doc = u8_xe_bytes_doc!(),
+        from_xe_bytes_doc = u8_xe_bytes_doc!(),
         bound_condition = "",
     }
     widening_impl! { u8, u16, 8, unsigned }
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index 4b230b15a1e..0073afd4960 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -4,7 +4,8 @@ use crate::marker::Tuple;
 /// An async-aware version of the [`Fn`](crate::ops::Fn) trait.
 ///
 /// All `async fn` and functions returning futures implement this trait.
-#[unstable(feature = "async_closure", issue = "62290")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 #[rustc_paren_sugar]
 #[fundamental]
 #[must_use = "async closures are lazy and do nothing unless called"]
@@ -18,7 +19,8 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
 /// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait.
 ///
 /// All `async fn` and functions returning futures implement this trait.
-#[unstable(feature = "async_closure", issue = "62290")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 #[rustc_paren_sugar]
 #[fundamental]
 #[must_use = "async closures are lazy and do nothing unless called"]
@@ -39,7 +41,8 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
 /// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait.
 ///
 /// All `async fn` and functions returning futures implement this trait.
-#[unstable(feature = "async_closure", issue = "62290")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 #[rustc_paren_sugar]
 #[fundamental]
 #[must_use = "async closures are lazy and do nothing unless called"]
@@ -64,7 +67,8 @@ mod impls {
     use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
     use crate::marker::Tuple;
 
-    #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
     impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F
     where
         F: AsyncFn<A>,
@@ -74,7 +78,8 @@ mod impls {
         }
     }
 
-    #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
     impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F
     where
         F: AsyncFn<A>,
@@ -89,7 +94,8 @@ mod impls {
         }
     }
 
-    #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
     impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F
     where
         F: AsyncFn<A>,
@@ -102,7 +108,8 @@ mod impls {
         }
     }
 
-    #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
     impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F
     where
         F: AsyncFnMut<A>,
@@ -117,7 +124,8 @@ mod impls {
         }
     }
 
-    #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+    #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
     impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F
     where
         F: AsyncFnMut<A>,
diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs
index 496b78439ea..9b23874bcf7 100644
--- a/library/core/src/prelude/mod.rs
+++ b/library/core/src/prelude/mod.rs
@@ -71,7 +71,7 @@ pub mod rust_2021 {
 /// The 2024 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2024", issue = "121042")]
+#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
 pub mod rust_2024 {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::common::*;
@@ -84,7 +84,7 @@ pub mod rust_2024 {
     #[doc(no_inline)]
     pub use crate::convert::{TryFrom, TryInto};
 
-    #[unstable(feature = "prelude_2024", issue = "121042")]
+    #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
     #[doc(no_inline)]
     pub use crate::future::{Future, IntoFuture};
 }
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 6d0361b8c63..3639feaacf3 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1587,15 +1587,6 @@ impl<T: ?Sized> *mut T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
-    /// When this is called during compile-time evaluation (which is unstable), the implementation
-    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
-    /// actual alignment of pointers is not known yet during compile-time, so an offset with
-    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
-    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
-    /// known, so the execution has to be correct for either choice. It is therefore impossible to
-    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
-    /// for unstable APIs.)
-    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 191eaccff98..97a7338b0bf 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4629,13 +4629,11 @@ impl<T> [T] {
     pub fn get_many_mut<I, const N: usize>(
         &mut self,
         indices: [I; N],
-    ) -> Result<[&mut I::Output; N], GetManyMutError<N>>
+    ) -> Result<[&mut I::Output; N], GetManyMutError>
     where
         I: GetManyMutIndex + SliceIndex<Self>,
     {
-        if !get_many_check_valid(&indices, self.len()) {
-            return Err(GetManyMutError { _private: () });
-        }
+        get_many_check_valid(&indices, self.len())?;
         // SAFETY: The `get_many_check_valid()` call checked that all indices
         // are disjunct and in bounds.
         unsafe { Ok(self.get_many_unchecked_mut(indices)) }
@@ -4978,53 +4976,59 @@ impl<T, const N: usize> SlicePattern for [T; N] {
 /// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..`
 /// comparison operations.
 #[inline]
-fn get_many_check_valid<I: GetManyMutIndex, const N: usize>(indices: &[I; N], len: usize) -> bool {
+fn get_many_check_valid<I: GetManyMutIndex, const N: usize>(
+    indices: &[I; N],
+    len: usize,
+) -> Result<(), GetManyMutError> {
     // NB: The optimizer should inline the loops into a sequence
     // of instructions without additional branching.
-    let mut valid = true;
     for (i, idx) in indices.iter().enumerate() {
-        valid &= idx.is_in_bounds(len);
+        if !idx.is_in_bounds(len) {
+            return Err(GetManyMutError::IndexOutOfBounds);
+        }
         for idx2 in &indices[..i] {
-            valid &= !idx.is_overlapping(idx2);
+            if idx.is_overlapping(idx2) {
+                return Err(GetManyMutError::OverlappingIndices);
+            }
         }
     }
-    valid
+    Ok(())
 }
 
-/// The error type returned by [`get_many_mut<N>`][`slice::get_many_mut`].
+/// The error type returned by [`get_many_mut`][`slice::get_many_mut`].
 ///
 /// It indicates one of two possible errors:
 /// - An index is out-of-bounds.
-/// - The same index appeared multiple times in the array.
+/// - The same index appeared multiple times in the array
+///   (or different but overlapping indices when ranges are provided).
 ///
 /// # Examples
 ///
 /// ```
 /// #![feature(get_many_mut)]
+/// use std::slice::GetManyMutError;
 ///
 /// let v = &mut [1, 2, 3];
-/// assert!(v.get_many_mut([0, 999]).is_err());
-/// assert!(v.get_many_mut([1, 1]).is_err());
+/// assert_eq!(v.get_many_mut([0, 999]), Err(GetManyMutError::IndexOutOfBounds));
+/// assert_eq!(v.get_many_mut([1, 1]), Err(GetManyMutError::OverlappingIndices));
 /// ```
 #[unstable(feature = "get_many_mut", issue = "104642")]
-// NB: The N here is there to be forward-compatible with adding more details
-// to the error type at a later point
-#[derive(Clone, PartialEq, Eq)]
-pub struct GetManyMutError<const N: usize> {
-    _private: (),
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum GetManyMutError {
+    /// An index provided was out-of-bounds for the slice.
+    IndexOutOfBounds,
+    /// Two indices provided were overlapping.
+    OverlappingIndices,
 }
 
 #[unstable(feature = "get_many_mut", issue = "104642")]
-impl<const N: usize> fmt::Debug for GetManyMutError<N> {
+impl fmt::Display for GetManyMutError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("GetManyMutError").finish_non_exhaustive()
-    }
-}
-
-#[unstable(feature = "get_many_mut", issue = "104642")]
-impl<const N: usize> fmt::Display for GetManyMutError<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt("an index is out of bounds or appeared multiple times in the array", f)
+        let msg = match self {
+            GetManyMutError::IndexOutOfBounds => "an index is out of bounds",
+            GetManyMutError::OverlappingIndices => "there were overlapping indices",
+        };
+        fmt::Display::fmt(msg, f)
     }
 }
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 49a03220039..047f5b0c4c5 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -348,7 +348,6 @@
 #![feature(pin_coerce_unsized_trait)]
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
-#![feature(prelude_2024)]
 #![feature(ptr_as_uninit)]
 #![feature(ptr_mask)]
 #![feature(random)]
diff --git a/library/std/src/os/hurd/mod.rs b/library/std/src/os/hurd/mod.rs
index aee86c7f616..6cd50aeada1 100644
--- a/library/std/src/os/hurd/mod.rs
+++ b/library/std/src/os/hurd/mod.rs
@@ -1,6 +1,7 @@
 //! Hurd-specific definitions
 
 #![stable(feature = "raw_ext", since = "1.1.0")]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 pub mod fs;
 pub mod raw;
diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs
index e4731280ffe..22a364074c5 100644
--- a/library/std/src/prelude/common.rs
+++ b/library/std/src/prelude/common.rs
@@ -12,7 +12,8 @@ pub use crate::marker::{Send, Sized, Sync, Unpin};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
-#[unstable(feature = "async_closure", issue = "62290")]
+#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
+#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
 #[doc(no_inline)]
 pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
 
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 0c610ba67e6..64349987fcf 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -25,6 +25,7 @@
 //!
 //! # Prelude contents
 //!
+//! The items included in the prelude depend on the edition of the crate.
 //! The first version of the prelude is used in Rust 2015 and Rust 2018,
 //! and lives in [`std::prelude::v1`].
 //! [`std::prelude::rust_2015`] and [`std::prelude::rust_2018`] re-export this prelude.
@@ -32,8 +33,9 @@
 //!
 //! * <code>[std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}</code>,
 //!   marker traits that indicate fundamental properties of types.
-//! * <code>[std::ops]::{[Drop], [Fn], [FnMut], [FnOnce]}</code>, various
-//!   operations for both destructors and overloading `()`.
+//! * <code>[std::ops]::{[Fn], [FnMut], [FnOnce]}</code>, and their analogous
+//!   async traits, <code>[std::ops]::{[AsyncFn], [AsyncFnMut], [AsyncFnOnce]}</code>.
+//! * <code>[std::ops]::[Drop]</code>, for implementing destructors.
 //! * <code>[std::mem]::[drop]</code>, a convenience function for explicitly
 //!   dropping a value.
 //! * <code>[std::mem]::{[size_of], [size_of_val]}</code>, to get the size of
@@ -67,15 +69,21 @@
 //! The prelude used in Rust 2021, [`std::prelude::rust_2021`], includes all of the above,
 //! and in addition re-exports:
 //!
-//! * <code>[std::convert]::{[TryFrom], [TryInto]}</code>,
+//! * <code>[std::convert]::{[TryFrom], [TryInto]}</code>.
 //! * <code>[std::iter]::[FromIterator]</code>.
 //!
+//! The prelude used in Rust 2024, [`std::prelude::rust_2024`], includes all of the above,
+//! and in addition re-exports:
+//!
+//! * <code>[std::future]::{[Future], [IntoFuture]}</code>.
+//!
 //! [std::borrow]: crate::borrow
 //! [std::boxed]: crate::boxed
 //! [std::clone]: crate::clone
 //! [std::cmp]: crate::cmp
 //! [std::convert]: crate::convert
 //! [std::default]: crate::default
+//! [std::future]: crate::future
 //! [std::iter]: crate::iter
 //! [std::marker]: crate::marker
 //! [std::mem]: crate::mem
@@ -85,6 +93,7 @@
 //! [`std::prelude::rust_2015`]: rust_2015
 //! [`std::prelude::rust_2018`]: rust_2018
 //! [`std::prelude::rust_2021`]: rust_2021
+//! [`std::prelude::rust_2024`]: rust_2024
 //! [std::result]: crate::result
 //! [std::slice]: crate::slice
 //! [std::string]: crate::string
@@ -94,6 +103,8 @@
 //! [book-dtor]: ../../book/ch15-03-drop.html
 //! [book-enums]: ../../book/ch06-01-defining-an-enum.html
 //! [book-iter]: ../../book/ch13-02-iterators.html
+//! [Future]: crate::future::Future
+//! [IntoFuture]: crate::future::IntoFuture
 
 // No formatting: this file is nothing but re-exports, and their order is worth preserving.
 #![cfg_attr(rustfmt, rustfmt::skip)]
@@ -158,12 +169,12 @@ pub mod rust_2021 {
 /// The 2024 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2024", issue = "121042")]
+#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
 pub mod rust_2024 {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::common::*;
 
-    #[unstable(feature = "prelude_2024", issue = "121042")]
+    #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")]
     #[doc(no_inline)]
     pub use core::prelude::rust_2024::*;
 }
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 79baa5b0b83..40d409310ff 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -178,3 +178,8 @@ cfg_if::cfg_if! {
 #[cfg(target_os = "hurd")]
 #[link(name = "gcc_s")]
 extern "C" {}
+
+#[cfg(all(target_os = "windows", target_env = "gnu", target_abi = "llvm"))]
+#[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
+#[link(name = "unwind", cfg(not(target_feature = "crt-static")))]
+extern "C" {}
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 715f8b57876..1fa9e480166 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -102,12 +102,9 @@ pub type _Unwind_Exception_Cleanup_Fn =
 // rustc_codegen_ssa::src::back::symbol_export, rustc_middle::middle::exported_symbols
 // and RFC 2841
 #[cfg_attr(
-    any(
-        all(
-            feature = "llvm-libunwind",
-            any(target_os = "fuchsia", target_os = "linux", target_os = "xous")
-        ),
-        all(target_os = "windows", target_env = "gnu", target_abi = "llvm")
+    all(
+        feature = "llvm-libunwind",
+        any(target_os = "fuchsia", target_os = "linux", target_os = "xous")
     ),
     link(name = "unwind", kind = "static", modifiers = "-bundle")
 )]
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 74dfe2e7ec8..ee813de1c9e 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -48,9 +48,9 @@ fn main() {
             err => {
                 drop(err);
                 if let Ok(pid) = pid {
-                    eprintln!("WARNING: build directory locked by process {pid}, waiting for lock");
+                    println!("WARNING: build directory locked by process {pid}, waiting for lock");
                 } else {
-                    eprintln!("WARNING: build directory locked, waiting for lock");
+                    println!("WARNING: build directory locked, waiting for lock");
                 }
                 let mut lock = t!(build_lock.write());
                 t!(lock.write(process::id().to_string().as_ref()));
@@ -70,13 +70,13 @@ fn main() {
     // changelog warning, not the `x.py setup` message.
     let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
     if suggest_setup {
-        eprintln!("WARNING: you have not made a `config.toml`");
-        eprintln!(
+        println!("WARNING: you have not made a `config.toml`");
+        println!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        eprintln!("{suggestion}");
+        println!("{suggestion}");
     }
 
     let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
@@ -86,13 +86,13 @@ fn main() {
     Build::new(config).build();
 
     if suggest_setup {
-        eprintln!("WARNING: you have not made a `config.toml`");
-        eprintln!(
+        println!("WARNING: you have not made a `config.toml`");
+        println!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        eprintln!("{suggestion}");
+        println!("{suggestion}");
     }
 
     // Give a warning if the pre-commit script is in pre-commit and not pre-push.
@@ -102,14 +102,14 @@ fn main() {
     if fs::read_to_string(pre_commit).is_ok_and(|contents| {
         contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
     }) {
-        eprintln!(
+        println!(
             "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
                   Consider moving it to .git/hooks/pre-push instead, which runs less often."
         );
     }
 
     if suggest_setup || changelog_suggestion.is_some() {
-        eprintln!("NOTE: this message was printed twice to make it more likely to be seen");
+        println!("NOTE: this message was printed twice to make it more likely to be seen");
     }
 
     if dump_bootstrap_shims {
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index e57ed488f97..88595ff7e51 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -306,7 +306,7 @@ fn main() {
         // should run on success, after this block.
     }
     if verbose > 0 {
-        eprintln!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
+        println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
     }
 
     if let Some(mut on_fail) = on_fail {
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 2af2e83db8f..d46c0ab7fef 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -287,7 +287,7 @@ impl Step for CodegenBackend {
     fn run(self, builder: &Builder<'_>) {
         // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
         if builder.build.config.vendor && self.backend == "gcc" {
-            eprintln!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
+            println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
             return;
         }
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 93f8091299f..0cacd6e4f37 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1611,7 +1611,7 @@ impl Step for Sysroot {
         let sysroot = sysroot_dir(compiler.stage);
 
         builder
-            .verbose(|| eprintln!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
+            .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
         let _ = fs::remove_dir_all(&sysroot);
         t!(fs::create_dir_all(&sysroot));
 
@@ -1681,7 +1681,7 @@ impl Step for Sysroot {
                     return true;
                 }
                 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
-                    builder.verbose_than(1, || eprintln!("ignoring {}", path.display()));
+                    builder.verbose_than(1, || println!("ignoring {}", path.display()));
                     false
                 } else {
                     true
@@ -2240,7 +2240,7 @@ pub fn stream_cargo(
         cargo.arg(arg);
     }
 
-    builder.verbose(|| eprintln!("running: {cargo:?}"));
+    builder.verbose(|| println!("running: {cargo:?}"));
 
     if builder.config.dry_run() {
         return true;
@@ -2266,7 +2266,7 @@ pub fn stream_cargo(
                 cb(msg)
             }
             // If this was informational, just print it out and continue
-            Err(_) => eprintln!("{line}"),
+            Err(_) => println!("{line}"),
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 57fce206f95..0c739115165 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -2080,7 +2080,7 @@ fn maybe_install_llvm(
     {
         let mut cmd = command(llvm_config);
         cmd.arg("--libfiles");
-        builder.verbose(|| eprintln!("running {cmd:?}"));
+        builder.verbose(|| println!("running {cmd:?}"));
         let files = cmd.run_capture_stdout(builder).stdout();
         let build_llvm_out = &builder.llvm_out(builder.config.build);
         let target_llvm_out = &builder.llvm_out(target);
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index d32e06d8748..29a96f77672 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -107,10 +107,10 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
         if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
     if len <= 10 {
         for path in paths {
-            eprintln!("fmt: {verb} {adjective}file {path}");
+            println!("fmt: {verb} {adjective}file {path}");
         }
     } else {
-        eprintln!("fmt: {verb} {len} {adjective}files");
+        println!("fmt: {verb} {len} {adjective}files");
     }
 }
 
@@ -199,7 +199,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
                 match get_modified_rs_files(build) {
                     Ok(Some(files)) => {
                         if files.is_empty() {
-                            eprintln!("fmt info: No modified files detected for formatting.");
+                            println!("fmt info: No modified files detected for formatting.");
                             return;
                         }
 
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 175e9982cc1..7ed01f25c94 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -134,7 +134,7 @@ impl Step for Profile {
                     t!(fs::remove_file(path));
                 }
                 _ => {
-                    eprintln!("Exiting.");
+                    println!("Exiting.");
                     crate::exit!(1);
                 }
             }
@@ -184,15 +184,15 @@ pub fn setup(config: &Config, profile: Profile) {
         Profile::Dist => &["dist", "build"],
     };
 
-    eprintln!();
+    println!();
 
-    eprintln!("To get started, try one of the following commands:");
+    println!("To get started, try one of the following commands:");
     for cmd in suggestions {
-        eprintln!("- `x.py {cmd}`");
+        println!("- `x.py {cmd}`");
     }
 
     if profile != Profile::Dist {
-        eprintln!(
+        println!(
             "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
         );
     }
@@ -224,7 +224,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
     t!(fs::write(path, settings));
 
     let include_path = profile.include_path(&config.src);
-    eprintln!("`x.py` will now use the configuration at {}", include_path.display());
+    println!("`x.py` will now use the configuration at {}", include_path.display());
 }
 
 /// Creates a toolchain link for stage1 using `rustup`
@@ -256,7 +256,7 @@ impl Step for Link {
         }
 
         if !rustup_installed(builder) {
-            eprintln!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
+            println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
             return;
         }
 
@@ -296,7 +296,7 @@ fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
     }
 
     if try_link_toolchain(builder, stage_path) {
-        eprintln!(
+        println!(
             "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
         );
     } else {
@@ -321,14 +321,14 @@ fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
                 return false;
             }
             // The toolchain has already been linked.
-            eprintln!(
+            println!(
                 "`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
             );
         }
         None => {
             // In this case, we don't know if the `stage1` toolchain has been linked;
             // but `rustup` failed, so let's not go any further.
-            eprintln!(
+            println!(
                 "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
             );
         }
@@ -389,12 +389,12 @@ pub fn interactive_path() -> io::Result<Profile> {
         input.parse()
     }
 
-    eprintln!("Welcome to the Rust project! What do you want to do with x.py?");
+    println!("Welcome to the Rust project! What do you want to do with x.py?");
     for ((letter, _), profile) in abbrev_all() {
-        eprintln!("{}) {}: {}", letter, profile, profile.purpose());
+        println!("{}) {}: {}", letter, profile, profile.purpose());
     }
     let template = loop {
-        eprint!(
+        print!(
             "Please choose one ({}): ",
             abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
         );
@@ -428,7 +428,7 @@ enum PromptResult {
 fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
     let mut input = String::new();
     loop {
-        eprint!("{prompt} ");
+        print!("{prompt} ");
         io::stdout().flush()?;
         input.clear();
         io::stdin().read_line(&mut input)?;
@@ -490,7 +490,7 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
         return Ok(());
     }
 
-    eprintln!(
+    println!(
         "\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
 If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
 pushing your code to ensure your code is up to par. If you decide later that this behavior is
@@ -498,7 +498,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
     );
 
     if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
-        eprintln!("Ok, skipping installation!");
+        println!("Ok, skipping installation!");
         return Ok(());
     }
     if !hooks_dir.exists() {
@@ -515,7 +515,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
             );
             return Err(e);
         }
-        Ok(_) => eprintln!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
+        Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
     };
     Ok(())
 }
@@ -541,7 +541,7 @@ Select which editor you would like to set up [default: None]: ";
 
         let mut input = String::new();
         loop {
-            eprint!("{}", prompt_str);
+            print!("{}", prompt_str);
             io::stdout().flush()?;
             input.clear();
             io::stdin().read_line(&mut input)?;
@@ -656,7 +656,7 @@ impl Step for Editor {
                 if let Some(editor_kind) = editor_kind {
                     while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
                 } else {
-                    eprintln!("Ok, skipping editor setup!");
+                    println!("Ok, skipping editor setup!");
                 }
             }
             Err(e) => eprintln!("Could not determine the editor: {e}"),
@@ -689,7 +689,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             mismatched_settings = Some(false);
         }
     }
-    eprintln!(
+    println!(
         "\nx.py can automatically install the recommended `{settings_filename}` file for rustc development"
     );
 
@@ -708,7 +708,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
         Some(PromptResult::Yes) => true,
         Some(PromptResult::Print) => false,
         _ => {
-            eprintln!("Ok, skipping settings!");
+            println!("Ok, skipping settings!");
             return Ok(true);
         }
     };
@@ -735,9 +735,9 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             _ => "Created",
         };
         fs::write(&settings_path, editor.settings_template())?;
-        eprintln!("{verb} `{}`", settings_filename);
+        println!("{verb} `{}`", settings_filename);
     } else {
-        eprintln!("\n{}", editor.settings_template());
+        println!("\n{}", editor.settings_template());
     }
     Ok(should_create)
 }
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index 7b2d9fff8f5..ba9b1b2fc33 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -66,6 +66,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
             build.build();
         }
     } else {
-        eprintln!("HELP: consider using the `--run` flag to automatically run suggested tests");
+        println!("HELP: consider using the `--run` flag to automatically run suggested tests");
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 380626952b2..30fdea7e19e 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -471,11 +471,11 @@ impl Miri {
         // We re-use the `cargo` from above.
         cargo.arg("--print-sysroot");
 
-        builder.verbose(|| eprintln!("running: {cargo:?}"));
+        builder.verbose(|| println!("running: {cargo:?}"));
         let stdout = cargo.run_capture_stdout(builder).stdout();
         // Output is "<sysroot>\n".
         let sysroot = stdout.trim_end();
-        builder.verbose(|| eprintln!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
+        builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
         PathBuf::from(sysroot)
     }
 }
@@ -2488,7 +2488,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
         }
     }
 
-    builder.verbose(|| eprintln!("doc tests for: {}", markdown.display()));
+    builder.verbose(|| println!("doc tests for: {}", markdown.display()));
     let mut cmd = builder.rustdoc_cmd(compiler);
     builder.add_rust_test_threads(&mut cmd);
     // allow for unstable options such as new editions
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 38abca8b8da..96d3162a8c5 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -523,7 +523,7 @@ impl Builder<'_> {
 
         let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
         if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) {
-            eprintln!("using sysroot {sysroot_str}");
+            println!("using sysroot {sysroot_str}");
         }
 
         let mut rustflags = Rustflags::new(target);
@@ -1035,12 +1035,7 @@ impl Builder<'_> {
             rustflags.arg("-Wrustc::internal");
             // cfg(bootstrap) - remove this check when lint is in bootstrap compiler
             if stage != 0 {
-                // Lint is allow by default so downstream tools don't get a lit
-                // they can do nothing about
-                // We shouldn't be preinterning symbols used by tests
-                if cmd_kind != Kind::Test {
-                    rustflags.arg("-Drustc::symbol_intern_string_literal");
-                }
+                rustflags.arg("-Drustc::symbol_intern_string_literal");
             }
             // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
             // of the individual lints are satisfied.
@@ -1208,6 +1203,11 @@ impl Builder<'_> {
             // even if we're not going to output debuginfo for the crate we're currently building,
             // so that it'll be available when downstream consumers of std try to use it.
             rustflags.arg("-Zinline-mir-preserve-debug");
+
+            // FIXME: always pass this after the next `#[cfg(bootstrap)]` update.
+            if compiler.stage != 0 {
+                rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions");
+            }
         }
 
         Cargo {
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index ffe3e053e72..026c26479d3 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -392,14 +392,14 @@ impl StepDescription {
     fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
         if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
             if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
-                eprintln!("Skipping {pathset:?} because it is excluded");
+                println!("Skipping {pathset:?} because it is excluded");
             }
             return true;
         }
 
         if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
             builder.verbose(|| {
-                eprintln!(
+                println!(
                     "{:?} not skipped for {:?} -- not in {:?}",
                     pathset, self.name, builder.config.skip
                 )
@@ -1437,11 +1437,11 @@ impl<'a> Builder<'a> {
                 panic!("{}", out);
             }
             if let Some(out) = self.cache.get(&step) {
-                self.verbose_than(1, || eprintln!("{}c {:?}", "  ".repeat(stack.len()), step));
+                self.verbose_than(1, || println!("{}c {:?}", "  ".repeat(stack.len()), step));
 
                 return out;
             }
-            self.verbose_than(1, || eprintln!("{}> {:?}", "  ".repeat(stack.len()), step));
+            self.verbose_than(1, || println!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
 
@@ -1462,7 +1462,7 @@ impl<'a> Builder<'a> {
             let step_string = format!("{step:?}");
             let brace_index = step_string.find('{').unwrap_or(0);
             let type_string = type_name::<S>();
-            eprintln!(
+            println!(
                 "[TIMING] {} {} -- {}.{:03}",
                 &type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
                 &step_string[brace_index..],
@@ -1479,9 +1479,7 @@ impl<'a> Builder<'a> {
             let cur_step = stack.pop().expect("step stack empty");
             assert_eq!(cur_step.downcast_ref(), Some(&step));
         }
-        self.verbose_than(1, || {
-            eprintln!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step)
-        });
+        self.verbose_than(1, || println!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step));
         self.cache.put(step, out.clone());
         out
     }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 002b990bb52..c6800aedca9 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1299,7 +1299,7 @@ impl Config {
                     .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
                 {
                     if !changes.is_empty() {
-                        eprintln!(
+                        println!(
                             "WARNING: There have been changes to x.py since you last updated:\n{}",
                             crate::human_readable_changes(&changes)
                         );
@@ -1565,7 +1565,7 @@ impl Config {
         }
 
         if cargo_clippy.is_some() && rustc.is_none() {
-            eprintln!(
+            println!(
                 "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
             );
         }
@@ -1852,7 +1852,7 @@ impl Config {
 
             // FIXME: Remove this option at the end of 2024.
             if parallel_compiler.is_some() {
-                eprintln!(
+                println!(
                     "WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default"
                 );
             }
@@ -1884,7 +1884,7 @@ impl Config {
                         if available_backends.contains(&backend) {
                             panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
                         } else {
-                            eprintln!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
+                            println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
                                 Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                 In this case, it would be referred to as '{backend}'.");
                         }
@@ -1913,7 +1913,7 @@ impl Config {
         // tests may fail due to using a different channel than the one used by the compiler during tests.
         if let Some(commit) = &config.download_rustc_commit {
             if is_user_configured_rust_channel {
-                eprintln!(
+                println!(
                     "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
                 );
 
@@ -2003,10 +2003,10 @@ impl Config {
 
             if config.llvm_from_ci {
                 let warn = |option: &str| {
-                    eprintln!(
+                    println!(
                         "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
                     );
-                    eprintln!(
+                    println!(
                         "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
                     );
                 };
@@ -2025,12 +2025,12 @@ impl Config {
                 // if they've chosen a different value.
 
                 if libzstd.is_some() {
-                    eprintln!(
+                    println!(
                         "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
                         like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
                         artifacts builder config."
                     );
-                    eprintln!(
+                    println!(
                         "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
                     );
                 }
@@ -2099,7 +2099,7 @@ impl Config {
                             if available_backends.contains(&backend) {
                                 panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
                             } else {
-                                eprintln!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
+                                println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
                                     Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                     In this case, it would be referred to as '{backend}'.");
                             }
@@ -2315,7 +2315,7 @@ impl Config {
         if self.dry_run() {
             return Ok(());
         }
-        self.verbose(|| eprintln!("running: {cmd:?}"));
+        self.verbose(|| println!("running: {cmd:?}"));
         build_helper::util::try_run(cmd, self.is_verbose())
     }
 
@@ -2490,7 +2490,7 @@ impl Config {
                         // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error
                         // to not break CI. For non-CI environments, we should return an error.
                         if CiEnv::is_ci() {
-                            eprintln!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
+                            println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
                             return None;
                         } else {
                             panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");
@@ -2501,8 +2501,8 @@ impl Config {
                         let ci_config_toml = match self.get_builder_toml("ci-rustc") {
                             Ok(ci_config_toml) => ci_config_toml,
                             Err(e) if e.to_string().contains("unknown field") => {
-                                eprintln!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
-                                eprintln!("HELP: Consider rebasing to a newer commit if available.");
+                                println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
+                                println!("HELP: Consider rebasing to a newer commit if available.");
                                 return None;
                             },
                             Err(e) => {
@@ -2527,7 +2527,7 @@ impl Config {
                             .is_some_and(|s| s == "1" || s == "true");
 
                         if disable_ci_rustc_if_incompatible && res.is_err() {
-                            eprintln!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
+                            println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
                             return None;
                         }
 
@@ -2712,7 +2712,7 @@ impl Config {
             return;
         }
 
-        eprintln!("Updating submodule {relative_path}");
+        println!("Updating submodule {relative_path}");
         self.check_run(
             helpers::git(Some(&self.src))
                 .run_always()
@@ -2835,7 +2835,7 @@ impl Config {
             Some(StringOrBool::Bool(true)) => false,
             Some(StringOrBool::String(s)) if s == "if-unchanged" => {
                 if !self.rust_info.is_managed_git_subrepository() {
-                    eprintln!(
+                    println!(
                         "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
                     );
                     crate::exit!(1);
@@ -2868,10 +2868,10 @@ impl Config {
                 if if_unchanged {
                     return None;
                 }
-                eprintln!("ERROR: could not find commit hash for downloading rustc");
-                eprintln!("HELP: maybe your repository history is too shallow?");
-                eprintln!("HELP: consider setting `rust.download-rustc=false` in config.toml");
-                eprintln!("HELP: or fetch enough history to include one upstream commit");
+                println!("ERROR: could not find commit hash for downloading rustc");
+                println!("HELP: maybe your repository history is too shallow?");
+                println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
+                println!("HELP: or fetch enough history to include one upstream commit");
                 crate::exit!(1);
             }
         };
@@ -2910,7 +2910,7 @@ impl Config {
         let if_unchanged = || {
             if self.rust_info.is_from_tarball() {
                 // Git is needed for running "if-unchanged" logic.
-                eprintln!(
+                println!(
                     "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
                 );
                 return false;
@@ -2959,10 +2959,10 @@ impl Config {
         // Only commits merged by bors will have CI artifacts.
         let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
         if commit.is_empty() {
-            eprintln!("error: could not find commit hash for downloading components from CI");
-            eprintln!("help: maybe your repository history is too shallow?");
-            eprintln!("help: consider disabling `{option_name}`");
-            eprintln!("help: or fetch enough history to include one upstream commit");
+            println!("error: could not find commit hash for downloading components from CI");
+            println!("help: maybe your repository history is too shallow?");
+            println!("help: consider disabling `{option_name}`");
+            println!("help: or fetch enough history to include one upstream commit");
             crate::exit!(1);
         }
 
@@ -2974,14 +2974,14 @@ impl Config {
         if has_changes {
             if if_unchanged {
                 if self.is_verbose() {
-                    eprintln!(
+                    println!(
                         "warning: saw changes to one of {modified_paths:?} since {commit}; \
                             ignoring `{option_name}`"
                     );
                 }
                 return None;
             }
-            eprintln!(
+            println!(
                 "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
             );
         }
@@ -3018,7 +3018,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
         ($current:expr, $expected:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    eprintln!(
+                    println!(
                         "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
                         stringify!($expected).replace("_", "-"),
@@ -3123,7 +3123,7 @@ fn check_incompatible_options_for_ci_rustc(
         ($current:expr, $expected:expr, $config_section:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    eprintln!(
+                    println!(
                         "WARNING: `{}` has no effect with `rust.download-rustc`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
                         format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 66b9f5ed84e..bfeb811508c 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -196,12 +196,12 @@ impl Flags {
         if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
             HelpVerboseOnly::try_parse_from(normalize_args(args))
         {
-            eprintln!("NOTE: updating submodules before printing available paths");
+            println!("NOTE: updating submodules before printing available paths");
             let config = Config::parse(Self::parse(&[String::from("build")]));
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
             if let Some(s) = paths {
-                eprintln!("{s}");
+                println!("{s}");
             } else {
                 panic!("No paths available for subcommand `{}`", subcommand.as_str());
             }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 05b91c518cf..db35e6907e6 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -77,7 +77,7 @@ impl Config {
         if self.dry_run() && !cmd.run_always {
             return true;
         }
-        self.verbose(|| eprintln!("running: {cmd:?}"));
+        self.verbose(|| println!("running: {cmd:?}"));
         check_run(cmd, self.is_verbose())
     }
 
@@ -144,7 +144,7 @@ impl Config {
     /// Please see <https://nixos.org/patchelf.html> for more information
     fn fix_bin_or_dylib(&self, fname: &Path) {
         assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
-        eprintln!("attempting to patch {}", fname.display());
+        println!("attempting to patch {}", fname.display());
 
         // Only build `.nix-deps` once.
         static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new();
@@ -206,7 +206,7 @@ impl Config {
     }
 
     fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
-        self.verbose(|| eprintln!("download {url}"));
+        self.verbose(|| println!("download {url}"));
         // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
         let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
         // While bootstrap itself only supports http and https downloads, downstream forks might
@@ -226,7 +226,7 @@ impl Config {
     }
 
     fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
-        eprintln!("downloading {url}");
+        println!("downloading {url}");
         // Try curl. If that fails and we are on windows, fallback to PowerShell.
         // options should be kept in sync with
         // src/bootstrap/src/core/download.rs
@@ -341,7 +341,7 @@ impl Config {
             short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
             let dst_path = dst.join(short_path);
             self.verbose(|| {
-                eprintln!("extracting {} to {}", original_path.display(), dst.display())
+                println!("extracting {} to {}", original_path.display(), dst.display())
             });
             if !t!(member.unpack_in(dst)) {
                 panic!("path traversal attack ??");
@@ -365,7 +365,7 @@ impl Config {
     pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
         use sha2::Digest;
 
-        self.verbose(|| eprintln!("verifying {}", path.display()));
+        self.verbose(|| println!("verifying {}", path.display()));
 
         if self.dry_run() {
             return false;
@@ -391,7 +391,7 @@ impl Config {
         let verified = checksum == expected;
 
         if !verified {
-            eprintln!(
+            println!(
                 "invalid checksum: \n\
                 found:    {checksum}\n\
                 expected: {expected}",
@@ -421,7 +421,7 @@ enum DownloadSource {
 /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
 impl Config {
     pub(crate) fn download_clippy(&self) -> PathBuf {
-        self.verbose(|| eprintln!("downloading stage0 clippy artifacts"));
+        self.verbose(|| println!("downloading stage0 clippy artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
@@ -518,7 +518,7 @@ impl Config {
     }
 
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
-        self.verbose(|| eprintln!("using downloaded stage2 artifacts from CI (commit {commit})"));
+        self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
 
         let version = self.artifact_version_part(commit);
         // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@@ -539,7 +539,7 @@ impl Config {
 
     #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn download_beta_toolchain(&self) {
-        self.verbose(|| eprintln!("downloading stage0 beta artifacts"));
+        self.verbose(|| println!("downloading stage0 beta artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
@@ -677,7 +677,7 @@ impl Config {
                     return;
                 } else {
                     self.verbose(|| {
-                        eprintln!(
+                        println!(
                             "ignoring cached file {} due to failed verification",
                             tarball.display()
                         )
@@ -776,10 +776,10 @@ download-rustc = false
                     t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
                 }
                 Err(e) if e.to_string().contains("unknown field") => {
-                    eprintln!(
+                    println!(
                         "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
                     );
-                    eprintln!("HELP: Consider rebasing to a newer commit if available.");
+                    println!("HELP: Consider rebasing to a newer commit if available.");
                 }
                 Err(e) => {
                     eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 71e7f40f032..dcf68cbeeda 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -237,11 +237,11 @@ than building it.
                 stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
 
             if !duplicated_targets.is_empty() {
-                eprintln!(
+                println!(
                     "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
                 );
                 for duplicated_target in duplicated_targets {
-                    eprintln!("  {duplicated_target}");
+                    println!("  {duplicated_target}");
                 }
                 std::process::exit(1);
             }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 5f778223d7d..0ecf61ffcd9 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -406,11 +406,11 @@ impl Build {
             .unwrap()
             .trim();
         if local_release.split('.').take(2).eq(version.split('.').take(2)) {
-            build.verbose(|| eprintln!("auto-detected local-rebuild {local_release}"));
+            build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
             build.local_rebuild = true;
         }
 
-        build.verbose(|| eprintln!("finding compilers"));
+        build.verbose(|| println!("finding compilers"));
         utils::cc_detect::find(&build);
         // When running `setup`, the profile is about to change, so any requirements we have now may
         // be different on the next invocation. Don't check for them until the next time x.py is
@@ -418,7 +418,7 @@ impl Build {
         //
         // Similarly, for `setup` we don't actually need submodules or cargo metadata.
         if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
-            build.verbose(|| eprintln!("running sanity check"));
+            build.verbose(|| println!("running sanity check"));
             crate::core::sanity::check(&mut build);
 
             // Make sure we update these before gathering metadata so we don't get an error about missing
@@ -436,7 +436,7 @@ impl Build {
             // Now, update all existing submodules.
             build.update_existing_submodules();
 
-            build.verbose(|| eprintln!("learning about cargo"));
+            build.verbose(|| println!("learning about cargo"));
             crate::core::metadata::build(&mut build);
         }
 
@@ -605,7 +605,7 @@ impl Build {
         let stamp = dir.join(".stamp");
         let mut cleared = false;
         if mtime(&stamp) < mtime(input) {
-            self.verbose(|| eprintln!("Dirty - {}", dir.display()));
+            self.verbose(|| println!("Dirty - {}", dir.display()));
             let _ = fs::remove_dir_all(dir);
             cleared = true;
         } else if stamp.exists() {
@@ -890,7 +890,7 @@ impl Build {
         let executed_at = std::panic::Location::caller();
 
         self.verbose(|| {
-            eprintln!("running: {command:?} (created at {created_at}, executed at {executed_at})")
+            println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
         });
 
         let cmd = command.as_command_mut();
@@ -947,7 +947,7 @@ Executed at: {executed_at}"#,
 
         let fail = |message: &str, output: CommandOutput| -> ! {
             if self.is_verbose() {
-                eprintln!("{message}");
+                println!("{message}");
             } else {
                 let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
                 // If the command captures output, the user would not see any indication that
@@ -957,16 +957,16 @@ Executed at: {executed_at}"#,
                     if let Some(stdout) =
                         output.stdout_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        eprintln!("STDOUT:\n{stdout}\n");
+                        println!("STDOUT:\n{stdout}\n");
                     }
                     if let Some(stderr) =
                         output.stderr_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        eprintln!("STDERR:\n{stderr}\n");
+                        println!("STDERR:\n{stderr}\n");
                     }
-                    eprintln!("Command {command:?} has failed. Rerun with -v to see more details.");
+                    println!("Command {command:?} has failed. Rerun with -v to see more details.");
                 } else {
-                    eprintln!("Command has failed. Rerun with -v to see more details.");
+                    println!("Command has failed. Rerun with -v to see more details.");
                 }
             }
             exit!(1);
@@ -1011,7 +1011,7 @@ Executed at: {executed_at}"#,
         match self.config.dry_run {
             DryRun::SelfCheck => (),
             DryRun::Disabled | DryRun::UserSelected => {
-                eprintln!("{msg}");
+                println!("{msg}");
             }
         }
     }
@@ -1666,7 +1666,7 @@ Executed at: {executed_at}"#,
         if self.config.dry_run() {
             return;
         }
-        self.verbose_than(1, || eprintln!("Copy/Link {src:?} to {dst:?}"));
+        self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
         if src == dst {
             return;
         }
@@ -1775,7 +1775,7 @@ Executed at: {executed_at}"#,
             return;
         }
         let dst = dstdir.join(src.file_name().unwrap());
-        self.verbose_than(1, || eprintln!("Install {src:?} to {dst:?}"));
+        self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
         t!(fs::create_dir_all(dstdir));
         if !src.exists() {
             panic!("ERROR: File \"{}\" not found!", src.display());
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index e8d5b60948a..0df00469452 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -155,15 +155,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
         build.cxx.borrow_mut().insert(target, compiler);
     }
 
-    build.verbose(|| eprintln!("CC_{} = {:?}", target.triple, build.cc(target)));
-    build.verbose(|| eprintln!("CFLAGS_{} = {cflags:?}", target.triple));
+    build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
+    build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
     if let Ok(cxx) = build.cxx(target) {
         let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
-        build.verbose(|| eprintln!("CXX_{} = {cxx:?}", target.triple));
-        build.verbose(|| eprintln!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
+        build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
+        build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
     }
     if let Some(ar) = ar {
-        build.verbose(|| eprintln!("AR_{} = {ar:?}", target.triple));
+        build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
         build.ar.borrow_mut().insert(target, ar);
     }
 
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index c0d52fd3430..923cc2dfc28 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -135,7 +135,7 @@ impl Drop for TimeIt {
     fn drop(&mut self) {
         let time = self.1.elapsed();
         if !self.0 {
-            eprintln!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
+            println!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
         }
     }
 }
@@ -267,12 +267,12 @@ pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
     let status = match cmd.as_command_mut().status() {
         Ok(status) => status,
         Err(e) => {
-            eprintln!("failed to execute command: {cmd:?}\nERROR: {e}");
+            println!("failed to execute command: {cmd:?}\nERROR: {e}");
             return false;
         }
     };
     if !status.success() && print_cmd_on_fail {
-        eprintln!(
+        println!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {status}\n\n"
         );
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 06d3add6281..b51fd490535 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -185,7 +185,7 @@ impl BuildMetrics {
                 if version.format_version == CURRENT_FORMAT_VERSION {
                     t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
                 } else {
-                    eprintln!(
+                    println!(
                         "WARNING: overriding existing build/metrics.json, as it's not \
                          compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
                     );
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index 7a3ec61c6da..eb2c8254dc0 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -56,7 +56,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
     let cmd = cmd.as_command_mut();
     cmd.stdout(Stdio::piped());
 
-    builder.verbose(|| eprintln!("running: {cmd:?}"));
+    builder.verbose(|| println!("running: {cmd:?}"));
 
     let mut process = cmd.spawn().unwrap();
 
@@ -71,7 +71,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
 
     let result = process.wait_with_output().unwrap();
     if !result.status.success() && builder.is_verbose() {
-        eprintln!(
+        println!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {}",
             result.status
@@ -135,9 +135,7 @@ impl<'a> Renderer<'a> {
         if self.up_to_date_tests > 0 {
             let n = self.up_to_date_tests;
             let s = if n > 1 { "s" } else { "" };
-            eprintln!(
-                "help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"
-            );
+            println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
         }
     }
 
@@ -187,12 +185,12 @@ impl<'a> Renderer<'a> {
     }
 
     fn render_test_outcome_verbose(&self, outcome: Outcome<'_>, test: &TestOutcome) {
-        eprint!("test {} ... ", test.name);
-        self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
+        print!("test {} ... ", test.name);
+        self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
         if let Some(exec_time) = test.exec_time {
-            eprint!(" ({exec_time:.2?})");
+            print!(" ({exec_time:.2?})");
         }
-        eprintln!();
+        println!();
     }
 
     fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
@@ -200,45 +198,45 @@ impl<'a> Renderer<'a> {
             if let Some(total) = self.tests_count {
                 let total = total.to_string();
                 let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len());
-                eprint!(" {executed}/{total}");
+                print!(" {executed}/{total}");
             }
-            eprintln!();
+            println!();
             self.terse_tests_in_line = 0;
         }
 
         self.terse_tests_in_line += 1;
-        self.builder.colored_stderr(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
+        self.builder.colored_stdout(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
         let _ = std::io::stdout().flush();
     }
 
     fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
         // The terse output doesn't end with a newline, so we need to add it ourselves.
         if !self.builder.config.verbose_tests {
-            eprintln!();
+            println!();
         }
 
         if !self.failures.is_empty() {
-            eprintln!("\nfailures:\n");
+            println!("\nfailures:\n");
             for failure in &self.failures {
                 if failure.stdout.is_some() || failure.message.is_some() {
-                    eprintln!("---- {} stdout ----", failure.name);
+                    println!("---- {} stdout ----", failure.name);
                     if let Some(stdout) = &failure.stdout {
-                        eprintln!("{stdout}");
+                        println!("{stdout}");
                     }
                     if let Some(message) = &failure.message {
-                        eprintln!("NOTE: {message}");
+                        println!("NOTE: {message}");
                     }
                 }
             }
 
-            eprintln!("\nfailures:");
+            println!("\nfailures:");
             for failure in &self.failures {
-                eprintln!("    {}", failure.name);
+                println!("    {}", failure.name);
             }
         }
 
         if !self.benches.is_empty() {
-            eprintln!("\nbenchmarks:");
+            println!("\nbenchmarks:");
 
             let mut rows = Vec::new();
             for bench in &self.benches {
@@ -253,13 +251,13 @@ impl<'a> Renderer<'a> {
             let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0);
             let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0);
             for row in &rows {
-                eprintln!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
+                println!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
             }
         }
 
-        eprint!("\ntest result: ");
-        self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
-        eprintln!(
+        print!("\ntest result: ");
+        self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
+        println!(
             ". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n",
             suite.passed,
             suite.failed,
@@ -276,7 +274,7 @@ impl<'a> Renderer<'a> {
     fn render_message(&mut self, message: Message) {
         match message {
             Message::Suite(SuiteMessage::Started { test_count }) => {
-                eprintln!("\nrunning {test_count} tests");
+                println!("\nrunning {test_count} tests");
                 self.executed_tests = 0;
                 self.terse_tests_in_line = 0;
                 self.tests_count = Some(test_count);
@@ -316,7 +314,7 @@ impl<'a> Renderer<'a> {
                 self.failures.push(outcome);
             }
             Message::Test(TestMessage::Timeout { name }) => {
-                eprintln!("test {name} has been running for a long time");
+                println!("test {name} has been running for a long time");
             }
             Message::Test(TestMessage::Started) => {} // Not useful
         }
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index f60498a4872..3c6c7a7fa18 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -344,7 +344,7 @@ impl<'a> Tarball<'a> {
         // For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
         let compression_profile = if self.builder.kind == Kind::Install {
             self.builder.verbose(|| {
-                eprintln!("Forcing dist.compression-profile = 'no-op' for `x install`.")
+                println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
             });
             // "no-op" indicates that the rust-installer won't produce compressed tarball sources.
             "no-op"
diff --git a/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
index 969389f92f7..7027c93857c 100755
--- a/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
@@ -35,7 +35,7 @@ PICK_REFS=()
 # commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
 # addition to versions of prebuilts. It should be bumped regularly by the
 # Fuchsia team – we aim for every 1-2 months.
-INTEGRATION_SHA=9f632bb7446d5a6af2998f1a0ebdb4b8ea2f4511
+INTEGRATION_SHA=bb38af4e3d45e490531b71fc52a460003141d032
 
 checkout=fuchsia
 jiri=.jiri_root/bin/jiri
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 34141c47cf3..50dfe0a1b56 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1841,9 +1841,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
         // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
         TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer,
-        TyKind::AnonAdt(..) => {
-            unimplemented!("Anonymous structs or unions are not supported yet")
-        }
     }
 }
 
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index cfb62c3ca16..91b31f31ab1 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -201,7 +201,7 @@ pub(crate) fn build_index(
                             // exported from this same module). It's also likely to Do
                             // What I Mean, since if a re-export changes the name, it might
                             // also be a change in semantic meaning.
-                            .filter(|fqp| fqp.last() == fqp.last());
+                            .filter(|this_fqp| this_fqp.last() == fqp.last());
                         Some(insert_into_map(
                             itemid_to_pathid,
                             ItemId::DefId(defid),
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index c449a1a875b..c300f7cd665 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -818,7 +818,6 @@ impl TyCoercionStability {
                 | TyKind::Typeof(..)
                 | TyKind::TraitObject(..)
                 | TyKind::InferDelegation(..)
-                | TyKind::AnonAdt(..)
                 | TyKind::Err(_) => Self::Reborrow,
             };
         }
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index ed27e38ef2d..1dac7b971f9 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
 
 impl EarlyLintPass for DuplicateMod {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind
+        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
             && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
             && let Some(local_path) = real.into_local_path()
             && let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index ffc76366983..dfea40db182 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
         }
 
         match &item.kind {
-            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
+            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
                 self.nest_level += 1;
 
                 if !self.check_indent(item.span, item.id) {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 620a9b56eb5..12074dd16e6 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Mod(lu, lmk), Mod(ru, rmk)) => {
             lu == ru
                 && match (lmk, rmk) {
-                    (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
+                    (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
                         linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
                     },
                     (ModKind::Unloaded, ModKind::Unloaded) => true,
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 4be4340862d..e318ad8671c 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -596,7 +596,6 @@ impl HirEqInterExpr<'_, '_, '_> {
             (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
             (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
             (&TyKind::Infer, &TyKind::Infer) => true,
-            (TyKind::AnonAdt(l_item_id), TyKind::AnonAdt(r_item_id)) => l_item_id == r_item_id,
             _ => false,
         }
     }
@@ -1246,8 +1245,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             | TyKind::Infer
             | TyKind::Never
             | TyKind::InferDelegation(..)
-            | TyKind::OpaqueDef(_)
-            | TyKind::AnonAdt(_) => {},
+            | TyKind::OpaqueDef(_) => {},
         }
     }
 
diff --git a/src/tools/clippy/tests/ui/async_yields_async.fixed b/src/tools/clippy/tests/ui/async_yields_async.fixed
index 208651bab1f..48402164a82 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.fixed
+++ b/src/tools/clippy/tests/ui/async_yields_async.fixed
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
 #![allow(clippy::redundant_async_block)]
 
diff --git a/src/tools/clippy/tests/ui/async_yields_async.rs b/src/tools/clippy/tests/ui/async_yields_async.rs
index b124c994442..8ad016b6bb4 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.rs
+++ b/src/tools/clippy/tests/ui/async_yields_async.rs
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 #![warn(clippy::async_yields_async)]
 #![allow(clippy::redundant_async_block)]
 
diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr
index 861c3f2ce4a..c900a9d7421 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.stderr
+++ b/src/tools/clippy/tests/ui/async_yields_async.stderr
@@ -1,5 +1,5 @@
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:38:9
+  --> tests/ui/async_yields_async.rs:37:9
    |
 LL |        let _h = async {
    |  _____________________-
@@ -20,7 +20,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:43:9
+  --> tests/ui/async_yields_async.rs:42:9
    |
 LL |       let _i = async {
    |  ____________________-
@@ -33,7 +33,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:49:9
+  --> tests/ui/async_yields_async.rs:48:9
    |
 LL |        let _j = async || {
    |  ________________________-
@@ -52,7 +52,7 @@ LL +         }.await
    |
 
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:54:9
+  --> tests/ui/async_yields_async.rs:53:9
    |
 LL |       let _k = async || {
    |  _______________________-
@@ -65,7 +65,7 @@ LL | |     };
    | |_____- outer async construct
 
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:56:23
+  --> tests/ui/async_yields_async.rs:55:23
    |
 LL |     let _l = async || CustomFutureType;
    |                       ^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@ LL |     let _l = async || CustomFutureType;
    |                       help: consider awaiting this value: `CustomFutureType.await`
 
 error: an async construct yields a type which is itself awaitable
-  --> tests/ui/async_yields_async.rs:62:9
+  --> tests/ui/async_yields_async.rs:61:9
    |
 LL |       let _m = async || {
    |  _______________________-
diff --git a/src/tools/clippy/tests/ui/author/blocks.rs b/src/tools/clippy/tests/ui/author/blocks.rs
index 164f7d0d9d6..e9db611a2aa 100644
--- a/src/tools/clippy/tests/ui/author/blocks.rs
+++ b/src/tools/clippy/tests/ui/author/blocks.rs
@@ -2,7 +2,6 @@
 
 #![allow(redundant_semicolons, clippy::no_effect)]
 #![feature(stmt_expr_attributes)]
-#![feature(async_closure)]
 
 #[rustfmt::skip]
 fn main() {
diff --git a/src/tools/clippy/tests/ui/infinite_loops.rs b/src/tools/clippy/tests/ui/infinite_loops.rs
index 0613eddce26..d7be6f9ce7e 100644
--- a/src/tools/clippy/tests/ui/infinite_loops.rs
+++ b/src/tools/clippy/tests/ui/infinite_loops.rs
@@ -3,7 +3,6 @@
 
 #![allow(clippy::never_loop)]
 #![warn(clippy::infinite_loop)]
-#![feature(async_closure)]
 
 extern crate proc_macros;
 use proc_macros::{external, with_span};
diff --git a/src/tools/clippy/tests/ui/infinite_loops.stderr b/src/tools/clippy/tests/ui/infinite_loops.stderr
index 3a3ed7d0fe8..7635a7442f4 100644
--- a/src/tools/clippy/tests/ui/infinite_loops.stderr
+++ b/src/tools/clippy/tests/ui/infinite_loops.stderr
@@ -1,5 +1,5 @@
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:14:5
+  --> tests/ui/infinite_loops.rs:13:5
    |
 LL | /     loop {
 LL | |
@@ -15,7 +15,7 @@ LL | fn no_break() -> ! {
    |               ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:21:5
+  --> tests/ui/infinite_loops.rs:20:5
    |
 LL | /     loop {
 LL | |
@@ -32,7 +32,7 @@ LL | fn all_inf() -> ! {
    |              ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:23:9
+  --> tests/ui/infinite_loops.rs:22:9
    |
 LL | /         loop {
 LL | |
@@ -49,7 +49,7 @@ LL | fn all_inf() -> ! {
    |              ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:25:13
+  --> tests/ui/infinite_loops.rs:24:13
    |
 LL | /             loop {
 LL | |
@@ -63,7 +63,7 @@ LL | fn all_inf() -> ! {
    |              ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:39:5
+  --> tests/ui/infinite_loops.rs:38:5
    |
 LL | /     loop {
 LL | |
@@ -74,7 +74,7 @@ LL | |     }
    = help: if this is not intended, try adding a `break` or `return` condition in the loop
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:52:5
+  --> tests/ui/infinite_loops.rs:51:5
    |
 LL | /     loop {
 LL | |         fn inner_fn() -> ! {
@@ -90,7 +90,7 @@ LL | fn no_break_never_ret_noise() -> ! {
    |                               ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:95:5
+  --> tests/ui/infinite_loops.rs:94:5
    |
 LL | /     loop {
 LL | |
@@ -107,7 +107,7 @@ LL | fn break_inner_but_not_outer_1(cond: bool) -> ! {
    |                                            ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:106:5
+  --> tests/ui/infinite_loops.rs:105:5
    |
 LL | /     loop {
 LL | |
@@ -124,7 +124,7 @@ LL | fn break_inner_but_not_outer_2(cond: bool) -> ! {
    |                                            ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:120:9
+  --> tests/ui/infinite_loops.rs:119:9
    |
 LL | /         loop {
 LL | |
@@ -138,7 +138,7 @@ LL | fn break_outer_but_not_inner() -> ! {
    |                                ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:143:9
+  --> tests/ui/infinite_loops.rs:142:9
    |
 LL | /         loop {
 LL | |
@@ -155,7 +155,7 @@ LL | fn break_wrong_loop(cond: bool) -> ! {
    |                                 ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:183:5
+  --> tests/ui/infinite_loops.rs:182:5
    |
 LL | /     loop {
 LL | |
@@ -172,7 +172,7 @@ LL | fn match_like() -> ! {
    |                 ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:224:5
+  --> tests/ui/infinite_loops.rs:223:5
    |
 LL | /     loop {
 LL | |
@@ -186,7 +186,7 @@ LL | fn match_like() -> ! {
    |                 ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:229:5
+  --> tests/ui/infinite_loops.rs:228:5
    |
 LL | /     loop {
 LL | |
@@ -203,7 +203,7 @@ LL | fn match_like() -> ! {
    |                 ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:334:9
+  --> tests/ui/infinite_loops.rs:333:9
    |
 LL | /         loop {
 LL | |
@@ -217,7 +217,7 @@ LL |     fn problematic_trait_method() -> ! {
    |                                   ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:344:9
+  --> tests/ui/infinite_loops.rs:343:9
    |
 LL | /         loop {
 LL | |
@@ -231,7 +231,7 @@ LL |     fn could_be_problematic() -> ! {
    |                               ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:353:9
+  --> tests/ui/infinite_loops.rs:352:9
    |
 LL | /         loop {
 LL | |
@@ -245,7 +245,7 @@ LL |     let _loop_forever = || -> ! {
    |                            ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:367:8
+  --> tests/ui/infinite_loops.rs:366:8
    |
 LL |       Ok(loop {
    |  ________^
@@ -256,7 +256,7 @@ LL | |     })
    = help: if this is not intended, try adding a `break` or `return` condition in the loop
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:409:5
+  --> tests/ui/infinite_loops.rs:408:5
    |
 LL | /     'infinite: loop {
 LL | |
@@ -272,7 +272,7 @@ LL | fn continue_outer() -> ! {
    |                     ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:416:5
+  --> tests/ui/infinite_loops.rs:415:5
    |
 LL | /     loop {
 LL | |
@@ -289,7 +289,7 @@ LL | fn continue_outer() -> ! {
    |                     ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:418:9
+  --> tests/ui/infinite_loops.rs:417:9
    |
 LL | /         'inner: loop {
 LL | |             loop {
@@ -304,7 +304,7 @@ LL | fn continue_outer() -> ! {
    |                     ++++
 
 error: infinite loop detected
-  --> tests/ui/infinite_loops.rs:426:5
+  --> tests/ui/infinite_loops.rs:425:5
    |
 LL | /     loop {
 LL | |
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
index 191f7719904..9138a8bacfe 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
 #![allow(clippy::type_complexity)]
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
index 33a3b90f9cf..ede6fa27778 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
 #![allow(clippy::type_complexity)]
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
index 000d81f811f..8e0d37df96b 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
@@ -1,5 +1,5 @@
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:16:13
+  --> tests/ui/redundant_closure_call_fixable.rs:15:13
    |
 LL |     let a = (|| 42)();
    |             ^^^^^^^^^ help: try doing something like: `42`
@@ -8,7 +8,7 @@ LL |     let a = (|| 42)();
    = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_call)]`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:17:13
+  --> tests/ui/redundant_closure_call_fixable.rs:16:13
    |
 LL |       let b = (async || {
    |  _____________^
@@ -28,7 +28,7 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:22:13
+  --> tests/ui/redundant_closure_call_fixable.rs:21:13
    |
 LL |       let c = (|| {
    |  _____________^
@@ -48,13 +48,13 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:27:13
+  --> tests/ui/redundant_closure_call_fixable.rs:26:13
    |
 LL |     let d = (async || something().await)();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:36:13
+  --> tests/ui/redundant_closure_call_fixable.rs:35:13
    |
 LL |             (|| m!())()
    |             ^^^^^^^^^^^ help: try doing something like: `m!()`
@@ -65,7 +65,7 @@ LL |     m2!();
    = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:31:13
+  --> tests/ui/redundant_closure_call_fixable.rs:30:13
    |
 LL |             (|| 0)()
    |             ^^^^^^^^ help: try doing something like: `0`
@@ -76,67 +76,67 @@ LL |     m2!();
    = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:44:16
+  --> tests/ui/redundant_closure_call_fixable.rs:43:16
    |
 LL |     assert_eq!((|| || 43)()(), 42);
    |                ^^^^^^^^^^^^^^ help: try doing something like: `43`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:53:10
+  --> tests/ui/redundant_closure_call_fixable.rs:52:10
    |
 LL |     dbg!((|| 42)());
    |          ^^^^^^^^^ help: try doing something like: `42`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:56:13
+  --> tests/ui/redundant_closure_call_fixable.rs:55:13
    |
 LL |     let a = (|| || || 123)();
    |             ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:60:13
+  --> tests/ui/redundant_closure_call_fixable.rs:59:13
    |
 LL |     let a = (|| || || || async || 1)()()()()();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:69:13
+  --> tests/ui/redundant_closure_call_fixable.rs:68:13
    |
 LL |     let a = (|| echo!(|| echo!(|| 1)))()()();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:71:13
+  --> tests/ui/redundant_closure_call_fixable.rs:70:13
    |
 LL |     let a = (|| echo!((|| 123)))()();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:84:11
+  --> tests/ui/redundant_closure_call_fixable.rs:83:11
    |
 LL |     bar()((|| || 42)()(), 5);
    |           ^^^^^^^^^^^^^^ help: try doing something like: `42`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:85:9
+  --> tests/ui/redundant_closure_call_fixable.rs:84:9
    |
 LL |     foo((|| || 42)()(), 5);
    |         ^^^^^^^^^^^^^^ help: try doing something like: `42`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:89:5
+  --> tests/ui/redundant_closure_call_fixable.rs:88:5
    |
 LL |     (|| async {})().await;
    |     ^^^^^^^^^^^^^^^ help: try doing something like: `async {}`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:98:18
+  --> tests/ui/redundant_closure_call_fixable.rs:97:18
    |
 LL |         spawn_on((|| async move {})());
    |                  ^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async move {}`
 
 error: try not to call a closure in the expression where it is declared
-  --> tests/ui/redundant_closure_call_fixable.rs:103:28
+  --> tests/ui/redundant_closure_call_fixable.rs:102:28
    |
 LL |     std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros();
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32`
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index d21aa240b2d..3e7695106a7 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -1,7 +1,7 @@
 //@aux-build:proc_macros.rs
 #![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
 #![warn(clippy::redundant_locals)]
-#![feature(async_closure, coroutines, stmt_expr_attributes)]
+#![feature(coroutines, stmt_expr_attributes)]
 
 extern crate proc_macros;
 use proc_macros::{external, with_span};
diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs
index 3ace6c5b6d7..92c80c27de0 100644
--- a/src/tools/compiletest/src/compute_diff.rs
+++ b/src/tools/compiletest/src/compute_diff.rs
@@ -144,7 +144,7 @@ where
     }
 
     if !wrote_data {
-        eprintln!("note: diff is identical to nightly rustdoc");
+        println!("note: diff is identical to nightly rustdoc");
         assert!(diff_output.metadata().unwrap().len() == 0);
         return false;
     } else if verbose {
diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs
index e75c8a5993e..b605bc813f1 100644
--- a/src/tools/compiletest/src/debuggers.rs
+++ b/src/tools/compiletest/src/debuggers.rs
@@ -20,7 +20,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.remote_test_client.is_some() && !config.target.contains("android") {
-        eprintln!(
+        println!(
             "WARNING: debuginfo tests are not available when \
              testing with remote"
         );
@@ -28,7 +28,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.target.contains("android") {
-        eprintln!(
+        println!(
             "{} debug-info test uses tcp 5039 port.\
              please reserve it",
             config.target
@@ -50,7 +50,7 @@ pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
     config.lldb_python_dir.as_ref()?;
 
     if let Some(350) = config.lldb_version {
-        eprintln!(
+        println!(
             "WARNING: The used version of LLDB (350) has a \
              known issue that breaks debuginfo tests. See \
              issue #32520 for more information. Skipping all \
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 9acb7d393b4..a5a166af33b 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -188,8 +188,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
     let (argv0, args_) = args.split_first().unwrap();
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
-        eprintln!("{}", opts.usage(&message));
-        eprintln!();
+        println!("{}", opts.usage(&message));
+        println!();
         panic!()
     }
 
@@ -200,8 +200,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
-        eprintln!("{}", opts.usage(&message));
-        eprintln!();
+        println!("{}", opts.usage(&message));
+        println!();
         panic!()
     }
 
@@ -508,7 +508,7 @@ pub fn run_tests(config: Arc<Config>) {
             // easy to miss which tests failed, and as such fail to reproduce
             // the failure locally.
 
-            eprintln!(
+            println!(
                 "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
                 config.suite,
                 config
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index ca746ed8c55..7b11bf3b121 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -131,7 +131,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
 
     if config.verbose {
         // We're going to be dumping a lot of info. Start on a new line.
-        eprintln!("\n");
+        print!("\n\n");
     }
     debug!("running {:?}", testpaths.file.display());
     let mut props = TestProps::from_file(&testpaths.file, revision, &config);
@@ -353,7 +353,7 @@ impl<'test> TestCx<'test> {
                 {
                     self.error(&format!("{} test did not emit an error", self.config.mode));
                     if self.config.mode == crate::common::Mode::Ui {
-                        eprintln!("note: by default, ui tests are expected not to compile");
+                        println!("note: by default, ui tests are expected not to compile");
                     }
                     proc_res.fatal(None, || ());
                 };
@@ -774,20 +774,20 @@ impl<'test> TestCx<'test> {
                 unexpected.len(),
                 not_found.len()
             ));
-            eprintln!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
+            println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
             if !unexpected.is_empty() {
-                eprintln!("{}", "--- unexpected errors (from JSON output) ---".green());
+                println!("{}", "--- unexpected errors (from JSON output) ---".green());
                 for error in &unexpected {
-                    eprintln!("{}", error.render_for_expected());
+                    println!("{}", error.render_for_expected());
                 }
-                eprintln!("{}", "---".green());
+                println!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                eprintln!("{}", "--- not found errors (from test file) ---".red());
+                println!("{}", "--- not found errors (from test file) ---".red());
                 for error in &not_found {
-                    eprintln!("{}", error.render_for_expected());
+                    println!("{}", error.render_for_expected());
                 }
-                eprintln!("{}", "---\n".red());
+                println!("{}", "---\n".red());
             }
             panic!("errors differ from expected");
         }
@@ -1876,18 +1876,18 @@ impl<'test> TestCx<'test> {
 
     fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
         if self.config.verbose {
-            eprintln!("------stdout------------------------------");
-            eprintln!("{}", out);
-            eprintln!("------stderr------------------------------");
-            eprintln!("{}", err);
-            eprintln!("------------------------------------------");
+            println!("------stdout------------------------------");
+            println!("{}", out);
+            println!("------stderr------------------------------");
+            println!("{}", err);
+            println!("------------------------------------------");
         }
     }
 
     fn error(&self, err: &str) {
         match self.revision {
-            Some(rev) => eprintln!("\nerror in revision `{}`: {}", rev, err),
-            None => eprintln!("\nerror: {}", err),
+            Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
+            None => println!("\nerror: {}", err),
         }
     }
 
@@ -1972,7 +1972,7 @@ impl<'test> TestCx<'test> {
         if !self.config.has_html_tidy {
             return;
         }
-        eprintln!("info: generating a diff against nightly rustdoc");
+        println!("info: generating a diff against nightly rustdoc");
 
         let suffix =
             self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
@@ -2082,7 +2082,7 @@ impl<'test> TestCx<'test> {
                 .output()
                 .unwrap();
             assert!(output.status.success());
-            eprintln!("{}", String::from_utf8_lossy(&output.stdout));
+            println!("{}", String::from_utf8_lossy(&output.stdout));
             eprintln!("{}", String::from_utf8_lossy(&output.stderr));
         } else {
             use colored::Colorize;
@@ -2496,7 +2496,7 @@ impl<'test> TestCx<'test> {
                 )"#
             )
             .replace_all(&output, |caps: &Captures<'_>| {
-                eprintln!("{}", &caps[0]);
+                println!("{}", &caps[0]);
                 caps[0].replace(r"\", "/")
             })
             .replace("\r\n", "\n")
@@ -2601,14 +2601,14 @@ impl<'test> TestCx<'test> {
         if let Err(err) = fs::write(&actual_path, &actual) {
             self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",));
         }
-        eprintln!("Saved the actual {stream} to {actual_path:?}");
+        println!("Saved the actual {stream} to {actual_path:?}");
 
         let expected_path =
             expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
 
         if !self.config.bless {
             if expected.is_empty() {
-                eprintln!("normalized {}:\n{}\n", stream, actual);
+                println!("normalized {}:\n{}\n", stream, actual);
             } else {
                 self.show_diff(
                     stream,
@@ -2631,10 +2631,10 @@ impl<'test> TestCx<'test> {
             if let Err(err) = fs::write(&expected_path, &actual) {
                 self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
             }
-            eprintln!("Blessing the {stream} of {test_name} in {expected_path:?}");
+            println!("Blessing the {stream} of {test_name} in {expected_path:?}");
         }
 
-        eprintln!("\nThe actual {0} differed from the expected {0}.", stream);
+        println!("\nThe actual {0} differed from the expected {0}.", stream);
 
         if self.config.bless { 0 } else { 1 }
     }
@@ -2783,7 +2783,7 @@ impl<'test> TestCx<'test> {
         fs::create_dir_all(&incremental_dir).unwrap();
 
         if self.config.verbose {
-            eprintln!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
         }
     }
 
@@ -2841,7 +2841,7 @@ impl ProcRes {
             }
         }
 
-        eprintln!(
+        println!(
             "status: {}\ncommand: {}\n{}\n{}\n",
             self.status,
             self.cmdline,
@@ -2852,7 +2852,7 @@ impl ProcRes {
 
     pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
         if let Some(e) = err {
-            eprintln!("\nerror: {}", e);
+            println!("\nerror: {}", e);
         }
         self.print_info();
         on_failure();
diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs
index 6acd140183d..6c866cbef21 100644
--- a/src/tools/compiletest/src/runtest/codegen_units.rs
+++ b/src/tools/compiletest/src/runtest/codegen_units.rs
@@ -64,13 +64,13 @@ impl TestCx<'_> {
         if !missing.is_empty() {
             missing.sort();
 
-            eprintln!("\nThese items should have been contained but were not:\n");
+            println!("\nThese items should have been contained but were not:\n");
 
             for item in &missing {
-                eprintln!("{}", item);
+                println!("{}", item);
             }
 
-            eprintln!("\n");
+            println!("\n");
         }
 
         if !unexpected.is_empty() {
@@ -80,24 +80,24 @@ impl TestCx<'_> {
                 sorted
             };
 
-            eprintln!("\nThese items were contained but should not have been:\n");
+            println!("\nThese items were contained but should not have been:\n");
 
             for item in sorted {
-                eprintln!("{}", item);
+                println!("{}", item);
             }
 
-            eprintln!("\n");
+            println!("\n");
         }
 
         if !wrong_cgus.is_empty() {
             wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
-            eprintln!("\nThe following items were assigned to wrong codegen units:\n");
+            println!("\nThe following items were assigned to wrong codegen units:\n");
 
             for &(ref expected_item, ref actual_item) in &wrong_cgus {
-                eprintln!("{}", expected_item.name);
-                eprintln!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
-                eprintln!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
-                eprintln!();
+                println!("{}", expected_item.name);
+                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
+                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
+                println!();
             }
         }
 
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index 7322e730e53..c621c22ac99 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -260,7 +260,7 @@ impl TestCx<'_> {
                 cmdline,
             };
             if adb.kill().is_err() {
-                eprintln!("Adb process is already finished.");
+                println!("Adb process is already finished.");
             }
         } else {
             let rust_src_root =
@@ -275,7 +275,7 @@ impl TestCx<'_> {
 
             match self.config.gdb_version {
                 Some(version) => {
-                    eprintln!("NOTE: compiletest thinks it is using GDB version {}", version);
+                    println!("NOTE: compiletest thinks it is using GDB version {}", version);
 
                     if version > extract_gdb_version("7.4").unwrap() {
                         // Add the directory containing the pretty printers to
@@ -297,7 +297,7 @@ impl TestCx<'_> {
                     }
                 }
                 _ => {
-                    eprintln!(
+                    println!(
                         "NOTE: compiletest does not know which version of \
                          GDB it is using"
                     );
@@ -392,10 +392,10 @@ impl TestCx<'_> {
 
         match self.config.lldb_version {
             Some(ref version) => {
-                eprintln!("NOTE: compiletest thinks it is using LLDB version {}", version);
+                println!("NOTE: compiletest thinks it is using LLDB version {}", version);
             }
             _ => {
-                eprintln!(
+                println!(
                     "NOTE: compiletest does not know which version of \
                      LLDB it is using"
                 );
diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs
index 4f26786129b..591aff0defe 100644
--- a/src/tools/compiletest/src/runtest/incremental.rs
+++ b/src/tools/compiletest/src/runtest/incremental.rs
@@ -30,7 +30,7 @@ impl TestCx<'_> {
         assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
 
         if self.config.verbose {
-            eprint!("revision={:?} props={:#?}", revision, self.props);
+            print!("revision={:?} props={:#?}", revision, self.props);
         }
 
         if revision.starts_with("cpass") {
diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs
index 64a2addaa28..d1ec0035744 100644
--- a/src/tools/compiletest/src/runtest/mir_opt.rs
+++ b/src/tools/compiletest/src/runtest/mir_opt.rs
@@ -89,7 +89,7 @@ impl TestCx<'_> {
                 }
                 let expected_string = fs::read_to_string(&expected_file).unwrap();
                 if dumped_string != expected_string {
-                    eprint!("{}", write_diff(&expected_string, &dumped_string, 3));
+                    print!("{}", write_diff(&expected_string, &dumped_string, 3));
                     panic!(
                         "Actual MIR output differs from expected MIR output {}",
                         expected_file.display()
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
index 84376d346af..31fdb0a5d13 100644
--- a/src/tools/compiletest/src/runtest/rustdoc_json.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -29,7 +29,7 @@ impl TestCx<'_> {
 
         if !res.status.success() {
             self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
-                eprintln!("Rustdoc Output:");
+                println!("Rustdoc Output:");
                 proc_res.print_info();
             })
         }
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index bc860bf18c7..172b1e32aad 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -109,10 +109,10 @@ impl TestCx<'_> {
         }
 
         if errors > 0 {
-            eprintln!("To update references, rerun the tests and pass the `--bless` flag");
+            println!("To update references, rerun the tests and pass the `--bless` flag");
             let relative_path_to_file =
                 self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
-            eprintln!(
+            println!(
                 "To only update this specific test, also pass `--test-args {}`",
                 relative_path_to_file.display(),
             );
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 7b50e62c29b..bff02f1db9f 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -30,7 +30,7 @@ fn path_div() -> &'static str {
 pub fn logv(config: &Config, s: String) {
     debug!("{}", s);
     if config.verbose {
-        eprintln!("{}", s);
+        println!("{}", s);
     }
 }
 
diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs
index 979a6d1cbe0..ed6b7b205b5 100644
--- a/src/tools/miri/tests/pass/async-closure-captures.rs
+++ b/src/tools/miri/tests/pass/async-closure-captures.rs
@@ -1,6 +1,6 @@
 // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync
 
-#![feature(async_closure, async_trait_bounds)]
+#![feature(async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs
index ad9822fa46d..105aa434b0a 100644
--- a/src/tools/miri/tests/pass/async-closure-drop.rs
+++ b/src/tools/miri/tests/pass/async-closure-drop.rs
@@ -1,4 +1,4 @@
-#![feature(async_closure, async_trait_bounds)]
+#![feature(async_fn_traits, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs
index 979b83687e4..4c0fb356f9d 100644
--- a/src/tools/miri/tests/pass/async-closure.rs
+++ b/src/tools/miri/tests/pass/async-closure.rs
@@ -1,4 +1,4 @@
-#![feature(async_closure, async_fn_traits)]
+#![feature(async_fn_traits)]
 #![allow(unused)]
 
 use std::future::Future;
diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs
index a455f377e85..6d556b77795 100644
--- a/src/tools/miri/tests/pass/async-drop.rs
+++ b/src/tools/miri/tests/pass/async-drop.rs
@@ -6,7 +6,7 @@
 // please consider modifying rustc's async drop test at
 // `tests/ui/async-await/async-drop.rs`.
 
-#![feature(async_drop, impl_trait_in_assoc_type, async_closure)]
+#![feature(async_drop, impl_trait_in_assoc_type)]
 #![allow(incomplete_features, dead_code)]
 
 // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 2bd4d17fe22..8c1d82de1da 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -85,6 +85,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -509,6 +515,7 @@ dependencies = [
  "base-db",
  "cfg",
  "either",
+ "expect-test",
  "hir-def",
  "hir-expand",
  "hir-ty",
@@ -519,6 +526,9 @@ dependencies = [
  "span",
  "stdx",
  "syntax",
+ "syntax-bridge",
+ "test-fixture",
+ "test-utils",
  "tracing",
  "triomphe",
  "tt",
@@ -1492,9 +1502,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613760a3071b25a67a8d7bc97b37c7fd4722562e9479137b83ae9cf8f8c1601a"
+checksum = "af462c3a2d524b84a51b6848b439787f01b35c6c1086d3e3086a5f5eea92ed9a"
 dependencies = [
  "bitflags 2.6.0",
  "ra-ap-rustc_index",
@@ -1503,20 +1513,19 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b2bc6b4ecede8ff28295041e22c2e66853f8e0125990c05135bad3c30bad12c"
+checksum = "be6bb8cb0ab78d94a222f1ffd3e87254cdfb57413382b8d6ebe26a85482f99d1"
 dependencies = [
- "arrayvec",
  "ra-ap-rustc_index_macros",
  "smallvec",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2374a39fb2d92d0509178c2b442eadca3cc10e403ef9729a040c1855b08ff261"
+checksum = "c24b1641455b46e87435b7321219672077066e678963d239a4a2904732979b16"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1525,9 +1534,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a2cf8e48b69af3ecc29ed3449892e8a999111d2f75212a78aa242e117cf1711"
+checksum = "94daa86974417981fed2f12bd8fb00158dfa6fee561152bed689278c846d0272"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1535,9 +1544,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d6f59a22b559263c5c42747ae362cf5d4fb272293fa119a4623f8ec288f9656"
+checksum = "fc07f6bd581746f358e39c4b6bfe8d455b3d6ad1a857821016d0d42eeb5e1e3e"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1545,9 +1554,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.80.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7d0575b54ffe09bc5d2f158454bc05f0c30c01d9992310965f854be50ae22b8"
+checksum = "2f49b86e1276c1c3c72898410def29b699415f4e7d1dfb3531daf79794694372"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.0.0",
@@ -1645,6 +1654,7 @@ version = "0.0.0"
 dependencies = [
  "always-assert",
  "anyhow",
+ "base64",
  "cargo_metadata",
  "cfg",
  "crossbeam-channel",
@@ -1655,6 +1665,7 @@ dependencies = [
  "hir-def",
  "hir-ty",
  "ide",
+ "ide-completion",
  "ide-db",
  "ide-ssr",
  "intern",
@@ -1683,6 +1694,7 @@ dependencies = [
  "stdx",
  "syntax",
  "syntax-bridge",
+ "tenthash",
  "test-fixture",
  "test-utils",
  "tikv-jemallocator",
@@ -1987,6 +1999,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "tenthash"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d67f9f3cf70e0852941d7bc3cb884b49b24b8ee956baf91ad0abae31f5ef11fb"
+
+[[package]]
 name = "test-fixture"
 version = "0.0.0"
 dependencies = [
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 632b290ba98..f7074f91354 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.80", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.80", default-features = false }
-ra-ap-rustc_index = { version = "0.80", default-features = false }
-ra-ap-rustc_abi = { version = "0.80", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.80", default-features = false }
+ra-ap-rustc_lexer = { version = "0.85", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.85", default-features = false }
+ra-ap-rustc_index = { version = "0.85", default-features = false }
+ra-ap-rustc_abi = { version = "0.85", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.85", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 57522d69321..e86944eeb35 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -547,29 +547,6 @@ impl CrateGraph {
         None
     }
 
-    // Work around for https://github.com/rust-lang/rust-analyzer/issues/6038.
-    // As hacky as it gets.
-    pub fn patch_cfg_if(&mut self) -> bool {
-        // we stupidly max by version in an attempt to have all duplicated std's depend on the same cfg_if so that deduplication still works
-        let cfg_if =
-            self.hacky_find_crate("cfg_if").max_by_key(|&it| self.arena[it].version.clone());
-        let std = self.hacky_find_crate("std").next();
-        match (cfg_if, std) {
-            (Some(cfg_if), Some(std)) => {
-                self.arena[cfg_if].dependencies.clear();
-                self.arena[std]
-                    .dependencies
-                    .push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
-                true
-            }
-            _ => false,
-        }
-    }
-
-    fn hacky_find_crate<'a>(&'a self, display_name: &'a str) -> impl Iterator<Item = CrateId> + 'a {
-        self.iter().filter(move |it| self[*it].display_name.as_deref() == Some(display_name))
-    }
-
     /// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies.
     /// Returns a mapping from old crate ids to new crate ids.
     pub fn remove_crates_except(&mut self, to_keep: &[CrateId]) -> Vec<Option<CrateId>> {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 5a386f6cf8d..867bee95bed 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -31,7 +31,7 @@ use crate::{
     path::{ModPath, Path},
     src::HasSource,
     type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
-    BlockId, DefWithBodyId, HasModule, Lookup,
+    BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
 };
 
 /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
@@ -141,7 +141,7 @@ pub struct BodySourceMap {
     field_map_back: FxHashMap<ExprId, FieldSource>,
     pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
 
-    types: TypesSourceMap,
+    pub types: TypesSourceMap,
 
     // FIXME: Make this a sane struct.
     template_map: Option<
@@ -160,9 +160,6 @@ pub struct BodySourceMap {
     diagnostics: Vec<BodyDiagnostic>,
 }
 
-#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
-pub struct SyntheticSyntax;
-
 #[derive(Debug, Eq, PartialEq)]
 pub enum BodyDiagnostic {
     InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
@@ -408,7 +405,8 @@ impl Body {
                     f(else_branch);
                 }
             }
-            Expr::Let { expr, .. } => {
+            Expr::Let { expr, pat } => {
+                self.walk_exprs_in_pat(*pat, &mut f);
                 f(*expr);
             }
             Expr::Block { statements, tail, .. }
@@ -444,7 +442,10 @@ impl Body {
             }
             Expr::Match { expr, arms } => {
                 f(*expr);
-                arms.iter().map(|arm| arm.expr).for_each(f);
+                arms.iter().for_each(|arm| {
+                    f(arm.expr);
+                    self.walk_exprs_in_pat(arm.pat, &mut f);
+                });
             }
             Expr::Break { expr, .. }
             | Expr::Return { expr }
@@ -505,6 +506,131 @@ impl Body {
         }
     }
 
+    pub fn walk_child_exprs_without_pats(&self, expr_id: ExprId, mut f: impl FnMut(ExprId)) {
+        let expr = &self[expr_id];
+        match expr {
+            Expr::Continue { .. }
+            | Expr::Const(_)
+            | Expr::Missing
+            | Expr::Path(_)
+            | Expr::OffsetOf(_)
+            | Expr::Literal(_)
+            | Expr::Underscore => {}
+            Expr::InlineAsm(it) => it.operands.iter().for_each(|(_, op)| match op {
+                AsmOperand::In { expr, .. }
+                | AsmOperand::Out { expr: Some(expr), .. }
+                | AsmOperand::InOut { expr, .. } => f(*expr),
+                AsmOperand::SplitInOut { in_expr, out_expr, .. } => {
+                    f(*in_expr);
+                    if let Some(out_expr) = out_expr {
+                        f(*out_expr);
+                    }
+                }
+                AsmOperand::Out { expr: None, .. }
+                | AsmOperand::Const(_)
+                | AsmOperand::Label(_)
+                | AsmOperand::Sym(_) => (),
+            }),
+            Expr::If { condition, then_branch, else_branch } => {
+                f(*condition);
+                f(*then_branch);
+                if let &Some(else_branch) = else_branch {
+                    f(else_branch);
+                }
+            }
+            Expr::Let { expr, .. } => {
+                f(*expr);
+            }
+            Expr::Block { statements, tail, .. }
+            | Expr::Unsafe { statements, tail, .. }
+            | Expr::Async { statements, tail, .. } => {
+                for stmt in statements.iter() {
+                    match stmt {
+                        Statement::Let { initializer, else_branch, .. } => {
+                            if let &Some(expr) = initializer {
+                                f(expr);
+                            }
+                            if let &Some(expr) = else_branch {
+                                f(expr);
+                            }
+                        }
+                        Statement::Expr { expr: expression, .. } => f(*expression),
+                        Statement::Item(_) => (),
+                    }
+                }
+                if let &Some(expr) = tail {
+                    f(expr);
+                }
+            }
+            Expr::Loop { body, .. } => f(*body),
+            Expr::Call { callee, args, .. } => {
+                f(*callee);
+                args.iter().copied().for_each(f);
+            }
+            Expr::MethodCall { receiver, args, .. } => {
+                f(*receiver);
+                args.iter().copied().for_each(f);
+            }
+            Expr::Match { expr, arms } => {
+                f(*expr);
+                arms.iter().map(|arm| arm.expr).for_each(f);
+            }
+            Expr::Break { expr, .. }
+            | Expr::Return { expr }
+            | Expr::Yield { expr }
+            | Expr::Yeet { expr } => {
+                if let &Some(expr) = expr {
+                    f(expr);
+                }
+            }
+            Expr::Become { expr } => f(*expr),
+            Expr::RecordLit { fields, spread, .. } => {
+                for field in fields.iter() {
+                    f(field.expr);
+                }
+                if let &Some(expr) = spread {
+                    f(expr);
+                }
+            }
+            Expr::Closure { body, .. } => {
+                f(*body);
+            }
+            Expr::BinaryOp { lhs, rhs, .. } => {
+                f(*lhs);
+                f(*rhs);
+            }
+            Expr::Range { lhs, rhs, .. } => {
+                if let &Some(lhs) = rhs {
+                    f(lhs);
+                }
+                if let &Some(rhs) = lhs {
+                    f(rhs);
+                }
+            }
+            Expr::Index { base, index, .. } => {
+                f(*base);
+                f(*index);
+            }
+            Expr::Field { expr, .. }
+            | Expr::Await { expr }
+            | Expr::Cast { expr, .. }
+            | Expr::Ref { expr, .. }
+            | Expr::UnaryOp { expr, .. }
+            | Expr::Box { expr } => {
+                f(*expr);
+            }
+            Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
+            Expr::Array(a) => match a {
+                Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
+                Array::Repeat { initializer, repeat } => {
+                    f(*initializer);
+                    f(*repeat)
+                }
+            },
+            &Expr::Assignment { target: _, value } => f(value),
+        }
+    }
+
     pub fn walk_exprs_in_pat(&self, pat_id: PatId, f: &mut impl FnMut(ExprId)) {
         self.walk_pats(pat_id, &mut |pat| {
             if let Pat::Expr(expr) | Pat::ConstBlock(expr) = self[pat] {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 1ab49e91569..3b73d409634 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -1510,20 +1510,20 @@ impl ExprCollector<'_> {
                         BuiltinShadowMode::Other,
                         None,
                     );
+                    // Funnily enough, record structs/variants *can* be shadowed
+                    // by pattern bindings (but unit or tuple structs/variants
+                    // can't).
                     match resolved.take_values() {
                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
-                        Some(ModuleDefId::EnumVariantId(_)) => {
-                            // this is only really valid for unit variants, but
-                            // shadowing other enum variants with a pattern is
-                            // an error anyway
+                        Some(ModuleDefId::EnumVariantId(variant))
+                            if self.db.variant_data(variant.into()).kind()
+                                != StructKind::Record =>
+                        {
                             (None, Pat::Path(name.into()))
                         }
                         Some(ModuleDefId::AdtId(AdtId::StructId(s)))
                             if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
                         {
-                            // Funnily enough, record structs *can* be shadowed
-                            // by pattern bindings (but unit or tuple structs
-                            // can't).
                             (None, Pat::Path(name.into()))
                         }
                         // shadowing statics is an error as well, so we just ignore that case here
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
index 3b29d98d198..8f010915845 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
@@ -1,6 +1,5 @@
 mod block;
 
-use base_db::SourceDatabase;
 use expect_test::{expect, Expect};
 use test_fixture::WithFixture;
 
@@ -11,7 +10,7 @@ use super::*;
 fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
     let db = TestDB::with_files(ra_fixture);
 
-    let krate = db.crate_graph().iter().next().unwrap();
+    let krate = db.fetch_test_crate();
     let def_map = db.crate_def_map(krate);
     let mut fn_def = None;
     'outer: for (_, module) in def_map.modules() {
@@ -404,3 +403,26 @@ fn foo() {
         }"#]]
     .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
 }
+
+#[test]
+fn shadowing_record_variant() {
+    let (_, body, _) = lower(
+        r#"
+enum A {
+    B { field: i32 },
+}
+fn f() {
+    use A::*;
+    match () {
+        B => {}
+    };
+}
+    "#,
+    );
+    assert_eq!(body.bindings.len(), 1, "should have a binding for `B`");
+    assert_eq!(
+        body.bindings[BindingId::from_raw(RawIdx::from_u32(0))].name.as_str(),
+        "B",
+        "should have a binding for `B`",
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 2a13f74aac7..15dd6aba311 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -369,7 +369,7 @@ impl ImplData {
 
         let item_tree = tree_id.item_tree(db);
         let impl_def = &item_tree[tree_id.value];
-        let target_trait = impl_def.target_trait.clone();
+        let target_trait = impl_def.target_trait;
         let self_ty = impl_def.self_ty;
         let is_negative = impl_def.is_negative;
         let is_unsafe = impl_def.is_unsafe;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index 11e9bb0d886..7b3f1d06d21 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -26,8 +26,8 @@ use crate::{
     nameres::{DefMap, MacroSubNs},
     path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
     type_ref::{
-        ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
-        TypesSourceMap,
+        ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
+        TypesMap, TypesSourceMap,
     },
     AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
     LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
@@ -225,6 +225,11 @@ impl GenericParams {
     }
 
     #[inline]
+    pub fn no_predicates(&self) -> bool {
+        self.where_predicates.is_empty()
+    }
+
+    #[inline]
     pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
         self.where_predicates.iter()
     }
@@ -874,14 +879,20 @@ fn copy_type_bound(
     to: &mut TypesMap,
     to_source_map: &mut TypesSourceMap,
 ) -> TypeBound {
+    let mut copy_path_id = |path: PathId| {
+        let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
+        let new_path_id = to.types.alloc(TypeRef::Path(new_path));
+        if let Some(&ptr) = from_source_map.types_map_back.get(path.type_ref()) {
+            to_source_map.types_map_back.insert(new_path_id, ptr);
+        }
+        PathId::from_type_ref_unchecked(new_path_id)
+    };
+
     match bound {
-        TypeBound::Path(path, modifier) => {
-            TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
+        &TypeBound::Path(path, modifier) => TypeBound::Path(copy_path_id(path), modifier),
+        TypeBound::ForLifetime(lifetimes, path) => {
+            TypeBound::ForLifetime(lifetimes.clone(), copy_path_id(*path))
         }
-        TypeBound::ForLifetime(lifetimes, path) => TypeBound::ForLifetime(
-            lifetimes.clone(),
-            copy_path(path, from, from_source_map, to, to_source_map),
-        ),
         TypeBound::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
         TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
         TypeBound::Error => TypeBound::Error,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 4d83ef99c84..6d4d519cd2b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -23,6 +23,7 @@ use crate::{
     hir::Literal,
     lower::LowerCtx,
     path::{GenericArg, Path},
+    SyntheticSyntax,
 };
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -91,19 +92,37 @@ impl Rawness {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
+/// impl's trait, that are always paths but need to be traced back to source code.
+pub struct PathId(TypeRefId);
+
+impl PathId {
+    #[inline]
+    pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
+        Self(type_ref)
+    }
+
+    #[inline]
+    pub fn type_ref(self) -> TypeRefId {
+        self.0
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct TraitRef {
-    pub path: Path,
+    pub path: PathId,
 }
 
 impl TraitRef {
     /// Converts an `ast::PathType` to a `hir::TraitRef`.
     pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
         // FIXME: Use `Path::from_src`
-        match node {
-            ast::Type::PathType(path) => {
-                path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
-            }
+        match &node {
+            ast::Type::PathType(path) => path
+                .path()
+                .and_then(|it| ctx.lower_path(it))
+                .map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
             _ => None,
         }
     }
@@ -173,11 +192,24 @@ impl TypesMap {
 impl Index<TypeRefId> for TypesMap {
     type Output = TypeRef;
 
+    #[inline]
     fn index(&self, index: TypeRefId) -> &Self::Output {
         &self.types[index]
     }
 }
 
+impl Index<PathId> for TypesMap {
+    type Output = Path;
+
+    #[inline]
+    fn index(&self, index: PathId) -> &Self::Output {
+        let TypeRef::Path(path) = &self[index.type_ref()] else {
+            unreachable!("`PathId` always points to `TypeRef::Path`");
+        };
+        path
+    }
+}
+
 pub type TypePtr = AstPtr<ast::Type>;
 pub type TypeSource = InFile<TypePtr>;
 
@@ -187,6 +219,12 @@ pub struct TypesSourceMap {
 }
 
 impl TypesSourceMap {
+    pub const EMPTY: Self = Self { types_map_back: ArenaMap::new() };
+
+    pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
+        self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
+    }
+
     pub(crate) fn shrink_to_fit(&mut self) {
         let TypesSourceMap { types_map_back } = self;
         types_map_back.shrink_to_fit();
@@ -214,15 +252,15 @@ impl LifetimeRef {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum TypeBound {
-    Path(Path, TraitBoundModifier),
-    ForLifetime(Box<[Name]>, Path),
+    Path(PathId, TraitBoundModifier),
+    ForLifetime(Box<[Name]>, PathId),
     Lifetime(LifetimeRef),
     Use(Box<[UseArgRef]>),
     Error,
 }
 
 #[cfg(target_pointer_width = "64")]
-const _: [(); 32] = [(); ::std::mem::size_of::<TypeBound>()];
+const _: [(); 24] = [(); ::std::mem::size_of::<TypeBound>()];
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum UseArgRef {
@@ -365,8 +403,8 @@ impl TypeRef {
                 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
                     for bound in bounds {
                         match bound {
-                            TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
-                                go_path(path, f, map)
+                            &TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
+                                go_path(&map[path], f, map)
                             }
                             TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
                         }
@@ -397,8 +435,8 @@ impl TypeRef {
                         }
                         for bound in binding.bounds.iter() {
                             match bound {
-                                TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
-                                    go_path(path, f, map)
+                                &TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
+                                    go_path(&map[path], f, map)
                                 }
                                 TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
                             }
@@ -425,7 +463,7 @@ pub(crate) fn type_bounds_from_ast(
 
 impl TypeBound {
     pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
-        let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
+        let mut lower_path_type = |path_type: &ast::PathType| ctx.lower_path(path_type.path()?);
 
         match node.kind() {
             ast::TypeBoundKind::PathType(path_type) => {
@@ -433,8 +471,10 @@ impl TypeBound {
                     Some(_) => TraitBoundModifier::Maybe,
                     None => TraitBoundModifier::None,
                 };
-                lower_path_type(path_type)
-                    .map(|p| TypeBound::Path(p, m))
+                lower_path_type(&path_type)
+                    .map(|p| {
+                        TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
+                    })
                     .unwrap_or(TypeBound::Error)
             }
             ast::TypeBoundKind::ForType(for_type) => {
@@ -445,12 +485,14 @@ impl TypeBound {
                         .collect(),
                     None => Box::default(),
                 };
-                let path = for_type.ty().and_then(|ty| match ty {
-                    ast::Type::PathType(path_type) => lower_path_type(path_type),
+                let path = for_type.ty().and_then(|ty| match &ty {
+                    ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
                     _ => None,
                 });
                 match path {
-                    Some(p) => TypeBound::ForLifetime(lt_refs, p),
+                    Some((p, ty)) => {
+                        TypeBound::ForLifetime(lt_refs, ctx.alloc_path(p, AstPtr::new(&ty)))
+                    }
                     None => TypeBound::Error,
                 }
             }
@@ -470,10 +512,10 @@ impl TypeBound {
         }
     }
 
-    pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
+    pub fn as_path<'a>(&self, map: &'a TypesMap) -> Option<(&'a Path, TraitBoundModifier)> {
         match self {
-            TypeBound::Path(p, m) => Some((p, m)),
-            TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
+            &TypeBound::Path(p, m) => Some((&map[p], m)),
+            &TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
             TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index d519c1708b3..71848845a84 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -34,7 +34,7 @@ use crate::{
     lower::LowerCtx,
     path::AssociatedTypeBinding,
     type_ref::{
-        LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
+        LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
         TypesMap, TypesSourceMap,
     },
     visibility::RawVisibility,
@@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
         };
 
         let ret_type = if func.async_token().is_some() {
-            let future_impl = desugar_future_path(ret_type);
+            let future_impl = desugar_future_path(&mut body_ctx, ret_type);
             let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
             body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
         } else {
@@ -936,7 +936,7 @@ impl<'a> Ctx<'a> {
     }
 }
 
-fn desugar_future_path(orig: TypeRefId) -> Path {
+fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId {
     let path = path![core::future::Future];
     let mut generic_args: Vec<_> =
         std::iter::repeat(None).take(path.segments().len() - 1).collect();
@@ -948,7 +948,8 @@ fn desugar_future_path(orig: TypeRefId) -> Path {
     };
     generic_args.push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));
 
-    Path::from_known_path(path, generic_args)
+    let path = Path::from_known_path(path, generic_args);
+    PathId::from_type_ref_unchecked(ctx.alloc_type_ref_desugared(TypeRef::Path(path)))
 }
 
 enum HasImplicitSelf {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index b6816a1f968..70bf2f13c88 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -484,7 +484,7 @@ impl Printer<'_> {
                     w!(self, "!");
                 }
                 if let Some(tr) = target_trait {
-                    self.print_path(&tr.path, types_map);
+                    self.print_path(&types_map[tr.path], types_map);
                     w!(self, " for ");
                 }
                 self.print_type_ref(*self_ty, types_map);
@@ -648,9 +648,9 @@ impl Printer<'_> {
                 let (target, bound) = match pred {
                     WherePredicate::TypeBound { target, bound } => (target, bound),
                     WherePredicate::Lifetime { target, bound } => {
-                        wln!(
+                        w!(
                             this,
-                            "{}: {},",
+                            "{}: {}",
                             target.name.display(self.db.upcast(), edition),
                             bound.name.display(self.db.upcast(), edition)
                         );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
index 5c07369f4b5..0f53969d6c7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
@@ -351,7 +351,8 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
             where
                 T: Copy,
                 T: 'a,
-                T: 'b
+                T: 'b,
+                'b: 'a
             {
                 pub(self) field: &'a &'b T,
             }
@@ -370,7 +371,8 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
             where
                 T: Copy,
                 T: 'a,
-                T: 'b
+                T: 'b,
+                'b: 'a
             {
                 // AstId: 9
                 pub(self) fn f<G>(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 166c965d14c..0629d87e544 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -376,6 +376,9 @@ language_item_table! {
     Fn,                      sym::fn_,                 fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
     FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait,          GenericRequirement::Exact(1);
     FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFn,                 sym::async_fn,            async_fn_trait,             Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFnMut,              sym::async_fn_mut,        async_fn_mut_trait,         Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFnOnce,             sym::async_fn_once,       async_fn_once_trait,        Target::Trait,          GenericRequirement::Exact(1);
 
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index eb55ba1d53d..8af27513ebc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
 pub struct UnresolvedMacro {
     pub path: hir_expand::mod_path::ModPath,
 }
+
+#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
+pub struct SyntheticSyntax;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
index 6d1a3d17447..7cddd48eb17 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
@@ -2,7 +2,7 @@
 use std::{cell::OnceCell, mem};
 
 use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
-use span::{AstIdMap, AstIdNode};
+use span::{AstIdMap, AstIdNode, Edition, EditionedFileId, FileId, RealSpanMap};
 use stdx::thin_vec::ThinVec;
 use syntax::ast;
 use triomphe::Arc;
@@ -10,7 +10,7 @@ use triomphe::Arc;
 use crate::{
     db::DefDatabase,
     path::Path,
-    type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
+    type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
 };
 
 pub struct LowerCtx<'a> {
@@ -63,6 +63,30 @@ impl<'a> LowerCtx<'a> {
         }
     }
 
+    /// Prepares a `LowerCtx` for synthetic AST that needs to be lowered. This is intended for IDE things.
+    pub fn for_synthetic_ast(
+        db: &'a dyn DefDatabase,
+        ast_id_map: Arc<AstIdMap>,
+        types_map: &'a mut TypesMap,
+        types_source_map: &'a mut TypesSourceMap,
+    ) -> Self {
+        let file_id = EditionedFileId::new(
+            FileId::from_raw(EditionedFileId::MAX_FILE_ID),
+            Edition::Edition2015,
+        );
+        LowerCtx {
+            db,
+            // Make up an invalid file id, so that if we will try to actually access it salsa will panic.
+            file_id: file_id.into(),
+            span_map: SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(file_id))).into(),
+            ast_id_map: ast_id_map.into(),
+            impl_trait_bounds: Vec::new(),
+            outer_impl_trait: false,
+            types_map,
+            types_source_map,
+        }
+    }
+
     pub(crate) fn span_map(&self) -> &SpanMap {
         self.span_map.get_or_init(|| self.db.span_map(self.file_id))
     }
@@ -118,4 +142,8 @@ impl<'a> LowerCtx<'a> {
     pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
         self.types_map.types.alloc(TypeRef::Error)
     }
+
+    pub(crate) fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
+        PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
index d568f6faa72..511626b5ed9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -1733,7 +1733,7 @@ m!(C("0"));
 macro_rules! m {
     ($k:expr) => { fn f() { K::$k; } }
 }
-/* parse error: expected identifier */
+/* parse error: expected identifier, `self`, `super`, `crate`, or `Self` */
 /* parse error: expected SEMICOLON */
 /* parse error: expected SEMICOLON */
 /* parse error: expected expression, item or let statement */
@@ -1759,8 +1759,9 @@ fn f() {
 //                   NAME_REF@6..7
 //                     IDENT@6..7 "K"
 //               COLON2@7..9 "::"
-//               ERROR@9..10
-//                 L_PAREN@9..10 "("
+//               PATH_SEGMENT@9..10
+//                 ERROR@9..10
+//                   L_PAREN@9..10 "("
 //         EXPR_STMT@10..16
 //           CALL_EXPR@10..16
 //             PATH_EXPR@10..11
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
index 23d8b023b8b..e9a977da913 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
@@ -184,3 +184,31 @@ fn test() {
 "#]],
     );
 }
+
+#[test]
+fn meta_variable_raw_name_equals_non_raw() {
+    check(
+        r#"
+macro_rules! m {
+    ($r#name:tt) => {
+        $name
+    }
+}
+
+fn test() {
+    m!(1234)
+}
+"#,
+        expect![[r#"
+macro_rules! m {
+    ($r#name:tt) => {
+        $name
+    }
+}
+
+fn test() {
+    1234
+}
+"#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index d5b94f0ae44..0475e40c5b2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -16,7 +16,6 @@ mod proc_macros;
 
 use std::{iter, ops::Range, sync};
 
-use base_db::SourceDatabase;
 use expect_test::Expect;
 use hir_expand::{
     db::ExpandDatabase,
@@ -63,7 +62,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
         },
     )];
     let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros);
-    let krate = db.crate_graph().iter().next().unwrap();
+    let krate = db.fetch_test_crate();
     let def_map = db.crate_def_map(krate);
     let local_id = DefMap::ROOT;
     let module = def_map.module_id(local_id);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index a37e3c70e22..98b08bcf708 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -910,8 +910,13 @@ impl DefCollector<'_> {
                             self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
                             // record the glob import in case we add further items
                             let glob = self.glob_imports.entry(m.local_id).or_default();
-                            if !glob.iter().any(|(mid, _, _)| *mid == module_id) {
-                                glob.push((module_id, vis, id));
+                            match glob.iter_mut().find(|(mid, _, _)| *mid == module_id) {
+                                None => glob.push((module_id, vis, id)),
+                                Some((_, old_vis, _)) => {
+                                    if let Some(new_vis) = old_vis.max(vis, &self.def_map) {
+                                        *old_vis = new_vis;
+                                    }
+                                }
                             }
                         }
                     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
index e1e30e5cec9..32c158415ba 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
@@ -13,13 +13,13 @@ use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB};
 
 fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
     let db = TestDB::with_files(ra_fixture);
-    let krate = db.crate_graph().iter().next().unwrap();
+    let krate = db.fetch_test_crate();
     db.crate_def_map(krate)
 }
 
 fn render_crate_def_map(ra_fixture: &str) -> String {
     let db = TestDB::with_files(ra_fixture);
-    let krate = db.crate_graph().iter().next().unwrap();
+    let krate = db.fetch_test_crate();
     db.crate_def_map(krate).dump(&db)
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
index 543ab41cd59..8963a576794 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
@@ -451,3 +451,42 @@ mod glob_target {
         "#]],
     );
 }
+
+#[test]
+fn regression_18580() {
+    check(
+        r#"
+pub mod libs {
+    pub struct Placeholder;
+}
+
+pub mod reexport_2 {
+    use reexport_1::*;
+    pub use reexport_1::*;
+
+    pub mod reexport_1 {
+        pub use crate::libs::*;
+    }
+}
+
+use reexport_2::*;
+"#,
+        expect![[r#"
+            crate
+            Placeholder: t v
+            libs: t
+            reexport_1: t
+            reexport_2: t
+
+            crate::libs
+            Placeholder: t v
+
+            crate::reexport_2
+            Placeholder: t v
+            reexport_1: t
+
+            crate::reexport_2::reexport_1
+            Placeholder: t v
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
index d920c108266..1cfbabca28c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
@@ -1,15 +1,11 @@
-use base_db::{SourceDatabase, SourceDatabaseFileInputExt as _};
+use base_db::SourceDatabaseFileInputExt as _;
 use test_fixture::WithFixture;
 
 use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId};
 
 fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
     let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
-    let krate = {
-        let crate_graph = db.crate_graph();
-        // Some of these tests use minicore/proc-macros which will be injected as the first crate
-        crate_graph.iter().last().unwrap()
-    };
+    let krate = db.fetch_test_crate();
     {
         let events = db.log_executed(|| {
             db.crate_def_map(krate);
@@ -120,28 +116,31 @@ fn f() { foo }
     );
 }
 
-#[test]
-fn typing_inside_an_attribute_arg_should_not_invalidate_def_map() {
-    check_def_map_is_not_recomputed(
-        r"
-//- proc_macros: identity
-//- /lib.rs
-mod foo;
+// Would be nice if this was the case, but as attribute inputs are stored in the item tree, this is
+// not currently the case.
+// #[test]
+// fn typing_inside_an_attribute_arg_should_not_invalidate_def_map() {
+//     check_def_map_is_not_recomputed(
+//         r"
+// //- proc_macros: identity
+// //- /lib.rs
+// mod foo;
+
+// //- /foo/mod.rs
+// pub mod bar;
+
+// //- /foo/bar.rs
+// $0
+// #[proc_macros::identity]
+// fn f() {}
+// ",
+//         r"
+// #[proc_macros::identity(foo)]
+// fn f() {}
+// ",
+//     );
+// }
 
-//- /foo/mod.rs
-pub mod bar;
-
-//- /foo/bar.rs
-$0
-#[proc_macros::identity]
-fn f() {}
-",
-        r"
-#[proc_macros::identity(foo)]
-fn f() {}
-",
-    );
-}
 #[test]
 fn typing_inside_macro_heavy_file_should_not_invalidate_def_map() {
     check_def_map_is_not_recomputed(
@@ -198,31 +197,33 @@ pub struct S {}
     );
 }
 
-#[test]
-fn typing_inside_a_derive_should_not_invalidate_def_map() {
-    check_def_map_is_not_recomputed(
-        r"
-//- proc_macros: derive_identity
-//- minicore:derive
-//- /lib.rs
-mod foo;
-
-//- /foo/mod.rs
-pub mod bar;
-
-//- /foo/bar.rs
-$0
-#[derive(proc_macros::DeriveIdentity)]
-#[allow()]
-struct S;
-",
-        r"
-#[derive(proc_macros::DeriveIdentity)]
-#[allow(dead_code)]
-struct S;
-",
-    );
-}
+// Would be nice if this was the case, but as attribute inputs are stored in the item tree, this is
+// not currently the case.
+// #[test]
+// fn typing_inside_a_derive_should_not_invalidate_def_map() {
+//     check_def_map_is_not_recomputed(
+//         r"
+// //- proc_macros: derive_identity
+// //- minicore:derive
+// //- /lib.rs
+// mod foo;
+
+// //- /foo/mod.rs
+// pub mod bar;
+
+// //- /foo/bar.rs
+// $0
+// #[derive(proc_macros::DeriveIdentity)]
+// #[allow()]
+// struct S;
+// ",
+//         r"
+// #[derive(proc_macros::DeriveIdentity)]
+// #[allow(dead_code)]
+// struct S;
+// ",
+//     );
+// }
 
 #[test]
 fn typing_inside_a_function_should_not_invalidate_item_expansions() {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
index aa2c4a6f1bc..44e132061ad 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
@@ -1,5 +1,7 @@
 //! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
 mod lower;
+#[cfg(test)]
+mod tests;
 
 use std::{
     fmt::{self, Display},
@@ -19,6 +21,8 @@ use syntax::ast;
 
 pub use hir_expand::mod_path::{path, ModPath, PathKind};
 
+pub use lower::hir_segment_to_ast_segment;
+
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum ImportAlias {
     /// Unnamed alias, as in `use Foo as _;`
@@ -230,7 +234,7 @@ impl Path {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct PathSegment<'a> {
     pub name: &'a Name,
     pub args_and_bindings: Option<&'a GenericArgs>,
@@ -274,6 +278,12 @@ impl<'a> PathSegments<'a> {
             generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
         }
     }
+    pub fn strip_last(&self) -> PathSegments<'a> {
+        PathSegments {
+            segments: self.segments.split_last().map_or(&[], |it| it.1),
+            generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
+        }
+    }
     pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
         self.segments
             .iter()
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index 553e615b94f..3b7e7653fba 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -17,13 +17,31 @@ use crate::{
     type_ref::{LifetimeRef, TypeBound, TypeRef},
 };
 
+#[cfg(test)]
+thread_local! {
+    /// This is used to test `hir_segment_to_ast_segment()`. It's a hack, but it makes testing much easier.
+    pub(super) static SEGMENT_LOWERING_MAP: std::cell::RefCell<rustc_hash::FxHashMap<ast::PathSegment, usize>> = std::cell::RefCell::default();
+}
+
 /// Converts an `ast::Path` to `Path`. Works with use trees.
 /// It correctly handles `$crate` based path from macro call.
+// If you modify the logic of the lowering, make sure to check if `hir_segment_to_ast_segment()`
+// also needs an update.
 pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
     let mut kind = PathKind::Plain;
     let mut type_anchor = None;
     let mut segments = Vec::new();
     let mut generic_args = Vec::new();
+    #[cfg(test)]
+    let mut ast_segments = Vec::new();
+    #[cfg(test)]
+    let mut ast_segments_offset = 0;
+    #[allow(unused_mut)]
+    let mut push_segment = |_segment: &ast::PathSegment, segments: &mut Vec<Name>, name| {
+        #[cfg(test)]
+        ast_segments.push(_segment.clone());
+        segments.push(name);
+    };
     loop {
         let segment = path.segment()?;
 
@@ -34,6 +52,10 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
         match segment.kind()? {
             ast::PathSegmentKind::Name(name_ref) => {
                 if name_ref.text() == "$crate" {
+                    if path.qualifier().is_some() {
+                        // FIXME: Report an error.
+                        return None;
+                    }
                     break kind = resolve_crate_root(
                         ctx.db.upcast(),
                         ctx.span_map().span_for_range(name_ref.syntax().text_range()).ctx,
@@ -48,7 +70,7 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
                     .or_else(|| {
                         lower_generic_args_from_fn_path(
                             ctx,
-                            segment.param_list(),
+                            segment.parenthesized_arg_list(),
                             segment.ret_type(),
                         )
                     });
@@ -56,10 +78,10 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
                     generic_args.resize(segments.len(), None);
                     generic_args.push(args);
                 }
-                segments.push(name);
+                push_segment(&segment, &mut segments, name);
             }
             ast::PathSegmentKind::SelfTypeKw => {
-                segments.push(Name::new_symbol_root(sym::Self_.clone()));
+                push_segment(&segment, &mut segments, Name::new_symbol_root(sym::Self_.clone()));
             }
             ast::PathSegmentKind::Type { type_ref, trait_ref } => {
                 assert!(path.qualifier().is_none()); // this can only occur at the first segment
@@ -81,6 +103,10 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
                         kind = mod_path.kind;
 
                         segments.extend(mod_path.segments().iter().cloned().rev());
+                        #[cfg(test)]
+                        {
+                            ast_segments_offset = mod_path.segments().len();
+                        }
                         if let Some(path_generic_args) = path_generic_args {
                             generic_args.resize(segments.len() - num_segments, None);
                             generic_args.extend(Vec::from(path_generic_args).into_iter().rev());
@@ -112,10 +138,18 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
                 }
             }
             ast::PathSegmentKind::CrateKw => {
+                if path.qualifier().is_some() {
+                    // FIXME: Report an error.
+                    return None;
+                }
                 kind = PathKind::Crate;
                 break;
             }
             ast::PathSegmentKind::SelfKw => {
+                if path.qualifier().is_some() {
+                    // FIXME: Report an error.
+                    return None;
+                }
                 // don't break out if `self` is the last segment of a path, this mean we got a
                 // use tree like `foo::{self}` which we want to resolve as `foo`
                 if !segments.is_empty() {
@@ -162,6 +196,13 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
         }
     }
 
+    #[cfg(test)]
+    {
+        ast_segments.reverse();
+        SEGMENT_LOWERING_MAP
+            .with_borrow_mut(|map| map.extend(ast_segments.into_iter().zip(ast_segments_offset..)));
+    }
+
     let mod_path = Interned::new(ModPath::from_segments(kind, segments));
     if type_anchor.is_none() && generic_args.is_empty() {
         return Some(Path::BarePath(mod_path));
@@ -181,6 +222,41 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
     }
 }
 
+/// This function finds the AST segment that corresponds to the HIR segment
+/// with index `segment_idx` on the path that is lowered from `path`.
+pub fn hir_segment_to_ast_segment(path: &ast::Path, segment_idx: u32) -> Option<ast::PathSegment> {
+    // Too tightly coupled to `lower_path()`, but unfortunately we cannot decouple them,
+    // as keeping source maps for all paths segments will have a severe impact on memory usage.
+
+    let mut segments = path.segments();
+    if let Some(ast::PathSegmentKind::Type { trait_ref: Some(trait_ref), .. }) =
+        segments.clone().next().and_then(|it| it.kind())
+    {
+        segments.next();
+        return find_segment(trait_ref.path()?.segments().chain(segments), segment_idx);
+    }
+    return find_segment(segments, segment_idx);
+
+    fn find_segment(
+        segments: impl Iterator<Item = ast::PathSegment>,
+        segment_idx: u32,
+    ) -> Option<ast::PathSegment> {
+        segments
+            .filter(|segment| match segment.kind() {
+                Some(
+                    ast::PathSegmentKind::CrateKw
+                    | ast::PathSegmentKind::SelfKw
+                    | ast::PathSegmentKind::SuperKw
+                    | ast::PathSegmentKind::Type { .. },
+                )
+                | None => false,
+                Some(ast::PathSegmentKind::Name(name)) => name.text() != "$crate",
+                Some(ast::PathSegmentKind::SelfTypeKw) => true,
+            })
+            .nth(segment_idx as usize)
+    }
+}
+
 pub(super) fn lower_generic_args(
     lower_ctx: &mut LowerCtx<'_>,
     node: ast::GenericArgList,
@@ -247,12 +323,12 @@ pub(super) fn lower_generic_args(
 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
 fn lower_generic_args_from_fn_path(
     ctx: &mut LowerCtx<'_>,
-    params: Option<ast::ParamList>,
+    args: Option<ast::ParenthesizedArgList>,
     ret_type: Option<ast::RetType>,
 ) -> Option<GenericArgs> {
-    let params = params?;
+    let params = args?;
     let mut param_types = Vec::new();
-    for param in params.params() {
+    for param in params.type_args() {
         let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
         param_types.push(type_ref);
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs
new file mode 100644
index 00000000000..67a27bf85e8
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/tests.rs
@@ -0,0 +1,126 @@
+use expect_test::{expect, Expect};
+use span::Edition;
+use syntax::ast::{self, make};
+use test_fixture::WithFixture;
+
+use crate::{
+    lower::LowerCtx,
+    path::{
+        lower::{hir_segment_to_ast_segment, SEGMENT_LOWERING_MAP},
+        Path,
+    },
+    pretty,
+    test_db::TestDB,
+    type_ref::{TypesMap, TypesSourceMap},
+};
+
+fn lower_path(path: ast::Path) -> (TestDB, TypesMap, Option<Path>) {
+    let (db, file_id) = TestDB::with_single_file("");
+    let mut types_map = TypesMap::default();
+    let mut types_source_map = TypesSourceMap::default();
+    let mut ctx = LowerCtx::new(&db, file_id.into(), &mut types_map, &mut types_source_map);
+    let lowered_path = ctx.lower_path(path);
+    (db, types_map, lowered_path)
+}
+
+#[track_caller]
+fn check_hir_to_ast(path: &str, ignore_segments: &[&str]) {
+    let path = make::path_from_text(path);
+    SEGMENT_LOWERING_MAP.with_borrow_mut(|map| map.clear());
+    let _ = lower_path(path.clone()).2.expect("failed to lower path");
+    SEGMENT_LOWERING_MAP.with_borrow(|map| {
+        for (segment, segment_idx) in map {
+            if ignore_segments.contains(&&*segment.to_string()) {
+                continue;
+            }
+
+            let restored_segment = hir_segment_to_ast_segment(&path, *segment_idx as u32)
+                .unwrap_or_else(|| {
+                    panic!(
+                        "failed to map back segment `{segment}` \
+                        numbered {segment_idx} in HIR from path `{path}`"
+                    )
+                });
+            assert_eq!(
+                segment, &restored_segment,
+                "mapping back `{segment}` numbered {segment_idx} in HIR \
+                from path `{path}` produced incorrect segment `{restored_segment}`"
+            );
+        }
+    });
+}
+
+#[test]
+fn hir_to_ast_trait_ref() {
+    check_hir_to_ast("<A as B::C::D>::E::F", &["A"]);
+}
+
+#[test]
+fn hir_to_ast_plain_path() {
+    check_hir_to_ast("A::B::C::D::E::F", &[]);
+}
+
+#[test]
+fn hir_to_ast_crate_path() {
+    check_hir_to_ast("crate::A::B::C", &[]);
+    check_hir_to_ast("crate::super::super::A::B::C", &[]);
+}
+
+#[test]
+fn hir_to_ast_self_path() {
+    check_hir_to_ast("self::A::B::C", &[]);
+    check_hir_to_ast("self::super::super::A::B::C", &[]);
+}
+
+#[test]
+fn hir_to_ast_super_path() {
+    check_hir_to_ast("super::A::B::C", &[]);
+    check_hir_to_ast("super::super::super::A::B::C", &[]);
+}
+
+#[test]
+fn hir_to_ast_type_anchor_path() {
+    check_hir_to_ast("<A::B>::C::D", &["A", "B"]);
+}
+
+#[test]
+fn hir_to_ast_path_super_in_middle() {
+    check_hir_to_ast("A::super::B::super::super::C::D", &[]);
+}
+
+#[track_caller]
+fn check_fail_lowering(path: &str) {
+    let (_, _, lowered_path) = lower_path(make::path_from_text(path));
+    assert!(lowered_path.is_none(), "path `{path}` should fail lowering");
+}
+
+#[test]
+fn keywords_in_middle_fail_lowering1() {
+    check_fail_lowering("self::A::self::B::super::C::crate::D");
+}
+
+#[test]
+fn keywords_in_middle_fail_lowering2() {
+    check_fail_lowering("A::super::self::C::D");
+}
+
+#[test]
+fn keywords_in_middle_fail_lowering3() {
+    check_fail_lowering("A::crate::B::C::D");
+}
+
+#[track_caller]
+fn check_path_lowering(path: &str, expected: Expect) {
+    let (db, types_map, lowered_path) = lower_path(make::path_from_text(path));
+    let lowered_path = lowered_path.expect("failed to lower path");
+    let mut buf = String::new();
+    pretty::print_path(&db, &lowered_path, &types_map, &mut buf, Edition::CURRENT)
+        .expect("failed to pretty-print path");
+    expected.assert_eq(&buf);
+}
+
+#[test]
+fn fn_like_path_with_coloncolon() {
+    check_path_lowering("Fn::(A, B) -> C", expect![[r#"Fn::<(A, B), Output = C>"#]]);
+    check_path_lowering("Fn::(A, B)", expect![[r#"Fn::<(A, B), Output = ()>"#]]);
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
index 9ceb82d5fd6..eb9488feaa9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
@@ -271,7 +271,7 @@ pub(crate) fn print_type_bounds(
                     TraitBoundModifier::None => (),
                     TraitBoundModifier::Maybe => write!(buf, "?")?,
                 }
-                print_path(db, path, map, buf, edition)?;
+                print_path(db, &map[*path], map, buf, edition)?;
             }
             TypeBound::ForLifetime(lifetimes, path) => {
                 write!(
@@ -279,7 +279,7 @@ pub(crate) fn print_type_bounds(
                     "for<{}> ",
                     lifetimes.iter().map(|it| it.display(db.upcast(), edition)).format(", ")
                 )?;
-                print_path(db, path, map, buf, edition)?;
+                print_path(db, &map[*path], map, buf, edition)?;
             }
             TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition))?,
             TypeBound::Use(args) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 26655e40ca7..316406c151f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -576,10 +576,12 @@ impl Resolver {
             match scope {
                 Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
                 &Scope::ImplDefScope(impl_) => {
-                    if let Some(target_trait) = &db.impl_data(impl_).target_trait {
-                        if let Some(TypeNs::TraitId(trait_)) =
-                            self.resolve_path_in_type_ns_fully(db, &target_trait.path)
-                        {
+                    let impl_data = db.impl_data(impl_);
+                    if let Some(target_trait) = impl_data.target_trait {
+                        if let Some(TypeNs::TraitId(trait_)) = self.resolve_path_in_type_ns_fully(
+                            db,
+                            &impl_data.types_map[target_trait.path],
+                        ) {
                             traits.insert(trait_);
                         }
                     }
@@ -640,9 +642,9 @@ impl Resolver {
         })
     }
 
-    pub fn generic_params(&self) -> Option<&Arc<GenericParams>> {
+    pub fn generic_params(&self) -> Option<&GenericParams> {
         self.scopes().find_map(|scope| match scope {
-            Scope::GenericParams { params, .. } => Some(params),
+            Scope::GenericParams { params, .. } => Some(&**params),
             _ => None,
         })
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index 0c36c88fb09..54e6c1fd206 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -78,6 +78,19 @@ impl FileLoader for TestDB {
 }
 
 impl TestDB {
+    pub(crate) fn fetch_test_crate(&self) -> CrateId {
+        let crate_graph = self.crate_graph();
+        let it = crate_graph
+            .iter()
+            .find(|&idx| {
+                crate_graph[idx].display_name.as_ref().map(|it| it.canonical_name().as_str())
+                    == Some("ra_test_fixture")
+            })
+            .or_else(|| crate_graph.iter().next())
+            .unwrap();
+        it
+    }
+
     pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
         for &krate in self.relevant_crates(file_id).iter() {
             let crate_def_map = self.crate_def_map(krate);
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index d41f69812ee..8c04d054029 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -180,6 +180,13 @@ impl<FileId: FileIdToSyntax, T> InFileWrapper<FileId, T> {
     }
 }
 
+#[allow(private_bounds)]
+impl<FileId: FileIdToSyntax, N: AstNode> InFileWrapper<FileId, AstPtr<N>> {
+    pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
+        self.value.to_node(&self.file_syntax(db))
+    }
+}
+
 impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
     pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
         self.with_value(self.value.syntax())
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
index b6d5828da96..0af29681a13 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
@@ -110,7 +110,8 @@ pub(crate) fn fixup_syntax(
                     }
                 },
                 ast::ExprStmt(it) => {
-                    if it.semicolon_token().is_none() {
+                    let needs_semi = it.semicolon_token().is_none() && it.expr().map_or(false, |e| e.syntax().kind() != SyntaxKind::BLOCK_EXPR);
+                    if needs_semi {
                         append.insert(node.clone().into(), vec![
                             Leaf::Punct(Punct {
                                 char: ';',
@@ -908,4 +909,19 @@ fn foo () {|| __ra_fixup}
 "#]],
         );
     }
+
+    #[test]
+    fn fixup_regression_() {
+        check(
+            r#"
+fn foo() {
+    {}
+    {}
+}
+"#,
+            expect![[r#"
+fn foo () {{} {}}
+"#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 7d2f556406d..2ee598dfbfd 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -269,6 +269,13 @@ pub enum MacroDefKind {
     ProcMacro(AstId<ast::Fn>, CustomProcMacroExpander, ProcMacroKind),
 }
 
+impl MacroDefKind {
+    #[inline]
+    pub fn is_declarative(&self) -> bool {
+        matches!(self, MacroDefKind::Declarative(..))
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct EagerCallInfo {
     /// The expanded argument of the eager macro.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 3a3a05c369a..6856eaa3e02 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -22,7 +22,7 @@ use crate::{
     consteval::ConstEvalError,
     dyn_compatibility::DynCompatibilityViolation,
     layout::{Layout, LayoutError},
-    lower::{GenericDefaults, GenericPredicates},
+    lower::{Diagnostics, GenericDefaults, GenericPredicates},
     method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
     mir::{BorrowckResult, MirBody, MirLowerError},
     Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner,
@@ -115,21 +115,35 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[ra_salsa::cycle(crate::lower::ty_recover)]
     fn ty(&self, def: TyDefId) -> Binders<Ty>;
 
+    #[ra_salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)]
+    fn type_for_type_alias_with_diagnostics(&self, def: TypeAliasId) -> (Binders<Ty>, Diagnostics);
+
     /// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
     /// a `StructId` or `EnumVariantId` with a record constructor.
     #[ra_salsa::invoke(crate::lower::value_ty_query)]
     fn value_ty(&self, def: ValueTyDefId) -> Option<Binders<Ty>>;
 
+    #[ra_salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)]
+    #[ra_salsa::cycle(crate::lower::impl_self_ty_with_diagnostics_recover)]
+    fn impl_self_ty_with_diagnostics(&self, def: ImplId) -> (Binders<Ty>, Diagnostics);
     #[ra_salsa::invoke(crate::lower::impl_self_ty_query)]
-    #[ra_salsa::cycle(crate::lower::impl_self_ty_recover)]
     fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
 
+    #[ra_salsa::invoke(crate::lower::const_param_ty_with_diagnostics_query)]
+    fn const_param_ty_with_diagnostics(&self, def: ConstParamId) -> (Ty, Diagnostics);
     #[ra_salsa::invoke(crate::lower::const_param_ty_query)]
     fn const_param_ty(&self, def: ConstParamId) -> Ty;
 
+    #[ra_salsa::invoke(crate::lower::impl_trait_with_diagnostics_query)]
+    fn impl_trait_with_diagnostics(&self, def: ImplId) -> Option<(Binders<TraitRef>, Diagnostics)>;
     #[ra_salsa::invoke(crate::lower::impl_trait_query)]
     fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
 
+    #[ra_salsa::invoke(crate::lower::field_types_with_diagnostics_query)]
+    fn field_types_with_diagnostics(
+        &self,
+        var: VariantId,
+    ) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics);
     #[ra_salsa::invoke(crate::lower::field_types_query)]
     fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
 
@@ -154,6 +168,11 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[ra_salsa::invoke(crate::lower::generic_predicates_query)]
     fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
 
+    #[ra_salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)]
+    fn generic_predicates_without_parent_with_diagnostics(
+        &self,
+        def: GenericDefId,
+    ) -> (GenericPredicates, Diagnostics);
     #[ra_salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
     fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates;
 
@@ -164,8 +183,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[ra_salsa::invoke(crate::lower::trait_environment_query)]
     fn trait_environment(&self, def: GenericDefId) -> Arc<TraitEnvironment>;
 
+    #[ra_salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
+    #[ra_salsa::cycle(crate::lower::generic_defaults_with_diagnostics_recover)]
+    fn generic_defaults_with_diagnostics(
+        &self,
+        def: GenericDefId,
+    ) -> (GenericDefaults, Diagnostics);
     #[ra_salsa::invoke(crate::lower::generic_defaults_query)]
-    #[ra_salsa::cycle(crate::lower::generic_defaults_recover)]
     fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
 
     #[ra_salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs
index af4d2c9fc04..30c02a2936d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs
@@ -9,5 +9,5 @@ pub use crate::diagnostics::{
     expr::{
         record_literal_missing_fields, record_pattern_missing_fields, BodyValidationDiagnostic,
     },
-    unsafe_check::{missing_unsafe, unsafe_expressions, UnsafeExpr},
+    unsafe_check::{missing_unsafe, unsafe_expressions, InsideUnsafeBlock, UnsafetyReason},
 };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 58de19ba81e..5452f5c680d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -383,9 +383,6 @@ impl<'db> PatCx for MatchCheckCtx<'db> {
                     } else {
                         let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
 
-                        // Whether we must not match the fields of this variant exhaustively.
-                        let is_non_exhaustive =
-                            LazyCell::new(|| self.is_foreign_non_exhaustive(adt));
                         let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));
 
                         self.list_variant_fields(ty, variant)
@@ -396,8 +393,7 @@ impl<'db> PatCx for MatchCheckCtx<'db> {
                                             .is_visible_from(self.db.upcast(), self.module)
                                 };
                                 let is_uninhabited = self.is_uninhabited(&ty);
-                                let private_uninhabited =
-                                    is_uninhabited && (!is_visible() || *is_non_exhaustive);
+                                let private_uninhabited = is_uninhabited && !is_visible();
                                 (ty, PrivateUninhabitedField(private_uninhabited))
                             })
                             .collect()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
index c7f7fb7ad3d..193aaa52c26 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -1,12 +1,16 @@
 //! Provides validations for unsafe code. Currently checks if unsafe functions are missing
 //! unsafe blocks.
 
+use std::mem;
+
+use either::Either;
 use hir_def::{
     body::Body,
-    hir::{Expr, ExprId, ExprOrPatId, Pat, UnaryOp},
-    resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
+    hir::{Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp},
+    path::Path,
+    resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
     type_ref::Rawness,
-    DefWithBodyId,
+    AdtId, DefWithBodyId, FieldId, VariantId,
 };
 
 use crate::{
@@ -16,7 +20,10 @@ use crate::{
 /// Returns `(unsafe_exprs, fn_is_unsafe)`.
 ///
 /// If `fn_is_unsafe` is false, `unsafe_exprs` are hard errors. If true, they're `unsafe_op_in_unsafe_fn`.
-pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> (Vec<ExprOrPatId>, bool) {
+pub fn missing_unsafe(
+    db: &dyn HirDatabase,
+    def: DefWithBodyId,
+) -> (Vec<(ExprOrPatId, UnsafetyReason)>, bool) {
     let _p = tracing::info_span!("missing_unsafe").entered();
 
     let mut res = Vec::new();
@@ -30,111 +37,243 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> (Vec<ExprOrPa
 
     let body = db.body(def);
     let infer = db.infer(def);
-    unsafe_expressions(db, &infer, def, &body, body.body_expr, &mut |expr| {
-        if !expr.inside_unsafe_block {
-            res.push(expr.node);
+    let mut callback = |node, inside_unsafe_block, reason| {
+        if inside_unsafe_block == InsideUnsafeBlock::No {
+            res.push((node, reason));
         }
-    });
+    };
+    let mut visitor = UnsafeVisitor::new(db, &infer, &body, def, &mut callback);
+    visitor.walk_expr(body.body_expr);
+
+    if !is_unsafe {
+        // Unsafety in function parameter patterns (that can only be union destructuring)
+        // cannot be inserted into an unsafe block, so even with `unsafe_op_in_unsafe_fn`
+        // it is turned off for unsafe functions.
+        for &param in &body.params {
+            visitor.walk_pat(param);
+        }
+    }
 
     (res, is_unsafe)
 }
 
-pub struct UnsafeExpr {
-    pub node: ExprOrPatId,
-    pub inside_unsafe_block: bool,
+#[derive(Debug, Clone, Copy)]
+pub enum UnsafetyReason {
+    UnionField,
+    UnsafeFnCall,
+    InlineAsm,
+    RawPtrDeref,
+    MutableStatic,
+    ExternStatic,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum InsideUnsafeBlock {
+    No,
+    Yes,
 }
 
-// FIXME: Move this out, its not a diagnostic only thing anymore, and handle unsafe pattern accesses as well
 pub fn unsafe_expressions(
     db: &dyn HirDatabase,
     infer: &InferenceResult,
     def: DefWithBodyId,
     body: &Body,
     current: ExprId,
-    unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
+    unsafe_expr_cb: &mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
 ) {
-    walk_unsafe(
-        db,
-        infer,
-        body,
-        &mut resolver_for_expr(db.upcast(), def, current),
-        def,
-        current,
-        false,
-        unsafe_expr_cb,
-    )
+    let mut visitor = UnsafeVisitor::new(db, infer, body, def, unsafe_expr_cb);
+    _ = visitor.resolver.update_to_inner_scope(db.upcast(), def, current);
+    visitor.walk_expr(current);
 }
 
-fn walk_unsafe(
-    db: &dyn HirDatabase,
-    infer: &InferenceResult,
-    body: &Body,
-    resolver: &mut Resolver,
+struct UnsafeVisitor<'a> {
+    db: &'a dyn HirDatabase,
+    infer: &'a InferenceResult,
+    body: &'a Body,
+    resolver: Resolver,
     def: DefWithBodyId,
-    current: ExprId,
-    inside_unsafe_block: bool,
-    unsafe_expr_cb: &mut dyn FnMut(UnsafeExpr),
-) {
-    let mut mark_unsafe_path = |path, node| {
-        let g = resolver.update_to_inner_scope(db.upcast(), def, current);
-        let hygiene = body.expr_or_pat_path_hygiene(node);
-        let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path, hygiene);
-        if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
-            let static_data = db.static_data(id);
-            if static_data.mutable || (static_data.is_extern && !static_data.has_safe_kw) {
-                unsafe_expr_cb(UnsafeExpr { node, inside_unsafe_block });
+    inside_unsafe_block: InsideUnsafeBlock,
+    inside_assignment: bool,
+    inside_union_destructure: bool,
+    unsafe_expr_cb: &'a mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
+}
+
+impl<'a> UnsafeVisitor<'a> {
+    fn new(
+        db: &'a dyn HirDatabase,
+        infer: &'a InferenceResult,
+        body: &'a Body,
+        def: DefWithBodyId,
+        unsafe_expr_cb: &'a mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
+    ) -> Self {
+        let resolver = def.resolver(db.upcast());
+        Self {
+            db,
+            infer,
+            body,
+            resolver,
+            def,
+            inside_unsafe_block: InsideUnsafeBlock::No,
+            inside_assignment: false,
+            inside_union_destructure: false,
+            unsafe_expr_cb,
+        }
+    }
+
+    fn call_cb(&mut self, node: ExprOrPatId, reason: UnsafetyReason) {
+        (self.unsafe_expr_cb)(node, self.inside_unsafe_block, reason);
+    }
+
+    fn walk_pats_top(&mut self, pats: impl Iterator<Item = PatId>, parent_expr: ExprId) {
+        let guard = self.resolver.update_to_inner_scope(self.db.upcast(), self.def, parent_expr);
+        pats.for_each(|pat| self.walk_pat(pat));
+        self.resolver.reset_to_guard(guard);
+    }
+
+    fn walk_pat(&mut self, current: PatId) {
+        let pat = &self.body.pats[current];
+
+        if self.inside_union_destructure {
+            match pat {
+                Pat::Tuple { .. }
+                | Pat::Record { .. }
+                | Pat::Range { .. }
+                | Pat::Slice { .. }
+                | Pat::Path(..)
+                | Pat::Lit(..)
+                | Pat::Bind { .. }
+                | Pat::TupleStruct { .. }
+                | Pat::Ref { .. }
+                | Pat::Box { .. }
+                | Pat::Expr(..)
+                | Pat::ConstBlock(..) => self.call_cb(current.into(), UnsafetyReason::UnionField),
+                // `Or` only wraps other patterns, and `Missing`/`Wild` do not constitute a read.
+                Pat::Missing | Pat::Wild | Pat::Or(_) => {}
             }
         }
-        resolver.reset_to_guard(g);
-    };
 
-    let expr = &body.exprs[current];
-    match expr {
-        &Expr::Call { callee, .. } => {
-            if let Some(func) = infer[callee].as_fn_def(db) {
-                if is_fn_unsafe_to_call(db, func) {
-                    unsafe_expr_cb(UnsafeExpr { node: current.into(), inside_unsafe_block });
+        match pat {
+            Pat::Record { .. } => {
+                if let Some((AdtId::UnionId(_), _)) = self.infer[current].as_adt() {
+                    let old_inside_union_destructure =
+                        mem::replace(&mut self.inside_union_destructure, true);
+                    self.body.walk_pats_shallow(current, |pat| self.walk_pat(pat));
+                    self.inside_union_destructure = old_inside_union_destructure;
+                    return;
                 }
             }
-        }
-        Expr::Path(path) => mark_unsafe_path(path, current.into()),
-        Expr::Ref { expr, rawness: Rawness::RawPtr, mutability: _ } => {
-            if let Expr::Path(_) = body.exprs[*expr] {
-                // Do not report unsafe for `addr_of[_mut]!(EXTERN_OR_MUT_STATIC)`,
-                // see https://github.com/rust-lang/rust/pull/125834.
-                return;
+            Pat::Path(path) => self.mark_unsafe_path(current.into(), path),
+            &Pat::ConstBlock(expr) => {
+                let old_inside_assignment = mem::replace(&mut self.inside_assignment, false);
+                self.walk_expr(expr);
+                self.inside_assignment = old_inside_assignment;
             }
+            &Pat::Expr(expr) => self.walk_expr(expr),
+            _ => {}
         }
-        Expr::MethodCall { .. } => {
-            if infer
-                .method_resolution(current)
-                .map(|(func, _)| is_fn_unsafe_to_call(db, func))
-                .unwrap_or(false)
-            {
-                unsafe_expr_cb(UnsafeExpr { node: current.into(), inside_unsafe_block });
+
+        self.body.walk_pats_shallow(current, |pat| self.walk_pat(pat));
+    }
+
+    fn walk_expr(&mut self, current: ExprId) {
+        let expr = &self.body.exprs[current];
+        let inside_assignment = mem::replace(&mut self.inside_assignment, false);
+        match expr {
+            &Expr::Call { callee, .. } => {
+                if let Some(func) = self.infer[callee].as_fn_def(self.db) {
+                    if is_fn_unsafe_to_call(self.db, func) {
+                        self.call_cb(current.into(), UnsafetyReason::UnsafeFnCall);
+                    }
+                }
             }
-        }
-        Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
-            if let TyKind::Raw(..) = &infer[*expr].kind(Interner) {
-                unsafe_expr_cb(UnsafeExpr { node: current.into(), inside_unsafe_block });
+            Expr::Path(path) => {
+                let guard =
+                    self.resolver.update_to_inner_scope(self.db.upcast(), self.def, current);
+                self.mark_unsafe_path(current.into(), path);
+                self.resolver.reset_to_guard(guard);
             }
-        }
-        Expr::Unsafe { .. } => {
-            return body.walk_child_exprs(current, |child| {
-                walk_unsafe(db, infer, body, resolver, def, child, true, unsafe_expr_cb);
-            });
-        }
-        &Expr::Assignment { target, value: _ } => {
-            body.walk_pats(target, &mut |pat| {
-                if let Pat::Path(path) = &body[pat] {
-                    mark_unsafe_path(path, pat.into());
+            Expr::Ref { expr, rawness: Rawness::RawPtr, mutability: _ } => {
+                if let Expr::Path(_) = self.body.exprs[*expr] {
+                    // Do not report unsafe for `addr_of[_mut]!(EXTERN_OR_MUT_STATIC)`,
+                    // see https://github.com/rust-lang/rust/pull/125834.
+                    return;
+                }
+            }
+            Expr::MethodCall { .. } => {
+                if self
+                    .infer
+                    .method_resolution(current)
+                    .map(|(func, _)| is_fn_unsafe_to_call(self.db, func))
+                    .unwrap_or(false)
+                {
+                    self.call_cb(current.into(), UnsafetyReason::UnsafeFnCall);
                 }
-            });
+            }
+            Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
+                if let TyKind::Raw(..) = &self.infer[*expr].kind(Interner) {
+                    self.call_cb(current.into(), UnsafetyReason::RawPtrDeref);
+                }
+            }
+            Expr::Unsafe { .. } => {
+                let old_inside_unsafe_block =
+                    mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes);
+                self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child));
+                self.inside_unsafe_block = old_inside_unsafe_block;
+                return;
+            }
+            &Expr::Assignment { target, value: _ } => {
+                let old_inside_assignment = mem::replace(&mut self.inside_assignment, true);
+                self.walk_pats_top(std::iter::once(target), current);
+                self.inside_assignment = old_inside_assignment;
+            }
+            Expr::InlineAsm(_) => self.call_cb(current.into(), UnsafetyReason::InlineAsm),
+            // rustc allows union assignment to propagate through field accesses and casts.
+            Expr::Cast { .. } => self.inside_assignment = inside_assignment,
+            Expr::Field { .. } => {
+                self.inside_assignment = inside_assignment;
+                if !inside_assignment {
+                    if let Some(Either::Left(FieldId { parent: VariantId::UnionId(_), .. })) =
+                        self.infer.field_resolution(current)
+                    {
+                        self.call_cb(current.into(), UnsafetyReason::UnionField);
+                    }
+                }
+            }
+            Expr::Block { statements, .. } | Expr::Async { statements, .. } => {
+                self.walk_pats_top(
+                    statements.iter().filter_map(|statement| match statement {
+                        &Statement::Let { pat, .. } => Some(pat),
+                        _ => None,
+                    }),
+                    current,
+                );
+            }
+            Expr::Match { arms, .. } => {
+                self.walk_pats_top(arms.iter().map(|arm| arm.pat), current);
+            }
+            &Expr::Let { pat, .. } => {
+                self.walk_pats_top(std::iter::once(pat), current);
+            }
+            Expr::Closure { args, .. } => {
+                self.walk_pats_top(args.iter().copied(), current);
+            }
+            _ => {}
         }
-        _ => {}
+
+        self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child));
     }
 
-    body.walk_child_exprs(current, |child| {
-        walk_unsafe(db, infer, body, resolver, def, child, inside_unsafe_block, unsafe_expr_cb);
-    });
+    fn mark_unsafe_path(&mut self, node: ExprOrPatId, path: &Path) {
+        let hygiene = self.body.expr_or_pat_path_hygiene(node);
+        let value_or_partial =
+            self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, hygiene);
+        if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
+            let static_data = self.db.static_data(id);
+            if static_data.mutable {
+                self.call_cb(node, UnsafetyReason::MutableStatic);
+            } else if static_data.is_extern && !static_data.has_safe_kw {
+                self.call_cb(node, UnsafetyReason::ExternStatic);
+            }
+        }
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 4e95bdf219f..3dfa0e97cec 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1047,10 +1047,14 @@ impl HirDisplay for Ty {
                     );
                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
                     if parameters.len() - impl_ > 0 {
+                        let params_len = parameters.len();
                         // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
                         let parameters =
                             generic_args_sans_defaults(f, Some(generic_def_id), parameters);
-                        let without_impl = self_param as usize + type_ + const_ + lifetime;
+                        assert!(params_len >= parameters.len());
+                        let defaults = params_len - parameters.len();
+                        let without_impl =
+                            self_param as usize + type_ + const_ + lifetime - defaults;
                         // parent's params (those from enclosing impl or trait, if any).
                         let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
 
@@ -2062,12 +2066,12 @@ impl HirDisplayWithTypesMap for TypeBound {
         types_map: &TypesMap,
     ) -> Result<(), HirDisplayError> {
         match self {
-            TypeBound::Path(path, modifier) => {
+            &TypeBound::Path(path, modifier) => {
                 match modifier {
                     TraitBoundModifier::None => (),
                     TraitBoundModifier::Maybe => write!(f, "?")?,
                 }
-                path.hir_fmt(f, types_map)
+                types_map[path].hir_fmt(f, types_map)
             }
             TypeBound::Lifetime(lifetime) => {
                 write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
@@ -2079,7 +2083,7 @@ impl HirDisplayWithTypesMap for TypeBound {
                     "for<{}> ",
                     lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
                 )?;
-                path.hir_fmt(f, types_map)
+                types_map[*path].hir_fmt(f, types_map)
             }
             TypeBound::Use(args) => {
                 let edition = f.edition();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index c094bc39512..fe7541d2374 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -55,6 +55,10 @@ impl Generics {
         self.def
     }
 
+    pub(crate) fn self_types_map(&self) -> &TypesMap {
+        &self.params.types_map
+    }
+
     pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
         self.iter_self_id().chain(self.iter_parent_id())
     }
@@ -86,15 +90,13 @@ impl Generics {
         self.iter_self().chain(self.iter_parent())
     }
 
-    pub(crate) fn iter_with_types_map(
+    pub(crate) fn iter_parents_with_types_map(
         &self,
     ) -> impl Iterator<Item = ((GenericParamId, GenericParamDataRef<'_>), &TypesMap)> + '_ {
-        self.iter_self().zip(std::iter::repeat(&self.params.types_map)).chain(
-            self.iter_parent().zip(
-                self.parent_generics()
-                    .into_iter()
-                    .flat_map(|it| std::iter::repeat(&it.params.types_map)),
-            ),
+        self.iter_parent().zip(
+            self.parent_generics()
+                .into_iter()
+                .flat_map(|it| std::iter::repeat(&it.params.types_map)),
         )
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 01e0b635b22..dbee5a1a919 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -58,7 +58,7 @@ use crate::{
     fold_tys,
     generics::Generics,
     infer::{coerce::CoerceMany, expr::ExprIsRead, unify::InferenceTable},
-    lower::ImplTraitLoweringMode,
+    lower::{ImplTraitLoweringMode, TyLoweringDiagnostic},
     mir::MirSpan,
     to_assoc_type_id,
     traits::FnTrait,
@@ -191,6 +191,14 @@ impl<T> InferOk<T> {
     }
 }
 
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum InferenceTyDiagnosticSource {
+    /// Diagnostics that come from types in the body.
+    Body,
+    /// Diagnostics that come from types in fn parameters/return type, or static & const types.
+    Signature,
+}
+
 #[derive(Debug)]
 pub(crate) struct TypeError;
 pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
@@ -264,6 +272,10 @@ pub enum InferenceDiagnostic {
         expr_ty: Ty,
         cast_ty: Ty,
     },
+    TyDiagnostic {
+        source: InferenceTyDiagnosticSource,
+        diag: TyLoweringDiagnostic,
+    },
 }
 
 /// A mismatch between an expected and an inferred type.
@@ -858,7 +870,8 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn collect_const(&mut self, data: &ConstData) {
-        let return_ty = self.make_ty(data.type_ref, &data.types_map);
+        let return_ty =
+            self.make_ty(data.type_ref, &data.types_map, InferenceTyDiagnosticSource::Signature);
 
         // Constants might be defining usage sites of TAITs.
         self.make_tait_coercion_table(iter::once(&return_ty));
@@ -867,7 +880,8 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn collect_static(&mut self, data: &StaticData) {
-        let return_ty = self.make_ty(data.type_ref, &data.types_map);
+        let return_ty =
+            self.make_ty(data.type_ref, &data.types_map, InferenceTyDiagnosticSource::Signature);
 
         // Statics might be defining usage sites of TAITs.
         self.make_tait_coercion_table(iter::once(&return_ty));
@@ -877,11 +891,12 @@ impl<'a> InferenceContext<'a> {
 
     fn collect_fn(&mut self, func: FunctionId) {
         let data = self.db.function_data(func);
-        let mut param_tys = self.with_ty_lowering(&data.types_map, |ctx| {
-            ctx.type_param_mode(ParamLoweringMode::Placeholder)
-                .impl_trait_mode(ImplTraitLoweringMode::Param);
-            data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>()
-        });
+        let mut param_tys =
+            self.with_ty_lowering(&data.types_map, InferenceTyDiagnosticSource::Signature, |ctx| {
+                ctx.type_param_mode(ParamLoweringMode::Placeholder)
+                    .impl_trait_mode(ImplTraitLoweringMode::Param);
+                data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>()
+            });
         // Check if function contains a va_list, if it does then we append it to the parameter types
         // that are collected from the function data
         if data.is_varargs() {
@@ -918,11 +933,12 @@ impl<'a> InferenceContext<'a> {
         }
         let return_ty = data.ret_type;
 
-        let return_ty = self.with_ty_lowering(&data.types_map, |ctx| {
-            ctx.type_param_mode(ParamLoweringMode::Placeholder)
-                .impl_trait_mode(ImplTraitLoweringMode::Opaque)
-                .lower_ty(return_ty)
-        });
+        let return_ty =
+            self.with_ty_lowering(&data.types_map, InferenceTyDiagnosticSource::Signature, |ctx| {
+                ctx.type_param_mode(ParamLoweringMode::Placeholder)
+                    .impl_trait_mode(ImplTraitLoweringMode::Opaque)
+                    .lower_ty(return_ty)
+            });
         let return_ty = self.insert_type_vars(return_ty);
 
         let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
@@ -1226,9 +1242,20 @@ impl<'a> InferenceContext<'a> {
         self.result.diagnostics.push(diagnostic);
     }
 
+    fn push_ty_diagnostics(
+        &mut self,
+        source: InferenceTyDiagnosticSource,
+        diagnostics: Vec<TyLoweringDiagnostic>,
+    ) {
+        self.result.diagnostics.extend(
+            diagnostics.into_iter().map(|diag| InferenceDiagnostic::TyDiagnostic { source, diag }),
+        );
+    }
+
     fn with_ty_lowering<R>(
-        &self,
+        &mut self,
         types_map: &TypesMap,
+        types_source: InferenceTyDiagnosticSource,
         f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
     ) -> R {
         let mut ctx = crate::lower::TyLoweringContext::new(
@@ -1237,32 +1264,41 @@ impl<'a> InferenceContext<'a> {
             types_map,
             self.owner.into(),
         );
-        f(&mut ctx)
+        let result = f(&mut ctx);
+        self.push_ty_diagnostics(types_source, ctx.diagnostics);
+        result
     }
 
     fn with_body_ty_lowering<R>(
-        &self,
+        &mut self,
         f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
     ) -> R {
-        self.with_ty_lowering(&self.body.types, f)
+        self.with_ty_lowering(&self.body.types, InferenceTyDiagnosticSource::Body, f)
     }
 
-    fn make_ty(&mut self, type_ref: TypeRefId, types_map: &TypesMap) -> Ty {
-        let ty = self.with_ty_lowering(types_map, |ctx| ctx.lower_ty(type_ref));
+    fn make_ty(
+        &mut self,
+        type_ref: TypeRefId,
+        types_map: &TypesMap,
+        type_source: InferenceTyDiagnosticSource,
+    ) -> Ty {
+        let ty = self.with_ty_lowering(types_map, type_source, |ctx| ctx.lower_ty(type_ref));
         let ty = self.insert_type_vars(ty);
         self.normalize_associated_types_in(ty)
     }
 
     fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty {
-        self.make_ty(type_ref, &self.body.types)
+        self.make_ty(type_ref, &self.body.types, InferenceTyDiagnosticSource::Body)
     }
 
     fn err_ty(&self) -> Ty {
         self.result.standard_types.unknown.clone()
     }
 
-    fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
-        let lt = self.with_ty_lowering(TypesMap::EMPTY, |ctx| ctx.lower_lifetime(lifetime_ref));
+    fn make_body_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
+        let lt = self.with_ty_lowering(TypesMap::EMPTY, InferenceTyDiagnosticSource::Body, |ctx| {
+            ctx.lower_lifetime(lifetime_ref)
+        });
         self.insert_type_vars(lt)
     }
 
@@ -1431,12 +1467,20 @@ impl<'a> InferenceContext<'a> {
                 Some(ResolveValueResult::ValueNs(value, _)) => match value {
                     ValueNs::EnumVariantId(var) => {
                         let substs = ctx.substs_from_path(path, var.into(), true);
+                        self.push_ty_diagnostics(
+                            InferenceTyDiagnosticSource::Body,
+                            ctx.diagnostics,
+                        );
                         let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
                         let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                         return (ty, Some(var.into()));
                     }
                     ValueNs::StructId(strukt) => {
                         let substs = ctx.substs_from_path(path, strukt.into(), true);
+                        self.push_ty_diagnostics(
+                            InferenceTyDiagnosticSource::Body,
+                            ctx.diagnostics,
+                        );
                         let ty = self.db.ty(strukt.into());
                         let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                         return (ty, Some(strukt.into()));
@@ -1462,18 +1506,21 @@ impl<'a> InferenceContext<'a> {
         return match resolution {
             TypeNs::AdtId(AdtId::StructId(strukt)) => {
                 let substs = ctx.substs_from_path(path, strukt.into(), true);
+                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
                 let ty = self.db.ty(strukt.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
             }
             TypeNs::AdtId(AdtId::UnionId(u)) => {
                 let substs = ctx.substs_from_path(path, u.into(), true);
+                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
                 let ty = self.db.ty(u.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
             }
             TypeNs::EnumVariantId(var) => {
                 let substs = ctx.substs_from_path(path, var.into(), true);
+                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
                 let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
@@ -1519,6 +1566,9 @@ impl<'a> InferenceContext<'a> {
                         resolved_segment,
                         current_segment,
                         false,
+                        &mut |_, _reason| {
+                            // FIXME: Report an error.
+                        },
                     );
 
                     ty = self.table.insert_type_vars(ty);
@@ -1532,6 +1582,7 @@ impl<'a> InferenceContext<'a> {
                     remaining_idx += 1;
                     remaining_segments = remaining_segments.skip(1);
                 }
+                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
 
                 let variant = ty.as_adt().and_then(|(id, _)| match id {
                     AdtId::StructId(s) => Some(VariantId::StructId(s)),
@@ -1550,6 +1601,7 @@ impl<'a> InferenceContext<'a> {
                 };
                 let substs =
                     ctx.substs_from_path_segment(resolved_seg, Some(it.into()), true, None);
+                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
                 let ty = self.db.ty(it.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 366c3cb0f17..2fe90a8a924 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -125,7 +125,11 @@ impl CoerceMany {
         // pointers to have a chance at getting a match. See
         // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
         let sig = match (self.merged_ty().kind(Interner), expr_ty.kind(Interner)) {
-            (TyKind::FnDef(x, _), TyKind::FnDef(y, _)) if x == y => None,
+            (TyKind::FnDef(x, _), TyKind::FnDef(y, _))
+                if x == y && ctx.table.unify(&self.merged_ty(), &expr_ty) =>
+            {
+                None
+            }
             (TyKind::Closure(x, _), TyKind::Closure(y, _)) if x == y => None,
             (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => {
                 // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 32b4ea2f28b..a13541be695 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -1287,8 +1287,8 @@ impl InferenceContext<'_> {
         tgt_expr: ExprId,
     ) {
         match fn_x {
-            FnTrait::FnOnce => (),
-            FnTrait::FnMut => {
+            FnTrait::FnOnce | FnTrait::AsyncFnOnce => (),
+            FnTrait::FnMut | FnTrait::AsyncFnMut => {
                 if let TyKind::Ref(Mutability::Mut, lt, inner) = derefed_callee.kind(Interner) {
                     if adjustments
                         .last()
@@ -1312,7 +1312,7 @@ impl InferenceContext<'_> {
                     ));
                 }
             }
-            FnTrait::Fn => {
+            FnTrait::Fn | FnTrait::AsyncFn => {
                 if !matches!(derefed_callee.kind(Interner), TyKind::Ref(Mutability::Not, _, _)) {
                     adjustments.push(Adjustment::borrow(
                         Mutability::Not,
@@ -2155,7 +2155,7 @@ impl InferenceContext<'_> {
                                 DebruijnIndex::INNERMOST,
                             )
                         },
-                        |this, lt_ref| this.make_lifetime(lt_ref),
+                        |this, lt_ref| this.make_body_lifetime(lt_ref),
                     ),
                 };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 7550d197a3b..a6296c3af23 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -19,7 +19,7 @@ use crate::{
     TyBuilder, TyExt, TyKind, ValueTyDefId,
 };
 
-use super::{ExprOrPatId, InferenceContext};
+use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource};
 
 impl InferenceContext<'_> {
     pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> {
@@ -163,6 +163,7 @@ impl InferenceContext<'_> {
 
             let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
             let (ty, _) = ctx.lower_ty_relative_path(ty, orig_ns, remaining_segments_for_ty);
+            self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
             let ty = self.table.insert_type_vars(ty);
             let ty = self.table.normalize_associated_types_in(ty);
             self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
@@ -265,6 +266,9 @@ impl InferenceContext<'_> {
                         resolved_segment,
                         remaining_segments_for_ty,
                         true,
+                        &mut |_, _reason| {
+                            // FIXME: Report an error.
+                        },
                     )
                 });
                 if ty.is_unknown() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 54aa18ce207..165861c1b17 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -666,7 +666,7 @@ impl<'a> InferenceTable<'a> {
             highest_known_var: InferenceVar,
         }
         impl TypeFolder<Interner> for VarFudger<'_, '_> {
-            fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
+            fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
                 self
             }
 
@@ -794,69 +794,75 @@ impl<'a> InferenceTable<'a> {
         ty: &Ty,
         num_args: usize,
     ) -> Option<(FnTrait, Vec<Ty>, Ty)> {
-        let krate = self.trait_env.krate;
-        let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
-        let trait_data = self.db.trait_data(fn_once_trait);
-        let output_assoc_type =
-            trait_data.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
-
-        let mut arg_tys = Vec::with_capacity(num_args);
-        let arg_ty = TyBuilder::tuple(num_args)
-            .fill(|it| {
-                let arg = match it {
-                    ParamKind::Type => self.new_type_var(),
-                    ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
-                    ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
-                };
-                arg_tys.push(arg.clone());
-                arg.cast(Interner)
-            })
-            .build();
-
-        let b = TyBuilder::trait_ref(self.db, fn_once_trait);
-        if b.remaining() != 2 {
-            return None;
-        }
-        let mut trait_ref = b.push(ty.clone()).push(arg_ty).build();
+        for (fn_trait_name, output_assoc_name, subtraits) in [
+            (FnTrait::FnOnce, sym::Output.clone(), &[FnTrait::Fn, FnTrait::FnMut][..]),
+            (FnTrait::AsyncFnMut, sym::CallRefFuture.clone(), &[FnTrait::AsyncFn]),
+            (FnTrait::AsyncFnOnce, sym::CallOnceFuture.clone(), &[]),
+        ] {
+            let krate = self.trait_env.krate;
+            let fn_trait = fn_trait_name.get_id(self.db, krate)?;
+            let trait_data = self.db.trait_data(fn_trait);
+            let output_assoc_type =
+                trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
+
+            let mut arg_tys = Vec::with_capacity(num_args);
+            let arg_ty = TyBuilder::tuple(num_args)
+                .fill(|it| {
+                    let arg = match it {
+                        ParamKind::Type => self.new_type_var(),
+                        ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
+                        ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
+                    };
+                    arg_tys.push(arg.clone());
+                    arg.cast(Interner)
+                })
+                .build();
+
+            let b = TyBuilder::trait_ref(self.db, fn_trait);
+            if b.remaining() != 2 {
+                return None;
+            }
+            let mut trait_ref = b.push(ty.clone()).push(arg_ty).build();
 
-        let projection = {
-            TyBuilder::assoc_type_projection(
+            let projection = TyBuilder::assoc_type_projection(
                 self.db,
                 output_assoc_type,
                 Some(trait_ref.substitution.clone()),
             )
-            .build()
-        };
+            .fill_with_unknown()
+            .build();
 
-        let trait_env = self.trait_env.env.clone();
-        let obligation = InEnvironment {
-            goal: trait_ref.clone().cast(Interner),
-            environment: trait_env.clone(),
-        };
-        let canonical = self.canonicalize(obligation.clone());
-        if self.db.trait_solve(krate, self.trait_env.block, canonical.cast(Interner)).is_some() {
-            self.register_obligation(obligation.goal);
-            let return_ty = self.normalize_projection_ty(projection);
-            for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
-                let fn_x_trait = fn_x.get_id(self.db, krate)?;
-                trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
-                let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
-                    goal: trait_ref.clone().cast(Interner),
-                    environment: trait_env.clone(),
-                };
-                let canonical = self.canonicalize(obligation.clone());
-                if self
-                    .db
-                    .trait_solve(krate, self.trait_env.block, canonical.cast(Interner))
-                    .is_some()
-                {
-                    return Some((fn_x, arg_tys, return_ty));
+            let trait_env = self.trait_env.env.clone();
+            let obligation = InEnvironment {
+                goal: trait_ref.clone().cast(Interner),
+                environment: trait_env.clone(),
+            };
+            let canonical = self.canonicalize(obligation.clone());
+            if self.db.trait_solve(krate, self.trait_env.block, canonical.cast(Interner)).is_some()
+            {
+                self.register_obligation(obligation.goal);
+                let return_ty = self.normalize_projection_ty(projection);
+                for &fn_x in subtraits {
+                    let fn_x_trait = fn_x.get_id(self.db, krate)?;
+                    trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
+                    let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> =
+                        InEnvironment {
+                            goal: trait_ref.clone().cast(Interner),
+                            environment: trait_env.clone(),
+                        };
+                    let canonical = self.canonicalize(obligation.clone());
+                    if self
+                        .db
+                        .trait_solve(krate, self.trait_env.block, canonical.cast(Interner))
+                        .is_some()
+                    {
+                        return Some((fn_x, arg_tys, return_ty));
+                    }
                 }
+                return Some((fn_trait_name, arg_tys, return_ty));
             }
-            unreachable!("It should at least implement FnOnce at this point");
-        } else {
-            None
         }
+        None
     }
 
     pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
@@ -1004,7 +1010,7 @@ mod resolve {
     where
         F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
     {
-        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
+        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
             self
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
index c0a781b17ee..56b549436c7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
@@ -5,8 +5,7 @@ use chalk_ir::{
     visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
     DebruijnIndex,
 };
-use hir_def::{visibility::Visibility, AdtId, EnumVariantId, HasModule, ModuleId, VariantId};
-use intern::sym;
+use hir_def::{visibility::Visibility, AdtId, EnumVariantId, ModuleId, VariantId};
 use rustc_hash::FxHashSet;
 
 use crate::{
@@ -118,11 +117,6 @@ impl UninhabitedFrom<'_> {
         variant: VariantId,
         subst: &Substitution,
     ) -> ControlFlow<VisiblyUninhabited> {
-        let is_local = variant.krate(self.db.upcast()) == self.target_mod.krate();
-        if !is_local && self.db.attrs(variant.into()).by_key(&sym::non_exhaustive).exists() {
-            return CONTINUE_OPAQUELY_INHABITED;
-        }
-
         let variant_data = self.db.variant_data(variant);
         let fields = variant_data.fields();
         if fields.is_empty() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 22e7b1d920f..8bb90ca31e4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -84,12 +84,14 @@ pub use infer::{
     cast::CastError,
     closure::{CaptureKind, CapturedItem},
     could_coerce, could_unify, could_unify_deeply, Adjust, Adjustment, AutoBorrow, BindingMode,
-    InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast,
+    InferenceDiagnostic, InferenceResult, InferenceTyDiagnosticSource, OverloadedDeref,
+    PointerCast,
 };
 pub use interner::Interner;
 pub use lower::{
-    associated_type_shorthand_candidates, ImplTraitLoweringMode, ParamLoweringMode, TyDefId,
-    TyLoweringContext, ValueTyDefId,
+    associated_type_shorthand_candidates, GenericArgsProhibitedReason, ImplTraitLoweringMode,
+    ParamLoweringMode, TyDefId, TyLoweringContext, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
+    ValueTyDefId,
 };
 pub use mapping::{
     from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
@@ -385,7 +387,6 @@ pub enum FnAbi {
     Fastcall,
     FastcallUnwind,
     Msp430Interrupt,
-    PlatformIntrinsic,
     PtxKernel,
     RiscvInterruptM,
     RiscvInterruptS,
@@ -444,7 +445,6 @@ impl FnAbi {
             s if *s == sym::fastcall_dash_unwind => FnAbi::FastcallUnwind,
             s if *s == sym::fastcall => FnAbi::Fastcall,
             s if *s == sym::msp430_dash_interrupt => FnAbi::Msp430Interrupt,
-            s if *s == sym::platform_dash_intrinsic => FnAbi::PlatformIntrinsic,
             s if *s == sym::ptx_dash_kernel => FnAbi::PtxKernel,
             s if *s == sym::riscv_dash_interrupt_dash_m => FnAbi::RiscvInterruptM,
             s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS,
@@ -487,7 +487,6 @@ impl FnAbi {
             FnAbi::Fastcall => "fastcall",
             FnAbi::FastcallUnwind => "fastcall-unwind",
             FnAbi::Msp430Interrupt => "msp430-interrupt",
-            FnAbi::PlatformIntrinsic => "platform-intrinsic",
             FnAbi::PtxKernel => "ptx-kernel",
             FnAbi::RiscvInterruptM => "riscv-interrupt-m",
             FnAbi::RiscvInterruptS => "riscv-interrupt-s",
@@ -646,7 +645,7 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
             F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
         > TypeFolder<Interner> for FreeVarFolder<F1, F2>
     {
-        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
+        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
             self
         }
 
@@ -697,7 +696,7 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
     impl<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>> TypeFolder<Interner>
         for TyFolder<F>
     {
-        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
+        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
             self
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index b868ea95f85..b23f2749ab2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -33,8 +33,8 @@ use hir_def::{
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
     resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
     type_ref::{
-        ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
-        TypeRefId, TypesMap, TypesSourceMap,
+        ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
+        TypeRef, TypeRefId, TypesMap, TypesSourceMap,
     },
     AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
     FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId,
@@ -48,7 +48,7 @@ use rustc_pattern_analysis::Captures;
 use smallvec::SmallVec;
 use stdx::{impl_from, never};
 use syntax::ast;
-use triomphe::Arc;
+use triomphe::{Arc, ThinArc};
 
 use crate::{
     all_super_traits,
@@ -102,6 +102,31 @@ impl ImplTraitLoweringState {
     }
 }
 
+type TypeSource = Either<TypeRefId, hir_def::type_ref::TypeSource>;
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct TyLoweringDiagnostic {
+    pub source: TypeSource,
+    pub kind: TyLoweringDiagnosticKind,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum TyLoweringDiagnosticKind {
+    GenericArgsProhibited { segment: u32, reason: GenericArgsProhibitedReason },
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum GenericArgsProhibitedReason {
+    Module,
+    TyParam,
+    SelfTy,
+    PrimitiveTy,
+    /// When there is a generic enum, within the expression `Enum::Variant`,
+    /// either `Enum` or `Variant` are allowed to have generic arguments, but not both.
+    // FIXME: This is not used now but it should be.
+    EnumVariant,
+}
+
 #[derive(Debug)]
 pub struct TyLoweringContext<'a> {
     pub db: &'a dyn HirDatabase,
@@ -125,6 +150,7 @@ pub struct TyLoweringContext<'a> {
     expander: Option<Expander>,
     /// Tracks types with explicit `?Sized` bounds.
     pub(crate) unsized_types: FxHashSet<Ty>,
+    pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
 }
 
 impl<'a> TyLoweringContext<'a> {
@@ -159,6 +185,7 @@ impl<'a> TyLoweringContext<'a> {
             type_param_mode,
             expander: None,
             unsized_types: FxHashSet::default(),
+            diagnostics: Vec::new(),
         }
     }
 
@@ -198,6 +225,20 @@ impl<'a> TyLoweringContext<'a> {
         self.type_param_mode = type_param_mode;
         self
     }
+
+    pub fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
+        let source = match self.types_source_map {
+            Some(source_map) => {
+                let Ok(source) = source_map.type_syntax(type_ref) else {
+                    stdx::never!("error in synthetic type");
+                    return;
+                };
+                Either::Right(source)
+            }
+            None => Either::Left(type_ref),
+        };
+        self.diagnostics.push(TyLoweringDiagnostic { source, kind });
+    }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@@ -264,7 +305,8 @@ impl<'a> TyLoweringContext<'a> {
                     .intern(Interner)
             }
             TypeRef::Path(path) => {
-                let (ty, res_) = self.lower_path(path);
+                let (ty, res_) =
+                    self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
                 res = res_;
                 ty
             }
@@ -463,6 +505,7 @@ impl<'a> TyLoweringContext<'a> {
                                 impl_trait_mode: mem::take(&mut self.impl_trait_mode),
                                 expander: self.expander.take(),
                                 unsized_types: mem::take(&mut self.unsized_types),
+                                diagnostics: mem::take(&mut self.diagnostics),
                             };
 
                             let ty = inner_ctx.lower_ty(type_ref);
@@ -470,6 +513,7 @@ impl<'a> TyLoweringContext<'a> {
                             self.impl_trait_mode = inner_ctx.impl_trait_mode;
                             self.expander = inner_ctx.expander;
                             self.unsized_types = inner_ctx.unsized_types;
+                            self.diagnostics = inner_ctx.diagnostics;
 
                             self.expander.as_mut().unwrap().exit(mark);
                             Some(ty)
@@ -541,6 +585,10 @@ impl<'a> TyLoweringContext<'a> {
         resolved_segment: PathSegment<'_>,
         remaining_segments: PathSegments<'_>,
         infer_args: bool,
+        on_prohibited_generics_for_resolved_segment: &mut dyn FnMut(
+            &mut Self,
+            GenericArgsProhibitedReason,
+        ),
     ) -> (Ty, Option<TypeNs>) {
         let ty = match resolution {
             TypeNs::TraitId(trait_) => {
@@ -607,28 +655,44 @@ impl<'a> TyLoweringContext<'a> {
                 // FIXME(trait_alias): Implement trait alias.
                 return (TyKind::Error.intern(Interner), None);
             }
-            TypeNs::GenericParam(param_id) => match self.type_param_mode {
-                ParamLoweringMode::Placeholder => {
-                    TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
+            TypeNs::GenericParam(param_id) => {
+                if resolved_segment.args_and_bindings.is_some() {
+                    on_prohibited_generics_for_resolved_segment(
+                        self,
+                        GenericArgsProhibitedReason::TyParam,
+                    );
                 }
-                ParamLoweringMode::Variable => {
-                    let idx = match self
-                        .generics()
-                        .expect("generics in scope")
-                        .type_or_const_param_idx(param_id.into())
-                    {
-                        None => {
-                            never!("no matching generics");
-                            return (TyKind::Error.intern(Interner), None);
-                        }
-                        Some(idx) => idx,
-                    };
 
-                    TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
+                match self.type_param_mode {
+                    ParamLoweringMode::Placeholder => {
+                        TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
+                    }
+                    ParamLoweringMode::Variable => {
+                        let idx = match self
+                            .generics()
+                            .expect("generics in scope")
+                            .type_or_const_param_idx(param_id.into())
+                        {
+                            None => {
+                                never!("no matching generics");
+                                return (TyKind::Error.intern(Interner), None);
+                            }
+                            Some(idx) => idx,
+                        };
+
+                        TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
+                    }
                 }
+                .intern(Interner)
             }
-            .intern(Interner),
             TypeNs::SelfType(impl_id) => {
+                if resolved_segment.args_and_bindings.is_some() {
+                    on_prohibited_generics_for_resolved_segment(
+                        self,
+                        GenericArgsProhibitedReason::SelfTy,
+                    );
+                }
+
                 let generics = self.generics().expect("impl should have generic param scope");
 
                 match self.type_param_mode {
@@ -654,6 +718,13 @@ impl<'a> TyLoweringContext<'a> {
                 }
             }
             TypeNs::AdtSelfType(adt) => {
+                if resolved_segment.args_and_bindings.is_some() {
+                    on_prohibited_generics_for_resolved_segment(
+                        self,
+                        GenericArgsProhibitedReason::SelfTy,
+                    );
+                }
+
                 let generics = generics(self.db.upcast(), adt.into());
                 let substs = match self.type_param_mode {
                     ParamLoweringMode::Placeholder => generics.placeholder_subst(self.db),
@@ -666,6 +737,12 @@ impl<'a> TyLoweringContext<'a> {
 
             TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args),
             TypeNs::BuiltinType(it) => {
+                if resolved_segment.args_and_bindings.is_some() {
+                    on_prohibited_generics_for_resolved_segment(
+                        self,
+                        GenericArgsProhibitedReason::PrimitiveTy,
+                    );
+                }
                 self.lower_path_inner(resolved_segment, it.into(), infer_args)
             }
             TypeNs::TypeAliasId(it) => {
@@ -677,7 +754,7 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
     }
 
-    pub(crate) fn lower_path(&mut self, path: &Path) -> (Ty, Option<TypeNs>) {
+    pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option<TypeNs>) {
         // Resolve the path (in type namespace)
         if let Some(type_ref) = path.type_anchor() {
             let (ty, res) = self.lower_ty_ext(type_ref);
@@ -692,19 +769,44 @@ impl<'a> TyLoweringContext<'a> {
 
         if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
             // trait object type without dyn
-            let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
+            let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
             let ty = self.lower_dyn_trait(&[bound]);
             return (ty, None);
         }
 
-        let (resolved_segment, remaining_segments) = match remaining_index {
-            None => (
-                path.segments().last().expect("resolved path has at least one element"),
-                PathSegments::EMPTY,
-            ),
-            Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
-        };
-        self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false)
+        let (module_segments, resolved_segment_idx, resolved_segment, remaining_segments) =
+            match remaining_index {
+                None => (
+                    path.segments().strip_last(),
+                    path.segments().len() - 1,
+                    path.segments().last().expect("resolved path has at least one element"),
+                    PathSegments::EMPTY,
+                ),
+                Some(i) => (
+                    path.segments().take(i - 1),
+                    i - 1,
+                    path.segments().get(i - 1).unwrap(),
+                    path.segments().skip(i),
+                ),
+            };
+
+        self.prohibit_generics(path_id, 0, module_segments, GenericArgsProhibitedReason::Module);
+
+        self.lower_partly_resolved_path(
+            resolution,
+            resolved_segment,
+            remaining_segments,
+            false,
+            &mut |this, reason| {
+                this.push_diagnostic(
+                    path_id.type_ref(),
+                    TyLoweringDiagnosticKind::GenericArgsProhibited {
+                        segment: resolved_segment_idx as u32,
+                        reason,
+                    },
+                )
+            },
+        )
     }
 
     fn select_associated_type(&mut self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
@@ -741,12 +843,8 @@ impl<'a> TyLoweringContext<'a> {
                 // generic params. It's inefficient to splice the `Substitution`s, so we may want
                 // that method to optionally take parent `Substitution` as we already know them at
                 // this point (`t.substitution`).
-                let substs = self.substs_from_path_segment(
-                    segment.clone(),
-                    Some(associated_ty.into()),
-                    false,
-                    None,
-                );
+                let substs =
+                    self.substs_from_path_segment(segment, Some(associated_ty.into()), false, None);
 
                 let len_self =
                     crate::generics::generics(self.db.upcast(), associated_ty.into()).len_self();
@@ -998,12 +1096,41 @@ impl<'a> TyLoweringContext<'a> {
         TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
     }
 
-    fn lower_trait_ref_from_path(&mut self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> {
+    fn prohibit_generics(
+        &mut self,
+        path_id: PathId,
+        idx: u32,
+        segments: PathSegments<'_>,
+        reason: GenericArgsProhibitedReason,
+    ) {
+        segments.iter().zip(idx..).for_each(|(segment, idx)| {
+            if segment.args_and_bindings.is_some() {
+                self.push_diagnostic(
+                    path_id.type_ref(),
+                    TyLoweringDiagnosticKind::GenericArgsProhibited { segment: idx, reason },
+                );
+            }
+        });
+    }
+
+    fn lower_trait_ref_from_path(
+        &mut self,
+        path_id: PathId,
+        explicit_self_ty: Ty,
+    ) -> Option<TraitRef> {
+        let path = &self.types_map[path_id];
         let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? {
             // FIXME(trait_alias): We need to handle trait alias here.
             TypeNs::TraitId(tr) => tr,
             _ => return None,
         };
+        // Do this after we verify it's indeed a trait to not confuse the user if they're not modules.
+        self.prohibit_generics(
+            path_id,
+            0,
+            path.segments().strip_last(),
+            GenericArgsProhibitedReason::Module,
+        );
         let segment = path.segments().last().expect("path should have at least one segment");
         Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty))
     }
@@ -1013,7 +1140,7 @@ impl<'a> TyLoweringContext<'a> {
         trait_ref: &HirTraitRef,
         explicit_self_ty: Ty,
     ) -> Option<TraitRef> {
-        self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
+        self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty)
     }
 
     fn trait_ref_substs_from_path(
@@ -1072,11 +1199,11 @@ impl<'a> TyLoweringContext<'a> {
     ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let mut trait_ref = None;
         let clause = match bound {
-            TypeBound::Path(path, TraitBoundModifier::None) => {
+            &TypeBound::Path(path, TraitBoundModifier::None) => {
                 trait_ref = self.lower_trait_ref_from_path(path, self_ty);
                 trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
             }
-            TypeBound::Path(path, TraitBoundModifier::Maybe) => {
+            &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
                 let sized_trait = self
                     .db
                     .lang_item(self.resolver.krate(), LangItem::Sized)
@@ -1092,7 +1219,7 @@ impl<'a> TyLoweringContext<'a> {
                 }
                 None
             }
-            TypeBound::ForLifetime(_, path) => {
+            &TypeBound::ForLifetime(_, path) => {
                 // FIXME Don't silently drop the hrtb lifetimes here
                 trait_ref = self.lower_trait_ref_from_path(path, self_ty);
                 trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
@@ -1121,8 +1248,8 @@ impl<'a> TyLoweringContext<'a> {
         trait_ref: TraitRef,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let last_segment = match bound {
-            TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
-                path.segments().last()
+            &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
+                self.types_map[path].segments().last()
             }
             TypeBound::Path(_, TraitBoundModifier::Maybe)
             | TypeBound::Use(_)
@@ -1227,7 +1354,9 @@ impl<'a> TyLoweringContext<'a> {
                                     }
                                     _ => unreachable!(),
                                 }
-                                ext.lower_ty(type_ref)
+                                let ty = ext.lower_ty(type_ref);
+                                self.diagnostics.extend(ext.diagnostics);
+                                ty
                             } else {
                                 self.lower_ty(type_ref)
                             };
@@ -1523,11 +1652,24 @@ fn named_associated_type_shorthand_candidates<R>(
     }
 }
 
-/// Build the type of all specific fields of a struct or enum variant.
+pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
+
+fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
+    (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
+}
+
 pub(crate) fn field_types_query(
     db: &dyn HirDatabase,
     variant_id: VariantId,
 ) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
+    db.field_types_with_diagnostics(variant_id).0
+}
+
+/// Build the type of all specific fields of a struct or enum variant.
+pub(crate) fn field_types_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    variant_id: VariantId,
+) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
     let var_data = variant_id.variant_data(db.upcast());
     let (resolver, def): (_, GenericDefId) = match variant_id {
         VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
@@ -1543,7 +1685,7 @@ pub(crate) fn field_types_query(
     for (field_id, field_data) in var_data.fields().iter() {
         res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
     }
-    Arc::new(res)
+    (Arc::new(res), create_diagnostics(ctx.diagnostics))
 }
 
 /// This query exists only to be used when resolving short-hand associated types
@@ -1593,9 +1735,10 @@ pub(crate) fn generic_predicates_for_param_query(
             }
 
             match bound {
-                TypeBound::ForLifetime(_, path) | TypeBound::Path(path, _) => {
+                &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
                     // Only lower the bound if the trait could possibly define the associated
                     // type we're looking for.
+                    let path = &ctx.types_map[path];
 
                     let Some(assoc_name) = &assoc_name else { return true };
                     let Some(TypeNs::TraitId(tr)) =
@@ -1743,15 +1886,22 @@ pub(crate) fn generic_predicates_query(
     db: &dyn HirDatabase,
     def: GenericDefId,
 ) -> GenericPredicates {
-    generic_predicates_filtered_by(db, def, |_, _| true)
+    generic_predicates_filtered_by(db, def, |_, _| true).0
 }
 
-/// Resolve the where clause(s) of an item with generics,
-/// except the ones inherited from the parent
 pub(crate) fn generic_predicates_without_parent_query(
     db: &dyn HirDatabase,
     def: GenericDefId,
 ) -> GenericPredicates {
+    db.generic_predicates_without_parent_with_diagnostics(def).0
+}
+
+/// Resolve the where clause(s) of an item with generics,
+/// except the ones inherited from the parent
+pub(crate) fn generic_predicates_without_parent_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    def: GenericDefId,
+) -> (GenericPredicates, Diagnostics) {
     generic_predicates_filtered_by(db, def, |_, d| *d == def)
 }
 
@@ -1761,7 +1911,7 @@ fn generic_predicates_filtered_by<F>(
     db: &dyn HirDatabase,
     def: GenericDefId,
     filter: F,
-) -> GenericPredicates
+) -> (GenericPredicates, Diagnostics)
 where
     F: Fn(&WherePredicate, &GenericDefId) -> bool,
 {
@@ -1802,7 +1952,10 @@ where
             );
         };
     }
-    GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
+    (
+        GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
+        create_diagnostics(ctx.diagnostics),
+    )
 }
 
 /// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
@@ -1855,75 +2008,110 @@ impl ops::Deref for GenericDefaults {
     }
 }
 
-/// Resolve the default type params from generics
 pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
+    db.generic_defaults_with_diagnostics(def).0
+}
+
+/// Resolve the default type params from generics.
+///
+/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents).
+pub(crate) fn generic_defaults_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    def: GenericDefId,
+) -> (GenericDefaults, Diagnostics) {
     let generic_params = generics(db.upcast(), def);
     if generic_params.len() == 0 {
-        return GenericDefaults(None);
+        return (GenericDefaults(None), None);
     }
     let resolver = def.resolver(db.upcast());
     let parent_start_idx = generic_params.len_self();
 
-    let mut ctx = TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into())
-        .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
-        .with_type_param_mode(ParamLoweringMode::Variable);
-    GenericDefaults(Some(Arc::from_iter(generic_params.iter_with_types_map().enumerate().map(
-        |(idx, ((id, p), types_map))| {
-            ctx.types_map = types_map;
-            match p {
-                GenericParamDataRef::TypeParamData(p) => {
-                    let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| {
-                        // Each default can only refer to previous parameters.
-                        // Type variable default referring to parameter coming
-                        // after it is forbidden (FIXME: report diagnostic)
-                        fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx)
-                    });
-                    crate::make_binders(db, &generic_params, ty.cast(Interner))
-                }
-                GenericParamDataRef::ConstParamData(p) => {
-                    let GenericParamId::ConstParamId(id) = id else {
-                        unreachable!("Unexpected lifetime or type argument")
-                    };
+    let mut ctx =
+        TyLoweringContext::new(db, &resolver, generic_params.self_types_map(), def.into())
+            .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
+            .with_type_param_mode(ParamLoweringMode::Variable);
+    let mut idx = 0;
+    let mut defaults = generic_params
+        .iter_self()
+        .map(|(id, p)| {
+            let result =
+                handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+            idx += 1;
+            result
+        })
+        .collect::<Vec<_>>();
+    let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
+    defaults.extend(generic_params.iter_parents_with_types_map().map(|((id, p), types_map)| {
+        ctx.types_map = types_map;
+        let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+        idx += 1;
+        result
+    }));
+    let defaults = GenericDefaults(Some(Arc::from_iter(defaults)));
+    return (defaults, diagnostics);
+
+    fn handle_generic_param(
+        ctx: &mut TyLoweringContext<'_>,
+        idx: usize,
+        id: GenericParamId,
+        p: GenericParamDataRef<'_>,
+        parent_start_idx: usize,
+        generic_params: &Generics,
+    ) -> Binders<crate::GenericArg> {
+        match p {
+            GenericParamDataRef::TypeParamData(p) => {
+                let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| {
+                    // Each default can only refer to previous parameters.
+                    // Type variable default referring to parameter coming
+                    // after it is forbidden (FIXME: report diagnostic)
+                    fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx)
+                });
+                crate::make_binders(ctx.db, generic_params, ty.cast(Interner))
+            }
+            GenericParamDataRef::ConstParamData(p) => {
+                let GenericParamId::ConstParamId(id) = id else {
+                    unreachable!("Unexpected lifetime or type argument")
+                };
 
-                    let mut val = p.default.as_ref().map_or_else(
-                        || unknown_const_as_generic(db.const_param_ty(id)),
-                        |c| {
-                            let param_ty = ctx.lower_ty(p.ty);
-                            let c = ctx.lower_const(c, param_ty);
-                            c.cast(Interner)
-                        },
-                    );
-                    // Each default can only refer to previous parameters, see above.
-                    val = fallback_bound_vars(val, idx, parent_start_idx);
-                    make_binders(db, &generic_params, val)
-                }
-                GenericParamDataRef::LifetimeParamData(_) => {
-                    make_binders(db, &generic_params, error_lifetime().cast(Interner))
-                }
+                let mut val = p.default.as_ref().map_or_else(
+                    || unknown_const_as_generic(ctx.db.const_param_ty(id)),
+                    |c| {
+                        let param_ty = ctx.lower_ty(p.ty);
+                        let c = ctx.lower_const(c, param_ty);
+                        c.cast(Interner)
+                    },
+                );
+                // Each default can only refer to previous parameters, see above.
+                val = fallback_bound_vars(val, idx, parent_start_idx);
+                make_binders(ctx.db, generic_params, val)
             }
-        },
-    ))))
+            GenericParamDataRef::LifetimeParamData(_) => {
+                make_binders(ctx.db, generic_params, error_lifetime().cast(Interner))
+            }
+        }
+    }
 }
 
-pub(crate) fn generic_defaults_recover(
+pub(crate) fn generic_defaults_with_diagnostics_recover(
     db: &dyn HirDatabase,
     _cycle: &Cycle,
     def: &GenericDefId,
-) -> GenericDefaults {
+) -> (GenericDefaults, Diagnostics) {
     let generic_params = generics(db.upcast(), *def);
     if generic_params.len() == 0 {
-        return GenericDefaults(None);
+        return (GenericDefaults(None), None);
     }
     // FIXME: this code is not covered in tests.
     // we still need one default per parameter
-    GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| {
+    let defaults = GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| {
         let val = match id {
             GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
             GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
             GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
         };
         crate::make_binders(db, &generic_params, val)
-    }))))
+    }))));
+    (defaults, None)
 }
 
 fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
@@ -2066,7 +2254,10 @@ fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
     make_binders(db, &generics, ty)
 }
 
-fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
+pub(crate) fn type_for_type_alias_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    t: TypeAliasId,
+) -> (Binders<Ty>, Diagnostics) {
     let generics = generics(db.upcast(), t.into());
     let resolver = t.resolver(db.upcast());
     let type_alias_data = db.type_alias_data(t);
@@ -2081,7 +2272,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
             .map(|type_ref| ctx.lower_ty(type_ref))
             .unwrap_or_else(|| TyKind::Error.intern(Interner))
     };
-    make_binders(db, &generics, inner)
+    (make_binders(db, &generics, inner), create_diagnostics(ctx.diagnostics))
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -2124,7 +2315,7 @@ pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
     match def {
         TyDefId::BuiltinType(it) => Binders::empty(Interner, TyBuilder::builtin(it)),
         TyDefId::AdtId(it) => type_for_adt(db, it),
-        TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
+        TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
     }
 }
 
@@ -2149,47 +2340,73 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option<
 }
 
 pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
+    db.impl_self_ty_with_diagnostics(impl_id).0
+}
+
+pub(crate) fn impl_self_ty_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    impl_id: ImplId,
+) -> (Binders<Ty>, Diagnostics) {
     let impl_data = db.impl_data(impl_id);
     let resolver = impl_id.resolver(db.upcast());
     let generics = generics(db.upcast(), impl_id.into());
     let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
-    make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty))
+    (
+        make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty)),
+        create_diagnostics(ctx.diagnostics),
+    )
 }
 
-// returns None if def is a type arg
 pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
+    db.const_param_ty_with_diagnostics(def).0
+}
+
+// returns None if def is a type arg
+pub(crate) fn const_param_ty_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    def: ConstParamId,
+) -> (Ty, Diagnostics) {
     let parent_data = db.generic_params(def.parent());
     let data = &parent_data[def.local_id()];
     let resolver = def.parent().resolver(db.upcast());
     let mut ctx =
         TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into());
-    match data {
+    let ty = match data {
         TypeOrConstParamData::TypeParamData(_) => {
             never!();
             Ty::new(Interner, TyKind::Error)
         }
         TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
-    }
+    };
+    (ty, create_diagnostics(ctx.diagnostics))
 }
 
-pub(crate) fn impl_self_ty_recover(
+pub(crate) fn impl_self_ty_with_diagnostics_recover(
     db: &dyn HirDatabase,
     _cycle: &Cycle,
     impl_id: &ImplId,
-) -> Binders<Ty> {
+) -> (Binders<Ty>, Diagnostics) {
     let generics = generics(db.upcast(), (*impl_id).into());
-    make_binders(db, &generics, TyKind::Error.intern(Interner))
+    (make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
 }
 
 pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
+    db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
+}
+
+pub(crate) fn impl_trait_with_diagnostics_query(
+    db: &dyn HirDatabase,
+    impl_id: ImplId,
+) -> Option<(Binders<TraitRef>, Diagnostics)> {
     let impl_data = db.impl_data(impl_id);
     let resolver = impl_id.resolver(db.upcast());
     let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
     let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
     let target_trait = impl_data.target_trait.as_ref()?;
-    Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?))
+    let trait_ref = Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?);
+    Some((trait_ref, create_diagnostics(ctx.diagnostics)))
 }
 
 pub(crate) fn return_type_impl_traits(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index c4e06400510..1d1044df6e9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -2023,11 +2023,11 @@ pub fn mir_body_for_closure_query(
     ctx.result.locals.alloc(Local { ty: infer[*root].clone() });
     let closure_local = ctx.result.locals.alloc(Local {
         ty: match kind {
-            FnTrait::FnOnce => infer[expr].clone(),
-            FnTrait::FnMut => {
+            FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr].clone(),
+            FnTrait::FnMut | FnTrait::AsyncFnMut => {
                 TyKind::Ref(Mutability::Mut, error_lifetime(), infer[expr].clone()).intern(Interner)
             }
-            FnTrait::Fn => {
+            FnTrait::Fn | FnTrait::AsyncFn => {
                 TyKind::Ref(Mutability::Not, error_lifetime(), infer[expr].clone()).intern(Interner)
             }
         },
@@ -2055,8 +2055,10 @@ pub fn mir_body_for_closure_query(
     let mut err = None;
     let closure_local = ctx.result.locals.iter().nth(1).unwrap().0;
     let closure_projection = match kind {
-        FnTrait::FnOnce => vec![],
-        FnTrait::FnMut | FnTrait::Fn => vec![ProjectionElem::Deref],
+        FnTrait::FnOnce | FnTrait::AsyncFnOnce => vec![],
+        FnTrait::FnMut | FnTrait::Fn | FnTrait::AsyncFnMut | FnTrait::AsyncFn => {
+            vec![ProjectionElem::Deref]
+        }
     };
     ctx.result.walk_places(|p, store| {
         if let Some(it) = upvar_map.get(&p.local) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index bcf9d5ceff0..cabeeea2bd8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -18,13 +18,13 @@ use std::sync::LazyLock;
 use base_db::SourceDatabaseFileInputExt as _;
 use expect_test::Expect;
 use hir_def::{
-    body::{Body, BodySourceMap, SyntheticSyntax},
+    body::{Body, BodySourceMap},
     db::DefDatabase,
     hir::{ExprId, Pat, PatId},
     item_scope::ItemScope,
     nameres::DefMap,
     src::HasSource,
-    AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
+    AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax,
 };
 use hir_expand::{db::ExpandDatabase, FileRange, InFile};
 use itertools::Itertools;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index 273571901ad..7992f1feeeb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
@@ -942,3 +942,19 @@ fn main() {
 "#,
     )
 }
+
+#[test]
+fn regression_18626() {
+    check_no_mismatches(
+        r#"
+fn f() {
+    trait T {
+        fn f() {}
+    }
+    impl T for i32 {}
+    impl T for u32 {}
+    &[i32::f, u32::f] as &[fn()];
+}
+    "#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 624148cab20..e15d44bd6de 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -1631,6 +1631,29 @@ fn test<'lifetime>(
 }
 
 #[test]
+fn lifetime_bounds() {
+    check_infer(
+        r#"
+//- minicore: sized, coerce_unsized
+trait Trait<'a>: Sized {
+    fn f(&'a self) {}
+}
+fn test<'a, 'b: 'a>(it: impl Trait<'a>){
+    it.f();
+}
+"#,
+        expect![[r#"
+            38..42 'self': &'a Self
+            44..46 '{}': ()
+            69..71 'it': impl Trait<'a>
+            88..103 '{     it.f(); }': ()
+            94..96 'it': impl Trait<'a>
+            94..100 'it.f()': ()
+        "#]],
+    );
+}
+
+#[test]
 fn error_bound_chalk() {
     check_types(
         r#"
@@ -4811,3 +4834,53 @@ fn bar(v: *const ()) {
         "#]],
     );
 }
+
+#[test]
+fn async_fn_traits() {
+    check_infer(
+        r#"
+//- minicore: async_fn
+async fn foo<T: AsyncFn(u32) -> i32>(a: T) {
+    let fut1 = a(0);
+    fut1.await;
+}
+async fn bar<T: AsyncFnMut(u32) -> i32>(mut b: T) {
+    let fut2 = b(0);
+    fut2.await;
+}
+async fn baz<T: AsyncFnOnce(u32) -> i32>(c: T) {
+    let fut3 = c(0);
+    fut3.await;
+}
+    "#,
+        expect![[r#"
+            37..38 'a': T
+            43..83 '{     ...ait; }': ()
+            43..83 '{     ...ait; }': impl Future<Output = ()>
+            53..57 'fut1': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            60..61 'a': T
+            60..64 'a(0)': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            62..63 '0': u32
+            70..74 'fut1': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            70..80 'fut1.await': i32
+            124..129 'mut b': T
+            134..174 '{     ...ait; }': ()
+            134..174 '{     ...ait; }': impl Future<Output = ()>
+            144..148 'fut2': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            151..152 'b': T
+            151..155 'b(0)': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            153..154 '0': u32
+            161..165 'fut2': AsyncFnMut::CallRefFuture<'?, T, (u32,)>
+            161..171 'fut2.await': i32
+            216..217 'c': T
+            222..262 '{     ...ait; }': ()
+            222..262 '{     ...ait; }': impl Future<Output = ()>
+            232..236 'fut3': AsyncFnOnce::CallOnceFuture<T, (u32,)>
+            239..240 'c': T
+            239..243 'c(0)': AsyncFnOnce::CallOnceFuture<T, (u32,)>
+            241..242 '0': u32
+            249..253 'fut3': AsyncFnOnce::CallOnceFuture<T, (u32,)>
+            249..259 'fut3.await': i32
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index 51ccd4ef293..8cb7dbf60f3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -220,6 +220,10 @@ pub enum FnTrait {
     FnOnce,
     FnMut,
     Fn,
+
+    AsyncFnOnce,
+    AsyncFnMut,
+    AsyncFn,
 }
 
 impl fmt::Display for FnTrait {
@@ -228,6 +232,9 @@ impl fmt::Display for FnTrait {
             FnTrait::FnOnce => write!(f, "FnOnce"),
             FnTrait::FnMut => write!(f, "FnMut"),
             FnTrait::Fn => write!(f, "Fn"),
+            FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
+            FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
+            FnTrait::AsyncFn => write!(f, "AsyncFn"),
         }
     }
 }
@@ -238,6 +245,9 @@ impl FnTrait {
             FnTrait::FnOnce => "call_once",
             FnTrait::FnMut => "call_mut",
             FnTrait::Fn => "call",
+            FnTrait::AsyncFnOnce => "async_call_once",
+            FnTrait::AsyncFnMut => "async_call_mut",
+            FnTrait::AsyncFn => "async_call",
         }
     }
 
@@ -246,6 +256,9 @@ impl FnTrait {
             FnTrait::FnOnce => LangItem::FnOnce,
             FnTrait::FnMut => LangItem::FnMut,
             FnTrait::Fn => LangItem::Fn,
+            FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
+            FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
+            FnTrait::AsyncFn => LangItem::AsyncFn,
         }
     }
 
@@ -254,15 +267,19 @@ impl FnTrait {
             LangItem::FnOnce => Some(FnTrait::FnOnce),
             LangItem::FnMut => Some(FnTrait::FnMut),
             LangItem::Fn => Some(FnTrait::Fn),
+            LangItem::AsyncFnOnce => Some(FnTrait::AsyncFnOnce),
+            LangItem::AsyncFnMut => Some(FnTrait::AsyncFnMut),
+            LangItem::AsyncFn => Some(FnTrait::AsyncFn),
             _ => None,
         }
     }
 
     pub const fn to_chalk_ir(self) -> rust_ir::ClosureKind {
+        // Chalk doesn't support async fn traits.
         match self {
-            FnTrait::FnOnce => rust_ir::ClosureKind::FnOnce,
-            FnTrait::FnMut => rust_ir::ClosureKind::FnMut,
-            FnTrait::Fn => rust_ir::ClosureKind::Fn,
+            FnTrait::AsyncFnOnce | FnTrait::FnOnce => rust_ir::ClosureKind::FnOnce,
+            FnTrait::AsyncFnMut | FnTrait::FnMut => rust_ir::ClosureKind::FnMut,
+            FnTrait::AsyncFn | FnTrait::Fn => rust_ir::ClosureKind::Fn,
         }
     }
 
@@ -271,6 +288,9 @@ impl FnTrait {
             FnTrait::FnOnce => Name::new_symbol_root(sym::call_once.clone()),
             FnTrait::FnMut => Name::new_symbol_root(sym::call_mut.clone()),
             FnTrait::Fn => Name::new_symbol_root(sym::call.clone()),
+            FnTrait::AsyncFnOnce => Name::new_symbol_root(sym::async_call_once.clone()),
+            FnTrait::AsyncFnMut => Name::new_symbol_root(sym::async_call_mut.clone()),
+            FnTrait::AsyncFn => Name::new_symbol_root(sym::async_call.clone()),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 28bda1e10e5..06719b09f73 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -185,7 +185,7 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
                     }
                 };
                 match is_trait {
-                    true => bound.as_path(),
+                    true => bound.as_path(&generic_params.types_map),
                     false => None,
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index 26666d6feb0..6aadc5c4f7e 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -33,6 +33,14 @@ syntax.workspace = true
 tt.workspace = true
 span.workspace = true
 
+[dev-dependencies]
+expect-test.workspace = true
+
+# local deps
+test-utils.workspace = true
+test-fixture.workspace = true
+syntax-bridge.workspace = true
+
 [features]
 in-rust-tree = ["hir-expand/in-rust-tree"]
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 8297acde857..612c6adb207 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -3,21 +3,35 @@
 //!
 //! This probably isn't the best way to do this -- ideally, diagnostics should
 //! be expressed in terms of hir types themselves.
-pub use hir_ty::diagnostics::{CaseType, IncorrectCase};
-use hir_ty::{
-    db::HirDatabase, diagnostics::BodyValidationDiagnostic, CastError, InferenceDiagnostic,
-};
-
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
-pub use hir_def::VariantId;
-use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
+use hir_def::{
+    hir::ExprOrPatId,
+    path::{hir_segment_to_ast_segment, ModPath},
+    type_ref::TypesSourceMap,
+    AssocItemId, DefWithBodyId, SyntheticSyntax,
+};
 use hir_expand::{name::Name, HirFileId, InFile};
-use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
+use hir_ty::{
+    db::HirDatabase,
+    diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
+    CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
+    TyLoweringDiagnosticKind,
+};
+use syntax::{
+    ast::{self, HasGenericArgs},
+    AstPtr, SyntaxError, SyntaxNodePtr, TextRange,
+};
 use triomphe::Arc;
 
 use crate::{AssocItem, Field, Local, Trait, Type};
 
+pub use hir_def::VariantId;
+pub use hir_ty::{
+    diagnostics::{CaseType, IncorrectCase},
+    GenericArgsProhibitedReason,
+};
+
 macro_rules! diagnostics {
     ($($diag:ident,)*) => {
         #[derive(Debug)]
@@ -96,6 +110,7 @@ diagnostics![
     UnresolvedIdent,
     UnusedMut,
     UnusedVariable,
+    GenericArgsProhibited,
 ];
 
 #[derive(Debug)]
@@ -258,9 +273,10 @@ pub struct PrivateField {
 
 #[derive(Debug)]
 pub struct MissingUnsafe {
-    pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
+    pub node: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
     /// If true, the diagnostics is an `unsafe_op_in_unsafe_fn` lint instead of a hard error.
     pub only_lint: bool,
+    pub reason: UnsafetyReason,
 }
 
 #[derive(Debug)]
@@ -385,6 +401,12 @@ pub struct InvalidCast {
     pub cast_ty: Type,
 }
 
+#[derive(Debug)]
+pub struct GenericArgsProhibited {
+    pub args: InFile<AstPtr<Either<ast::GenericArgList, ast::ParenthesizedArgList>>>,
+    pub reason: GenericArgsProhibitedReason,
+}
+
 impl AnyDiagnostic {
     pub(crate) fn body_validation_diagnostic(
         db: &dyn HirDatabase,
@@ -524,6 +546,7 @@ impl AnyDiagnostic {
         db: &dyn HirDatabase,
         def: DefWithBodyId,
         d: &InferenceDiagnostic,
+        outer_types_source_map: &TypesSourceMap,
         source_map: &hir_def::body::BodySourceMap,
     ) -> Option<AnyDiagnostic> {
         let expr_syntax = |expr| {
@@ -637,6 +660,44 @@ impl AnyDiagnostic {
                 let cast_ty = Type::new(db, def, cast_ty.clone());
                 InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
             }
+            InferenceDiagnostic::TyDiagnostic { source, diag } => {
+                let source_map = match source {
+                    InferenceTyDiagnosticSource::Body => &source_map.types,
+                    InferenceTyDiagnosticSource::Signature => outer_types_source_map,
+                };
+                Self::ty_diagnostic(diag, source_map, db)?
+            }
+        })
+    }
+
+    pub(crate) fn ty_diagnostic(
+        diag: &TyLoweringDiagnostic,
+        source_map: &TypesSourceMap,
+        db: &dyn HirDatabase,
+    ) -> Option<AnyDiagnostic> {
+        let source = match diag.source {
+            Either::Left(type_ref_id) => {
+                let Ok(source) = source_map.type_syntax(type_ref_id) else {
+                    stdx::never!("error on synthetic type syntax");
+                    return None;
+                };
+                source
+            }
+            Either::Right(source) => source,
+        };
+        let syntax = || source.value.to_node(&db.parse_or_expand(source.file_id));
+        Some(match diag.kind {
+            TyLoweringDiagnosticKind::GenericArgsProhibited { segment, reason } => {
+                let ast::Type::PathType(syntax) = syntax() else { return None };
+                let segment = hir_segment_to_ast_segment(&syntax.path()?, segment)?;
+                let args = if let Some(generics) = segment.generic_arg_list() {
+                    AstPtr::new(&generics).wrap_left()
+                } else {
+                    AstPtr::new(&segment.parenthesized_arg_list()?).wrap_right()
+                };
+                let args = source.with_value(args);
+                GenericArgsProhibited { args, reason }.into()
+            }
         })
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 9275f45d881..959d62d5951 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -132,12 +132,18 @@ impl HirDisplay for Function {
         } else {
             match &data.types_map[data.ret_type] {
                 TypeRef::ImplTrait(bounds) => match &bounds[0] {
-                    TypeBound::Path(path, _) => Some(
-                        *path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
-                            [0]
-                        .type_ref
-                        .as_ref()
-                        .unwrap(),
+                    &TypeBound::Path(path, _) => Some(
+                        *data.types_map[path]
+                            .segments()
+                            .iter()
+                            .last()
+                            .unwrap()
+                            .args_and_bindings
+                            .unwrap()
+                            .bindings[0]
+                            .type_ref
+                            .as_ref()
+                            .unwrap(),
                     ),
                     _ => None,
                 },
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index c9498b3aead..83d72dfcf14 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -20,12 +20,11 @@
 #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
 #![recursion_limit = "512"]
 
-mod semantics;
-mod source_analyzer;
-
 mod attrs;
 mod from_id;
 mod has_source;
+mod semantics;
+mod source_analyzer;
 
 pub mod db;
 pub mod diagnostics;
@@ -43,7 +42,7 @@ use arrayvec::ArrayVec;
 use base_db::{CrateDisplayName, CrateId, CrateOrigin};
 use either::Either;
 use hir_def::{
-    body::{BodyDiagnostic, SyntheticSyntax},
+    body::BodyDiagnostic,
     data::adt::VariantData,
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
@@ -54,11 +53,12 @@ use hir_def::{
     path::ImportAlias,
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
+    type_ref::TypesSourceMap,
     AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
     DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
     HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
-    MacroExpander, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId,
-    TypeOrConstParamId, TypeParamId, UnionId,
+    MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId,
+    TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
 };
 use hir_expand::{
     attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
@@ -76,8 +76,8 @@ use hir_ty::{
     traits::FnTrait,
     AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
     GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
-    TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
-    WhereClause,
+    TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic,
+    ValueTyDefId, WhereClause,
 };
 use itertools::Itertools;
 use nameres::diagnostics::DefDiagnosticKind;
@@ -89,7 +89,7 @@ use syntax::{
     ast::{self, HasAttrs as _, HasGenericParams, HasName},
     format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
 };
-use triomphe::Arc;
+use triomphe::{Arc, ThinArc};
 
 use crate::db::{DefDatabase, HirDatabase};
 
@@ -147,6 +147,7 @@ pub use {
     },
     hir_ty::{
         consteval::ConstEvalError,
+        diagnostics::UnsafetyReason,
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
         dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
         layout::LayoutError,
@@ -410,6 +411,10 @@ impl ModuleDef {
             }
         }
 
+        if let Some(def) = self.as_self_generic_def() {
+            def.diagnostics(db, &mut acc);
+        }
+
         acc
     }
 
@@ -430,6 +435,23 @@ impl ModuleDef {
         }
     }
 
+    /// Returns only defs that have generics from themselves, not their parent.
+    pub fn as_self_generic_def(self) -> Option<GenericDef> {
+        match self {
+            ModuleDef::Function(it) => Some(it.into()),
+            ModuleDef::Adt(it) => Some(it.into()),
+            ModuleDef::Trait(it) => Some(it.into()),
+            ModuleDef::TraitAlias(it) => Some(it.into()),
+            ModuleDef::TypeAlias(it) => Some(it.into()),
+            ModuleDef::Module(_)
+            | ModuleDef::Variant(_)
+            | ModuleDef::Static(_)
+            | ModuleDef::Const(_)
+            | ModuleDef::BuiltinType(_)
+            | ModuleDef::Macro(_) => None,
+        }
+    }
+
     pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
         Some(match self {
             ModuleDef::Module(it) => it.attrs(db),
@@ -604,17 +626,42 @@ impl Module {
                 ModuleDef::Adt(adt) => {
                     match adt {
                         Adt::Struct(s) => {
+                            let tree_id = s.id.lookup(db.upcast()).id;
+                            let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
+                            push_ty_diagnostics(
+                                db,
+                                acc,
+                                db.field_types_with_diagnostics(s.id.into()).1,
+                                tree_source_maps.strukt(tree_id.value).item(),
+                            );
                             for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
                                 emit_def_diagnostic(db, acc, diag, edition);
                             }
                         }
                         Adt::Union(u) => {
+                            let tree_id = u.id.lookup(db.upcast()).id;
+                            let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
+                            push_ty_diagnostics(
+                                db,
+                                acc,
+                                db.field_types_with_diagnostics(u.id.into()).1,
+                                tree_source_maps.union(tree_id.value).item(),
+                            );
                             for diag in db.union_data_with_diagnostics(u.id).1.iter() {
                                 emit_def_diagnostic(db, acc, diag, edition);
                             }
                         }
                         Adt::Enum(e) => {
                             for v in e.variants(db) {
+                                let tree_id = v.id.lookup(db.upcast()).id;
+                                let tree_source_maps =
+                                    tree_id.item_tree_with_source_map(db.upcast()).1;
+                                push_ty_diagnostics(
+                                    db,
+                                    acc,
+                                    db.field_types_with_diagnostics(v.id.into()).1,
+                                    tree_source_maps.variant(tree_id.value),
+                                );
                                 acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
                                 for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
                                     emit_def_diagnostic(db, acc, diag, edition);
@@ -625,6 +672,17 @@ impl Module {
                     acc.extend(def.diagnostics(db, style_lints))
                 }
                 ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
+                ModuleDef::TypeAlias(type_alias) => {
+                    let tree_id = type_alias.id.lookup(db.upcast()).id;
+                    let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
+                    push_ty_diagnostics(
+                        db,
+                        acc,
+                        db.type_for_type_alias_with_diagnostics(type_alias.id).1,
+                        tree_source_maps.type_alias(tree_id.value).item(),
+                    );
+                    acc.extend(def.diagnostics(db, style_lints));
+                }
                 _ => acc.extend(def.diagnostics(db, style_lints)),
             }
         }
@@ -634,8 +692,11 @@ impl Module {
 
         let mut impl_assoc_items_scratch = vec![];
         for impl_def in self.impl_defs(db) {
+            GenericDef::Impl(impl_def).diagnostics(db, acc);
+
             let loc = impl_def.id.lookup(db.upcast());
-            let tree = loc.id.item_tree(db.upcast());
+            let (tree, tree_source_maps) = loc.id.item_tree_with_source_map(db.upcast());
+            let source_map = tree_source_maps.impl_(loc.id.value).item();
             let node = &tree[loc.id.value];
             let file_id = loc.id.file_id();
             if file_id.macro_file().map_or(false, |it| it.is_builtin_derive(db.upcast())) {
@@ -770,6 +831,19 @@ impl Module {
                 impl_assoc_items_scratch.clear();
             }
 
+            push_ty_diagnostics(
+                db,
+                acc,
+                db.impl_self_ty_with_diagnostics(impl_def.id).1,
+                source_map,
+            );
+            push_ty_diagnostics(
+                db,
+                acc,
+                db.impl_trait_with_diagnostics(impl_def.id).and_then(|it| it.1),
+                source_map,
+            );
+
             for &item in db.impl_data(impl_def.id).items.iter() {
                 AssocItem::from(item).diagnostics(db, acc, style_lints);
             }
@@ -1801,6 +1875,25 @@ impl DefWithBody {
         let krate = self.module(db).id.krate();
 
         let (body, source_map) = db.body_with_source_map(self.into());
+        let item_tree_source_maps;
+        let outer_types_source_map = match self {
+            DefWithBody::Function(function) => {
+                let function = function.id.lookup(db.upcast()).id;
+                item_tree_source_maps = function.item_tree_with_source_map(db.upcast()).1;
+                item_tree_source_maps.function(function.value).item()
+            }
+            DefWithBody::Static(statik) => {
+                let statik = statik.id.lookup(db.upcast()).id;
+                item_tree_source_maps = statik.item_tree_with_source_map(db.upcast()).1;
+                item_tree_source_maps.statik(statik.value)
+            }
+            DefWithBody::Const(konst) => {
+                let konst = konst.id.lookup(db.upcast()).id;
+                item_tree_source_maps = konst.item_tree_with_source_map(db.upcast()).1;
+                item_tree_source_maps.konst(konst.value)
+            }
+            DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => &TypesSourceMap::EMPTY,
+        };
 
         for (_, def_map) in body.blocks(db.upcast()) {
             Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
@@ -1860,7 +1953,13 @@ impl DefWithBody {
 
         let infer = db.infer(self.into());
         for d in &infer.diagnostics {
-            acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map));
+            acc.extend(AnyDiagnostic::inference_diagnostic(
+                db,
+                self.into(),
+                d,
+                outer_types_source_map,
+                &source_map,
+            ));
         }
 
         for (pat_or_expr, mismatch) in infer.type_mismatches() {
@@ -1890,10 +1989,10 @@ impl DefWithBody {
             );
         }
 
-        let (unafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into());
-        for expr in unafe_exprs {
-            match source_map.expr_or_pat_syntax(expr) {
-                Ok(expr) => acc.push(MissingUnsafe { expr, only_lint }.into()),
+        let (unsafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into());
+        for (node, reason) in unsafe_exprs {
+            match source_map.expr_or_pat_syntax(node) {
+                Ok(node) => acc.push(MissingUnsafe { node, only_lint, reason }.into()),
                 Err(SyntheticSyntax) => {
                     // FIXME: Here and elsewhere in this file, the `expr` was
                     // desugared, report or assert that this doesn't happen.
@@ -3324,12 +3423,22 @@ impl AssocItem {
     ) {
         match self {
             AssocItem::Function(func) => {
+                GenericDef::Function(func).diagnostics(db, acc);
                 DefWithBody::from(func).diagnostics(db, acc, style_lints);
             }
             AssocItem::Const(const_) => {
                 DefWithBody::from(const_).diagnostics(db, acc, style_lints);
             }
             AssocItem::TypeAlias(type_alias) => {
+                GenericDef::TypeAlias(type_alias).diagnostics(db, acc);
+                let tree_id = type_alias.id.lookup(db.upcast()).id;
+                let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
+                push_ty_diagnostics(
+                    db,
+                    acc,
+                    db.type_for_type_alias_with_diagnostics(type_alias.id).1,
+                    tree_source_maps.type_alias(tree_id.value).item(),
+                );
                 for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
                     acc.push(diag.into());
                 }
@@ -3416,6 +3525,97 @@ impl GenericDef {
             })
             .collect()
     }
+
+    fn id(self) -> GenericDefId {
+        match self {
+            GenericDef::Function(it) => it.id.into(),
+            GenericDef::Adt(it) => it.into(),
+            GenericDef::Trait(it) => it.id.into(),
+            GenericDef::TraitAlias(it) => it.id.into(),
+            GenericDef::TypeAlias(it) => it.id.into(),
+            GenericDef::Impl(it) => it.id.into(),
+            GenericDef::Const(it) => it.id.into(),
+        }
+    }
+
+    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
+        let def = self.id();
+
+        let item_tree_source_maps;
+        let (generics, generics_source_map) = db.generic_params_with_source_map(def);
+
+        if generics.is_empty() && generics.no_predicates() {
+            return;
+        }
+
+        let source_map = match &generics_source_map {
+            Some(it) => it,
+            None => match def {
+                GenericDefId::FunctionId(it) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.function(id.value).generics()
+                }
+                GenericDefId::AdtId(AdtId::EnumId(it)) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.enum_generic(id.value)
+                }
+                GenericDefId::AdtId(AdtId::StructId(it)) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.strukt(id.value).generics()
+                }
+                GenericDefId::AdtId(AdtId::UnionId(it)) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.union(id.value).generics()
+                }
+                GenericDefId::TraitId(it) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.trait_generic(id.value)
+                }
+                GenericDefId::TraitAliasId(it) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.trait_alias_generic(id.value)
+                }
+                GenericDefId::TypeAliasId(it) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.type_alias(id.value).generics()
+                }
+                GenericDefId::ImplId(it) => {
+                    let id = it.lookup(db.upcast()).id;
+                    item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
+                    item_tree_source_maps.impl_(id.value).generics()
+                }
+                GenericDefId::ConstId(_) => return,
+            },
+        };
+
+        push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, source_map);
+        push_ty_diagnostics(
+            db,
+            acc,
+            db.generic_predicates_without_parent_with_diagnostics(def).1,
+            source_map,
+        );
+        for (param_id, param) in generics.iter_type_or_consts() {
+            if let TypeOrConstParamData::ConstParamData(_) = param {
+                push_ty_diagnostics(
+                    db,
+                    acc,
+                    db.const_param_ty_with_diagnostics(ConstParamId::from_unchecked(
+                        TypeOrConstParamId { parent: def, local_id: param_id },
+                    ))
+                    .1,
+                    source_map,
+                );
+            }
+        }
+    }
 }
 
 /// A single local definition.
@@ -3581,6 +3781,18 @@ impl Local {
     }
 }
 
+impl PartialOrd for Local {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Local {
+    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+        self.binding_id.cmp(&other.binding_id)
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct DeriveHelper {
     pub(crate) derive: MacroId,
@@ -5799,3 +6011,19 @@ pub enum DocLinkDef {
     Field(Field),
     SelfType(Trait),
 }
+
+fn push_ty_diagnostics(
+    db: &dyn HirDatabase,
+    acc: &mut Vec<AnyDiagnostic>,
+    diagnostics: Option<ThinArc<(), TyLoweringDiagnostic>>,
+    source_map: &TypesSourceMap,
+) {
+    if let Some(diagnostics) = diagnostics {
+        acc.extend(
+            diagnostics
+                .slice
+                .iter()
+                .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)),
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 9d3f8e5fba4..f9d3f9d07e6 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -34,7 +34,7 @@ use intern::Symbol;
 use itertools::Itertools;
 use rustc_hash::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
-use span::{EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
+use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
 use stdx::TupleExt;
 use syntax::{
     algo::skip_trivia_token,
@@ -42,6 +42,7 @@ use syntax::{
     AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
     TextSize,
 };
+use triomphe::Arc;
 
 use crate::{
     db::HirDatabase,
@@ -509,6 +510,22 @@ impl<'db> SemanticsImpl<'db> {
         self.with_ctx(|ctx| ctx.has_derives(adt))
     }
 
+    pub fn derive_helpers_in_scope(&self, adt: &ast::Adt) -> Option<Vec<(Symbol, Symbol)>> {
+        let sa = self.analyze_no_infer(adt.syntax())?;
+        let id = self.db.ast_id_map(sa.file_id).ast_id(adt);
+        let result = sa
+            .resolver
+            .def_map()
+            .derive_helpers_in_scope(InFile::new(sa.file_id, id))?
+            .iter()
+            .map(|(name, macro_, _)| {
+                let macro_name = Macro::from(*macro_).name(self.db).symbol().clone();
+                (name.symbol().clone(), macro_name)
+            })
+            .collect();
+        Some(result)
+    }
+
     pub fn derive_helper(&self, attr: &ast::Attr) -> Option<Vec<(Macro, MacroFileId)>> {
         let adt = attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it {
             ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
@@ -1500,6 +1517,10 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(path.syntax())?.resolve_path(self.db, path)
     }
 
+    pub fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<TypeParam> {
+        self.analyze(name.syntax())?.resolve_use_type_arg(name)
+    }
+
     pub fn resolve_mod_path(
         &self,
         scope: &SyntaxNode,
@@ -1973,10 +1994,16 @@ impl SemanticsScope<'_> {
     /// Resolve a path as-if it was written at the given scope. This is
     /// necessary a heuristic, as it doesn't take hygiene into account.
     pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
+        let root = ast_path.syntax().ancestors().last().unwrap();
+        let ast_id_map = Arc::new(AstIdMap::from_source(&root));
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let mut ctx =
-            LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
+        let mut ctx = LowerCtx::for_synthetic_ast(
+            self.db.upcast(),
+            ast_id_map,
+            &mut types_map,
+            &mut types_source_map,
+        );
         let path = Path::from_src(&mut ctx, ast_path.clone())?;
         resolve_hir_path(
             self.db,
@@ -2003,6 +2030,10 @@ impl SemanticsScope<'_> {
         )
     }
 
+    pub fn generic_def(&self) -> Option<crate::GenericDef> {
+        self.resolver.generic_def().map(|id| id.into())
+    }
+
     pub fn extern_crates(&self) -> impl Iterator<Item = (Name, Module)> + '_ {
         self.resolver.extern_crates_in_scope().map(|(name, id)| (name, Module { id }))
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index c16454cff68..4329a888b39 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -36,7 +36,7 @@ use hir_expand::{
 use hir_ty::{
     diagnostics::{
         record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
-        UnsafeExpr,
+        InsideUnsafeBlock,
     },
     lang_items::lang_items_for_bin_op,
     method_resolution, Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
@@ -642,6 +642,14 @@ impl SourceAnalyzer {
         }
     }
 
+    pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {
+        let name = name.as_name();
+        self.resolver
+            .all_generic_params()
+            .find_map(|(params, parent)| params.find_type_by_name(&name, *parent))
+            .map(crate::TypeParam::from)
+    }
+
     pub(crate) fn resolve_path(
         &self,
         db: &dyn HirDatabase,
@@ -939,8 +947,8 @@ impl SourceAnalyzer {
                         *def,
                         body,
                         expr_id,
-                        &mut |UnsafeExpr { inside_unsafe_block, .. }| {
-                            is_unsafe |= !inside_unsafe_block
+                        &mut |_, inside_unsafe_block, _| {
+                            is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No
                         },
                     )
                 };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 7f8ea44fb12..57df39d541e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -2318,4 +2318,49 @@ impl<'a> Test<'a, i32> for bool {
 "#,
         );
     }
+
+    #[test]
+    fn issue_17321() {
+        check_assist(
+            add_missing_impl_members,
+            r#"
+fn main() {}
+
+mod other_file_1 {
+    pub const SOME_CONSTANT: usize = 8;
+}
+
+mod other_file_2 {
+    use crate::other_file_1::SOME_CONSTANT;
+
+    pub trait Trait {
+        type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
+    }
+}
+
+pub struct MyStruct;
+
+impl other_file_2::Trait for MyStruct$0 {}"#,
+            r#"
+fn main() {}
+
+mod other_file_1 {
+    pub const SOME_CONSTANT: usize = 8;
+}
+
+mod other_file_2 {
+    use crate::other_file_1::SOME_CONSTANT;
+
+    pub trait Trait {
+        type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
+    }
+}
+
+pub struct MyStruct;
+
+impl other_file_2::Trait for MyStruct {
+    $0type Iter;
+}"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
index 17efbcbd6c9..0f6970d9403 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
@@ -1,8 +1,9 @@
 use either::Either;
 use ide_db::defs::{Definition, NameRefClass};
 use syntax::{
-    ast::{self, make, HasArgList, HasGenericArgs},
-    ted, AstNode,
+    ast::{self, make, syntax_factory::SyntaxFactory, HasArgList, HasGenericArgs},
+    syntax_editor::Position,
+    AstNode,
 };
 
 use crate::{
@@ -91,20 +92,34 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
                 AssistId("add_type_ascription", AssistKind::RefactorRewrite),
                 "Add `: _` before assignment operator",
                 ident.text_range(),
-                |edit| {
-                    let let_stmt = edit.make_mut(let_stmt);
+                |builder| {
+                    let mut editor = builder.make_editor(let_stmt.syntax());
 
                     if let_stmt.semicolon_token().is_none() {
-                        ted::append_child(let_stmt.syntax(), make::tokens::semicolon());
+                        editor.insert(
+                            Position::last_child_of(let_stmt.syntax()),
+                            make::tokens::semicolon(),
+                        );
                     }
 
                     let placeholder_ty = make::ty_placeholder().clone_for_update();
 
-                    let_stmt.set_ty(Some(placeholder_ty.clone()));
-
-                    if let Some(cap) = ctx.config.snippet_cap {
-                        edit.add_placeholder_snippet(cap, placeholder_ty);
+                    if let Some(pat) = let_stmt.pat() {
+                        let elements = vec![
+                            make::token(syntax::SyntaxKind::COLON).into(),
+                            make::token(syntax::SyntaxKind::WHITESPACE).into(),
+                            placeholder_ty.syntax().clone().into(),
+                        ];
+                        editor.insert_all(Position::after(pat.syntax()), elements);
+                        if let Some(cap) = ctx.config.snippet_cap {
+                            editor.add_annotation(
+                                placeholder_ty.syntax(),
+                                builder.make_placeholder_snippet(cap),
+                            );
+                        }
                     }
+
+                    builder.add_file_edits(ctx.file_id(), editor);
                 },
             )?
         } else {
@@ -123,38 +138,58 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
         AssistId("add_turbo_fish", AssistKind::RefactorRewrite),
         "Add `::<>`",
         ident.text_range(),
-        |edit| {
-            edit.trigger_parameter_hints();
+        |builder| {
+            builder.trigger_parameter_hints();
+
+            let make = SyntaxFactory::new();
+            let mut editor = match &turbofish_target {
+                Either::Left(it) => builder.make_editor(it.syntax()),
+                Either::Right(it) => builder.make_editor(it.syntax()),
+            };
+
+            let fish_head = get_fish_head(&make, number_of_arguments);
 
-            let new_arg_list = match turbofish_target {
+            match turbofish_target {
                 Either::Left(path_segment) => {
-                    edit.make_mut(path_segment).get_or_create_generic_arg_list()
+                    if let Some(generic_arg_list) = path_segment.generic_arg_list() {
+                        editor.replace(generic_arg_list.syntax(), fish_head.syntax());
+                    } else {
+                        editor.insert(
+                            Position::last_child_of(path_segment.syntax()),
+                            fish_head.syntax(),
+                        );
+                    }
                 }
                 Either::Right(method_call) => {
-                    edit.make_mut(method_call).get_or_create_generic_arg_list()
+                    if let Some(generic_arg_list) = method_call.generic_arg_list() {
+                        editor.replace(generic_arg_list.syntax(), fish_head.syntax());
+                    } else {
+                        let position = if let Some(arg_list) = method_call.arg_list() {
+                            Position::before(arg_list.syntax())
+                        } else {
+                            Position::last_child_of(method_call.syntax())
+                        };
+                        editor.insert(position, fish_head.syntax());
+                    }
                 }
             };
 
-            let fish_head = get_fish_head(number_of_arguments).clone_for_update();
-
-            // Note: we need to replace the `new_arg_list` instead of being able to use something like
-            // `GenericArgList::add_generic_arg` as `PathSegment::get_or_create_generic_arg_list`
-            // always creates a non-turbofish form generic arg list.
-            ted::replace(new_arg_list.syntax(), fish_head.syntax());
-
             if let Some(cap) = ctx.config.snippet_cap {
                 for arg in fish_head.generic_args() {
-                    edit.add_placeholder_snippet(cap, arg)
+                    editor.add_annotation(arg.syntax(), builder.make_placeholder_snippet(cap));
                 }
             }
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
 
 /// This will create a turbofish generic arg list corresponding to the number of arguments
-fn get_fish_head(number_of_arguments: usize) -> ast::GenericArgList {
+fn get_fish_head(make: &SyntaxFactory, number_of_arguments: usize) -> ast::GenericArgList {
     let args = (0..number_of_arguments).map(|_| make::type_arg(make::ty_placeholder()).into());
-    make::turbofish_generic_arg_list(args)
+    make.turbofish_generic_arg_list(args)
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
index 605fd140523..f699899066b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
@@ -512,9 +512,11 @@ fn make_bool_enum(make_pub: bool) -> ast::Enum {
     let enum_def = make::enum_(
         if make_pub { Some(make::visibility_pub()) } else { None },
         make::name("Bool"),
+        None,
+        None,
         make::variant_list(vec![
-            make::variant(make::name("True"), None),
-            make::variant(make::name("False"), None),
+            make::variant(None, make::name("True"), None, None),
+            make::variant(None, make::name("False"), None, None),
         ]),
     )
     .clone_for_update();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index ad0be896450..6937d33ebc1 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -18,6 +18,7 @@ use ide_db::{
     },
     FxIndexSet, RootDatabase,
 };
+use itertools::Itertools;
 use syntax::{
     ast::{
         self, edit::IndentLevel, edit_in_place::Indent, AstNode, AstToken, HasGenericParams,
@@ -114,8 +115,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 return;
             }
 
-            let params =
-                body.extracted_function_params(ctx, &container_info, locals_used.iter().copied());
+            let params = body.extracted_function_params(ctx, &container_info, locals_used);
 
             let name = make_function_name(&semantics_scope);
 
@@ -1067,9 +1067,11 @@ impl FunctionBody {
         &self,
         ctx: &AssistContext<'_>,
         container_info: &ContainerInfo,
-        locals: impl Iterator<Item = Local>,
+        locals: FxIndexSet<Local>,
     ) -> Vec<Param> {
         locals
+            .into_iter()
+            .sorted()
             .map(|local| (local, local.primary_source(ctx.db())))
             .filter(|(_, src)| is_defined_outside_of_body(ctx, self, src))
             .filter_map(|(local, src)| match src.into_ident_pat() {
@@ -3167,11 +3169,11 @@ fn foo() {
     let mut c = C { p: P { n: 0 } };
     let mut v = C { p: P { n: 0 } };
     let u = C { p: P { n: 0 } };
-    fun_name(&mut c, &u, &mut v);
+    fun_name(&mut c, &mut v, &u);
     let m = c.p.n + v.p.n + u.p.n;
 }
 
-fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
+fn $0fun_name(c: &mut C, v: &mut C, u: &C) {
     c.p.n += u.p.n;
     let r = &mut v.p.n;
 }
@@ -5602,10 +5604,10 @@ fn parent(factor: i32) {
 fn parent(factor: i32) {
     let v = &[1, 2, 3];
 
-    fun_name(v, factor);
+    fun_name(factor, v);
 }
 
-fn $0fun_name(v: &[i32; 3], factor: i32) {
+fn $0fun_name(factor: i32, v: &[i32; 3]) {
     v.iter().map(|it| it * factor);
 }
 "#,
@@ -5786,11 +5788,11 @@ struct Struct<T: Into<i32>>(T);
 impl <T: Into<i32> + Copy> Struct<T> {
     fn func<V: Into<i32>>(&self, v: V) -> i32 {
         let t = self.0;
-        fun_name(t, v)
+        fun_name(v, t)
     }
 }
 
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
+fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(v: V, t: T) -> i32 {
     t.into() + v.into()
 }
 "#,
@@ -5815,11 +5817,11 @@ struct Struct<T: Into<i32>, U: Debug>(T, U);
 impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
     fn func<V: Into<i32>>(&self, v: V) -> i32 {
         let t = self.0;
-        fun_name(t, v)
+        fun_name(v, t)
     }
 }
 
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
+fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(v: V, t: T) -> i32 {
     t.into() + v.into()
 }
 "#,
@@ -5844,11 +5846,11 @@ struct Struct<T>(T) where T: Into<i32>;
 impl <T> Struct<T> where T: Into<i32> + Copy {
     fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
         let t = self.0;
-        fun_name(t, v)
+        fun_name(v, t)
     }
 }
 
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
+fn $0fun_name<T, V>(v: V, t: T) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
     t.into() + v.into()
 }
 "#,
@@ -5873,11 +5875,11 @@ struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
 impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
     fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
         let t = self.0;
-        fun_name(t, v)
+        fun_name(v, t)
     }
 }
 
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
+fn $0fun_name<T, V>(v: V, t: T) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
     t.into() + v.into()
 }
 "#,
@@ -6107,6 +6109,31 @@ fn $0fun_name() -> i32 {
     }
 
     #[test]
+    fn sort_params_in_order() {
+        check_assist(
+            extract_function,
+            r#"
+fn existing(a: i32, b: i32, c: i32) {
+    let x = 32;
+
+    let p = $0x + b + c + a$0;
+}
+"#,
+            r#"
+fn existing(a: i32, b: i32, c: i32) {
+    let x = 32;
+
+    let p = fun_name(a, b, c, x);
+}
+
+fn $0fun_name(a: i32, b: i32, c: i32, x: i32) -> i32 {
+    x + b + c + a
+}
+"#,
+        );
+    }
+
+    #[test]
     fn in_left_curly_is_not_applicable() {
         cov_mark::check!(extract_function_in_braces_is_not_applicable);
         check_assist_not_applicable(extract_function, r"fn foo() { $0}$0");
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs
index 8b46a23f9a6..818a868fe34 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_binexpr.rs
@@ -1,4 +1,7 @@
-use syntax::ast::{self, AstNode, BinExpr};
+use syntax::{
+    ast::{self, syntax_factory::SyntaxFactory, AstNode, BinExpr},
+    SyntaxKind, T,
+};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -19,22 +22,17 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // ```
 pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let expr = ctx.find_node_at_offset::<BinExpr>()?;
-    let rhs = expr.rhs()?.syntax().clone();
-    let lhs = expr.lhs()?.syntax().clone();
-
-    let lhs = if let Some(bin_expr) = BinExpr::cast(lhs.clone()) {
-        if bin_expr.op_kind() == expr.op_kind() {
-            bin_expr.rhs()?.syntax().clone()
-        } else {
-            lhs
-        }
-    } else {
-        lhs
+    let lhs = expr.lhs()?;
+    let rhs = expr.rhs()?;
+
+    let lhs = match &lhs {
+        ast::Expr::BinExpr(bin_expr) if bin_expr.op_kind() == expr.op_kind() => bin_expr.rhs()?,
+        _ => lhs,
     };
 
-    let op_range = expr.op_token()?.text_range();
+    let op_token = expr.op_token()?;
     // The assist should be applied only if the cursor is on the operator
-    let cursor_in_range = op_range.contains_range(ctx.selection_trimmed());
+    let cursor_in_range = op_token.text_range().contains_range(ctx.selection_trimmed());
     if !cursor_in_range {
         return None;
     }
@@ -47,13 +45,17 @@ pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
     acc.add(
         AssistId("flip_binexpr", AssistKind::RefactorRewrite),
         "Flip binary expression",
-        op_range,
-        |edit| {
-            if let FlipAction::FlipAndReplaceOp(new_op) = action {
-                edit.replace(op_range, new_op);
-            }
-            edit.replace(lhs.text_range(), rhs.text());
-            edit.replace(rhs.text_range(), lhs.text());
+        op_token.text_range(),
+        |builder| {
+            let mut editor = builder.make_editor(&expr.syntax().parent().unwrap());
+            let make = SyntaxFactory::new();
+            if let FlipAction::FlipAndReplaceOp(binary_op) = action {
+                editor.replace(op_token, make.token(binary_op))
+            };
+            editor.replace(lhs.syntax(), rhs.syntax());
+            editor.replace(rhs.syntax(), lhs.syntax());
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
@@ -62,7 +64,7 @@ enum FlipAction {
     // Flip the expression
     Flip,
     // Flip the expression and replace the operator with this string
-    FlipAndReplaceOp(&'static str),
+    FlipAndReplaceOp(SyntaxKind),
     // Do not flip the expression
     DontFlip,
 }
@@ -73,10 +75,10 @@ impl From<ast::BinaryOp> for FlipAction {
             ast::BinaryOp::Assignment { .. } => FlipAction::DontFlip,
             ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering, strict }) => {
                 let rev_op = match (ordering, strict) {
-                    (ast::Ordering::Less, true) => ">",
-                    (ast::Ordering::Less, false) => ">=",
-                    (ast::Ordering::Greater, true) => "<",
-                    (ast::Ordering::Greater, false) => "<=",
+                    (ast::Ordering::Less, true) => T![>],
+                    (ast::Ordering::Less, false) => T![>=],
+                    (ast::Ordering::Greater, true) => T![<],
+                    (ast::Ordering::Greater, false) => T![<=],
                 };
                 FlipAction::FlipAndReplaceOp(rev_op)
             }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
index af2c2c759ec..95e035c0537 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
@@ -1,7 +1,8 @@
-use ide_db::base_db::SourceDatabase;
-use syntax::TextSize;
 use syntax::{
-    algo::non_trivia_sibling, ast, AstNode, Direction, SyntaxKind, SyntaxToken, TextRange, T,
+    algo::non_trivia_sibling,
+    ast::{self, syntax_factory::SyntaxFactory},
+    syntax_editor::{Element, SyntaxMapping},
+    AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxToken, T,
 };
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -25,8 +26,6 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
     let comma = ctx.find_token_syntax_at_offset(T![,])?;
     let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
     let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
-    let (mut prev_text, mut next_text) = (prev.to_string(), next.to_string());
-    let (mut prev_range, mut next_range) = (prev.text_range(), next.text_range());
 
     // Don't apply a "flip" in case of a last comma
     // that typically comes before punctuation
@@ -40,53 +39,84 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
         return None;
     }
 
-    if let Some(parent) = comma.parent().and_then(ast::TokenTree::cast) {
-        // An attribute. It often contains a path followed by a token tree (e.g. `align(2)`), so we have
-        // to be smarter.
-        let prev_start =
-            match comma.siblings_with_tokens(Direction::Prev).skip(1).find(|it| it.kind() == T![,])
-            {
-                Some(it) => position_after_token(it.as_token().unwrap()),
-                None => position_after_token(&parent.left_delimiter_token()?),
-            };
-        let prev_end = prev.text_range().end();
-        let next_start = next.text_range().start();
-        let next_end =
-            match comma.siblings_with_tokens(Direction::Next).skip(1).find(|it| it.kind() == T![,])
-            {
-                Some(it) => position_before_token(it.as_token().unwrap()),
-                None => position_before_token(&parent.right_delimiter_token()?),
-            };
-        prev_range = TextRange::new(prev_start, prev_end);
-        next_range = TextRange::new(next_start, next_end);
-        let file_text = ctx.db().file_text(ctx.file_id().file_id());
-        prev_text = file_text[prev_range].to_owned();
-        next_text = file_text[next_range].to_owned();
-    }
+    let prev = match prev {
+        SyntaxElement::Node(node) => node.syntax_element(),
+        _ => prev,
+    };
+    let next = match next {
+        SyntaxElement::Node(node) => node.syntax_element(),
+        _ => next,
+    };
 
     acc.add(
         AssistId("flip_comma", AssistKind::RefactorRewrite),
         "Flip comma",
         comma.text_range(),
-        |edit| {
-            edit.replace(prev_range, next_text);
-            edit.replace(next_range, prev_text);
+        |builder| {
+            let parent = comma.parent().unwrap();
+            let mut editor = builder.make_editor(&parent);
+
+            if let Some(parent) = ast::TokenTree::cast(parent) {
+                // An attribute. It often contains a path followed by a
+                // token tree (e.g. `align(2)`), so we have to be smarter.
+                let (new_tree, mapping) = flip_tree(parent.clone(), comma);
+                editor.replace(parent.syntax(), new_tree.syntax());
+                editor.add_mappings(mapping);
+            } else {
+                editor.replace(prev.clone(), next.clone());
+                editor.replace(next.clone(), prev.clone());
+            }
+
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
 
-fn position_before_token(token: &SyntaxToken) -> TextSize {
-    match non_trivia_sibling(token.clone().into(), Direction::Prev) {
-        Some(prev_token) => prev_token.text_range().end(),
-        None => token.text_range().start(),
-    }
-}
-
-fn position_after_token(token: &SyntaxToken) -> TextSize {
-    match non_trivia_sibling(token.clone().into(), Direction::Next) {
-        Some(prev_token) => prev_token.text_range().start(),
-        None => token.text_range().end(),
-    }
+fn flip_tree(tree: ast::TokenTree, comma: SyntaxToken) -> (ast::TokenTree, SyntaxMapping) {
+    let mut tree_iter = tree.token_trees_and_tokens();
+    let before: Vec<_> =
+        tree_iter.by_ref().take_while(|it| it.as_token() != Some(&comma)).collect();
+    let after: Vec<_> = tree_iter.collect();
+
+    let not_ws = |element: &NodeOrToken<_, SyntaxToken>| match element {
+        NodeOrToken::Token(token) => token.kind() != SyntaxKind::WHITESPACE,
+        NodeOrToken::Node(_) => true,
+    };
+
+    let is_comma = |element: &NodeOrToken<_, SyntaxToken>| match element {
+        NodeOrToken::Token(token) => token.kind() == T![,],
+        NodeOrToken::Node(_) => false,
+    };
+
+    let prev_start_untrimmed = match before.iter().rposition(is_comma) {
+        Some(pos) => pos + 1,
+        None => 1,
+    };
+    let prev_end = 1 + before.iter().rposition(not_ws).unwrap();
+    let prev_start = prev_start_untrimmed
+        + before[prev_start_untrimmed..prev_end].iter().position(not_ws).unwrap();
+
+    let next_start = after.iter().position(not_ws).unwrap();
+    let next_end_untrimmed = match after.iter().position(is_comma) {
+        Some(pos) => pos,
+        None => after.len() - 1,
+    };
+    let next_end = 1 + after[..next_end_untrimmed].iter().rposition(not_ws).unwrap();
+
+    let result = [
+        &before[1..prev_start],
+        &after[next_start..next_end],
+        &before[prev_end..],
+        &[NodeOrToken::Token(comma)],
+        &after[..next_start],
+        &before[prev_start..prev_end],
+        &after[next_end..after.len() - 1],
+    ]
+    .concat();
+
+    let make = SyntaxFactory::new();
+    let new_token_tree = make.token_tree(tree.left_delimiter_token().unwrap().kind(), result);
+    (new_token_tree, make.finish_with_mappings())
 }
 
 #[cfg(test)]
@@ -147,4 +177,9 @@ mod tests {
             r#"#[foo(bar, qux, baz(1 + 1), other)] struct Foo;"#,
         );
     }
+
+    #[test]
+    fn flip_comma_attribute_incomplete() {
+        check_assist_not_applicable(flip_comma, r#"#[repr(align(2),$0)] struct Foo;"#);
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
index 70b5efcb645..298e5bd82c9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
@@ -23,11 +23,11 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
     let plus = ctx.find_token_syntax_at_offset(T![+])?;
 
     // Make sure we're in a `TypeBoundList`
-    ast::TypeBoundList::cast(plus.parent()?)?;
+    let parent = ast::TypeBoundList::cast(plus.parent()?)?;
 
     let (before, after) = (
-        non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
-        non_trivia_sibling(plus.clone().into(), Direction::Next)?,
+        non_trivia_sibling(plus.clone().into(), Direction::Prev)?.into_node()?,
+        non_trivia_sibling(plus.clone().into(), Direction::Next)?.into_node()?,
     );
 
     let target = plus.text_range();
@@ -35,9 +35,11 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
         AssistId("flip_trait_bound", AssistKind::RefactorRewrite),
         "Flip trait bounds",
         target,
-        |edit| {
-            edit.replace(before.text_range(), after.to_string());
-            edit.replace(after.text_range(), before.to_string());
+        |builder| {
+            let mut editor = builder.make_editor(parent.syntax());
+            editor.replace(before.clone(), after.clone());
+            editor.replace(after, before);
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
index c5c70c9f8eb..862be791d17 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
@@ -88,7 +88,7 @@ pub(crate) fn generate_documentation_template(
 // /// # Examples
 // ///
 // /// ```
-// /// use test::add;
+// /// use ra_test_fixture::add;
 // ///
 // /// assert_eq!(add(a, b), );
 // /// ```
@@ -596,7 +596,7 @@ pub fn noop_with_param(_a: i32) {}
 /// # Examples
 ///
 /// ```
-/// use test::noop_with_param;
+/// use ra_test_fixture::noop_with_param;
 ///
 /// noop_with_param(_a);
 /// ```
@@ -641,7 +641,7 @@ pub unsafe fn noop_unsafe() {}
 /// # Examples
 ///
 /// ```
-/// use test::noop_unsafe;
+/// use ra_test_fixture::noop_unsafe;
 ///
 /// unsafe { noop_unsafe() };
 /// ```
@@ -758,7 +758,7 @@ pub fn returns_a_value$0() -> i32 {
 /// # Examples
 ///
 /// ```
-/// use test::returns_a_value;
+/// use ra_test_fixture::returns_a_value;
 ///
 /// assert_eq!(returns_a_value(), );
 /// ```
@@ -807,7 +807,7 @@ pub fn modifies_a_value$0(a: &mut i32) {
 /// # Examples
 ///
 /// ```
-/// use test::modifies_a_value;
+/// use ra_test_fixture::modifies_a_value;
 ///
 /// let mut a = ;
 /// modifies_a_value(&mut a);
@@ -836,7 +836,7 @@ pub fn sum3$0(a: i32, b: i32, c: i32) -> i32 {
 /// # Examples
 ///
 /// ```
-/// use test::sum3;
+/// use ra_test_fixture::sum3;
 ///
 /// let result = sum3(a, b, c);
 /// assert_eq!(result, );
@@ -868,7 +868,7 @@ pub mod a {
         /// # Examples
         ///
         /// ```
-        /// use test::a::b::noop;
+        /// use ra_test_fixture::a::b::noop;
         ///
         /// noop();
         /// ```
@@ -898,7 +898,7 @@ impl MyStruct {
     /// # Examples
     ///
     /// ```
-    /// use test::MyStruct;
+    /// use ra_test_fixture::MyStruct;
     ///
     /// MyStruct::noop();
     /// ```
@@ -1169,7 +1169,7 @@ impl<T> MyGenericStruct<T> {
     /// # Examples
     ///
     /// ```
-    /// use test::MyGenericStruct;
+    /// use ra_test_fixture::MyGenericStruct;
     ///
     /// let my_generic_struct = ;
     /// my_generic_struct.consume();
@@ -1199,7 +1199,7 @@ impl<T> MyGenericStruct<T> {
     /// # Examples
     ///
     /// ```
-    /// use test::MyGenericStruct;
+    /// use ra_test_fixture::MyGenericStruct;
     ///
     /// let mut my_generic_struct = ;
     /// my_generic_struct.modify(new_value);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
index 5d584591210..bb08cb904ea 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_variant.rs
@@ -1,7 +1,7 @@
 use hir::{HasSource, HirDisplay, InRealFile};
 use ide_db::assists::{AssistId, AssistKind};
 use syntax::{
-    ast::{self, make, HasArgList},
+    ast::{self, syntax_factory::SyntaxFactory, HasArgList},
     match_ast, AstNode, SyntaxNode,
 };
 
@@ -33,7 +33,7 @@ use crate::assist_context::{AssistContext, Assists};
 // ```
 pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let path: ast::Path = ctx.find_node_at_offset()?;
-    let parent = path_parent(&path)?;
+    let parent = PathParent::new(&path)?;
 
     if ctx.sema.resolve_path(&path).is_some() {
         // No need to generate anything if the path resolves
@@ -46,14 +46,32 @@ pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>)
         return None;
     }
 
-    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
+    let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
         ctx.sema.resolve_path(&path.qualifier()?)
-    {
-        let target = path.syntax().text_range();
-        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref, parent);
-    }
+    else {
+        return None;
+    };
 
-    None
+    let target = path.syntax().text_range();
+    let name_ref: &ast::NameRef = &name_ref;
+    let db = ctx.db();
+    let InRealFile { file_id, value: enum_node } = e.source(db)?.original_ast_node_rooted(db)?;
+
+    acc.add(
+        AssistId("generate_enum_variant", AssistKind::Generate),
+        "Generate variant",
+        target,
+        |builder| {
+            let mut editor = builder.make_editor(enum_node.syntax());
+            let make = SyntaxFactory::new();
+            let field_list = parent.make_field_list(ctx, &make);
+            let variant = make.variant(None, make.name(&name_ref.text()), field_list, None);
+            if let Some(it) = enum_node.variant_list() {
+                it.add_variant(&mut editor, &variant);
+            }
+            builder.add_file_edits(file_id, editor);
+        },
+    )
 }
 
 #[derive(Debug)]
@@ -65,6 +83,20 @@ enum PathParent {
 }
 
 impl PathParent {
+    fn new(path: &ast::Path) -> Option<Self> {
+        let parent = path.syntax().parent()?;
+
+        match_ast! {
+            match parent {
+                ast::PathExpr(it) => Some(PathParent::PathExpr(it)),
+                ast::RecordExpr(it) => Some(PathParent::RecordExpr(it)),
+                ast::PathPat(it) => Some(PathParent::PathPat(it)),
+                ast::UseTree(it) => Some(PathParent::UseTree(it)),
+                _ => None
+            }
+        }
+    }
+
     fn syntax(&self) -> &SyntaxNode {
         match self {
             PathParent::PathExpr(it) => it.syntax(),
@@ -74,97 +106,49 @@ impl PathParent {
         }
     }
 
-    fn make_field_list(&self, ctx: &AssistContext<'_>) -> Option<ast::FieldList> {
+    fn make_field_list(
+        &self,
+        ctx: &AssistContext<'_>,
+        make: &SyntaxFactory,
+    ) -> Option<ast::FieldList> {
         let scope = ctx.sema.scope(self.syntax())?;
 
         match self {
             PathParent::PathExpr(it) => {
-                if let Some(call_expr) = it.syntax().parent().and_then(ast::CallExpr::cast) {
-                    make_tuple_field_list(call_expr, ctx, &scope)
-                } else {
-                    None
-                }
+                let call_expr = ast::CallExpr::cast(it.syntax().parent()?)?;
+                let args = call_expr.arg_list()?.args();
+                let tuple_fields = args.map(|arg| {
+                    let ty =
+                        expr_ty(ctx, make, arg, &scope).unwrap_or_else(|| make.ty_infer().into());
+                    make.tuple_field(None, ty)
+                });
+                Some(make.tuple_field_list(tuple_fields).into())
+            }
+            PathParent::RecordExpr(it) => {
+                let fields = it.record_expr_field_list()?.fields();
+                let record_fields = fields.map(|field| {
+                    let name = name_from_field(make, &field);
+
+                    let ty = field
+                        .expr()
+                        .and_then(|it| expr_ty(ctx, make, it, &scope))
+                        .unwrap_or_else(|| make.ty_infer().into());
+
+                    make.record_field(None, name, ty)
+                });
+                Some(make.record_field_list(record_fields).into())
             }
-            PathParent::RecordExpr(it) => make_record_field_list(it, ctx, &scope),
             PathParent::UseTree(_) | PathParent::PathPat(_) => None,
         }
     }
 }
 
-fn path_parent(path: &ast::Path) -> Option<PathParent> {
-    let parent = path.syntax().parent()?;
-
-    match_ast! {
-        match parent {
-            ast::PathExpr(it) => Some(PathParent::PathExpr(it)),
-            ast::RecordExpr(it) => Some(PathParent::RecordExpr(it)),
-            ast::PathPat(it) => Some(PathParent::PathPat(it)),
-            ast::UseTree(it) => Some(PathParent::UseTree(it)),
-            _ => None
-        }
-    }
-}
-
-fn add_variant_to_accumulator(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-    target: syntax::TextRange,
-    adt: hir::Enum,
-    name_ref: &ast::NameRef,
-    parent: PathParent,
-) -> Option<()> {
-    let db = ctx.db();
-    let InRealFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node_rooted(db)?;
-
-    acc.add(
-        AssistId("generate_enum_variant", AssistKind::Generate),
-        "Generate variant",
-        target,
-        |builder| {
-            builder.edit_file(file_id.file_id());
-            let node = builder.make_mut(enum_node);
-            let variant = make_variant(ctx, name_ref, parent);
-            if let Some(it) = node.variant_list() {
-                it.add_variant(variant.clone_for_update())
-            }
-        },
-    )
-}
-
-fn make_variant(
-    ctx: &AssistContext<'_>,
-    name_ref: &ast::NameRef,
-    parent: PathParent,
-) -> ast::Variant {
-    let field_list = parent.make_field_list(ctx);
-    make::variant(make::name(&name_ref.text()), field_list)
-}
-
-fn make_record_field_list(
-    record: &ast::RecordExpr,
-    ctx: &AssistContext<'_>,
-    scope: &hir::SemanticsScope<'_>,
-) -> Option<ast::FieldList> {
-    let fields = record.record_expr_field_list()?.fields();
-    let record_fields = fields.map(|field| {
-        let name = name_from_field(&field);
-
-        let ty = field
-            .expr()
-            .and_then(|it| expr_ty(ctx, it, scope))
-            .unwrap_or_else(make::ty_placeholder);
-
-        make::record_field(None, name, ty)
-    });
-    Some(make::record_field_list(record_fields).into())
-}
-
-fn name_from_field(field: &ast::RecordExprField) -> ast::Name {
+fn name_from_field(make: &SyntaxFactory, field: &ast::RecordExprField) -> ast::Name {
     let text = match field.name_ref() {
         Some(it) => it.to_string(),
         None => name_from_field_shorthand(field).unwrap_or("unknown".to_owned()),
     };
-    make::name(&text)
+    make.name(&text)
 }
 
 fn name_from_field_shorthand(field: &ast::RecordExprField) -> Option<String> {
@@ -175,27 +159,15 @@ fn name_from_field_shorthand(field: &ast::RecordExprField) -> Option<String> {
     Some(path.as_single_name_ref()?.to_string())
 }
 
-fn make_tuple_field_list(
-    call_expr: ast::CallExpr,
-    ctx: &AssistContext<'_>,
-    scope: &hir::SemanticsScope<'_>,
-) -> Option<ast::FieldList> {
-    let args = call_expr.arg_list()?.args();
-    let tuple_fields = args.map(|arg| {
-        let ty = expr_ty(ctx, arg, scope).unwrap_or_else(make::ty_placeholder);
-        make::tuple_field(None, ty)
-    });
-    Some(make::tuple_field_list(tuple_fields).into())
-}
-
 fn expr_ty(
     ctx: &AssistContext<'_>,
+    make: &SyntaxFactory,
     arg: ast::Expr,
     scope: &hir::SemanticsScope<'_>,
 ) -> Option<ast::Type> {
     let ty = ctx.sema.type_of_expr(&arg).map(|it| it.adjusted())?;
     let text = ty.display_source_code(ctx.db(), scope.module().into(), false).ok()?;
-    Some(make::ty(&text))
+    Some(make.ty(&text))
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs
index bf6ac1719f3..8c276415bb1 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs
@@ -1,9 +1,6 @@
 use ide_db::syntax_helpers::suggest_name;
 use itertools::Itertools;
-use syntax::{
-    ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, HasGenericParams, HasName},
-    ted,
-};
+use syntax::ast::{self, syntax_factory::SyntaxFactory, AstNode, HasGenericParams, HasName};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -25,42 +22,42 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_>
 
     let type_bound_list = impl_trait_type.type_bound_list()?;
 
+    let make = SyntaxFactory::new();
     let target = fn_.syntax().text_range();
     acc.add(
         AssistId("introduce_named_generic", AssistKind::RefactorRewrite),
         "Replace impl trait with generic",
         target,
-        |edit| {
-            let impl_trait_type = edit.make_mut(impl_trait_type);
-            let fn_ = edit.make_mut(fn_);
-            let fn_generic_param_list = fn_.get_or_create_generic_param_list();
-
-            let existing_names = fn_generic_param_list
-                .generic_params()
-                .flat_map(|param| match param {
-                    ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()),
-                    p => Some(p.to_string()),
-                })
-                .collect_vec();
+        |builder| {
+            let mut editor = builder.make_editor(fn_.syntax());
+
+            let existing_names = match fn_.generic_param_list() {
+                Some(generic_param_list) => generic_param_list
+                    .generic_params()
+                    .flat_map(|param| match param {
+                        ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()),
+                        p => Some(p.to_string()),
+                    })
+                    .collect_vec(),
+                None => Vec::new(),
+            };
             let type_param_name = suggest_name::NameGenerator::new_with_names(
                 existing_names.iter().map(|s| s.as_str()),
             )
             .for_impl_trait_as_generic(&impl_trait_type);
 
-            let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list))
-                .clone_for_update();
-            let new_ty = make::ty(&type_param_name).clone_for_update();
+            let type_param = make.type_param(make.name(&type_param_name), Some(type_bound_list));
+            let new_ty = make.ty(&type_param_name);
 
-            ted::replace(impl_trait_type.syntax(), new_ty.syntax());
-            fn_generic_param_list.add_generic_param(type_param.into());
+            editor.replace(impl_trait_type.syntax(), new_ty.syntax());
+            editor.add_generic_param(&fn_, type_param.clone().into());
 
             if let Some(cap) = ctx.config.snippet_cap {
-                if let Some(generic_param) =
-                    fn_.generic_param_list().and_then(|it| it.generic_params().last())
-                {
-                    edit.add_tabstop_before(cap, generic_param);
-                }
+                editor.add_annotation(type_param.syntax(), builder.make_tabstop_before(cap));
             }
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
index 4d3e85ab1b2..972303c2a04 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
@@ -92,10 +92,9 @@ fn replace<T: AstNode + PartialEq>(
     fields: impl Iterator<Item = T>,
     sorted_fields: impl IntoIterator<Item = T>,
 ) {
-    fields.zip(sorted_fields).for_each(|(field, sorted_field)| {
-        // FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us
-        editor.replace(field.syntax(), sorted_field.syntax().clone_for_update())
-    });
+    fields
+        .zip(sorted_fields)
+        .for_each(|(field, sorted_field)| editor.replace(field.syntax(), sorted_field.syntax()));
 }
 
 fn compute_fields_ranks(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
index d7fa8826125..eb1d538f874 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
@@ -101,10 +101,10 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         |builder| {
             let mut editor = builder.make_editor(&parent_node);
 
-            assoc_items.into_iter().zip(sorted).for_each(|(old, new)| {
-                // FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us
-                editor.replace(old.syntax(), new.clone_for_update().syntax())
-            });
+            assoc_items
+                .into_iter()
+                .zip(sorted)
+                .for_each(|(old, new)| editor.replace(old.syntax(), new.syntax()));
 
             builder.add_file_edits(ctx.file_id(), editor);
         },
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs
index 64e30b18345..54e16d4d80a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs
@@ -4,7 +4,7 @@ use itertools::Itertools;
 
 use syntax::{
     ast::{self, HasName},
-    ted, AstNode, TextRange,
+    AstNode, SyntaxNode,
 };
 
 use crate::{utils::get_methods, AssistContext, AssistId, AssistKind, Assists};
@@ -114,7 +114,7 @@ trait AddRewrite {
         label: &str,
         old: Vec<T>,
         new: Vec<T>,
-        target: TextRange,
+        target: &SyntaxNode,
     ) -> Option<()>;
 }
 
@@ -124,15 +124,22 @@ impl AddRewrite for Assists {
         label: &str,
         old: Vec<T>,
         new: Vec<T>,
-        target: TextRange,
+        target: &SyntaxNode,
     ) -> Option<()> {
-        self.add(AssistId("sort_items", AssistKind::RefactorRewrite), label, target, |builder| {
-            let mutable: Vec<T> = old.into_iter().map(|it| builder.make_mut(it)).collect();
-            mutable
-                .into_iter()
-                .zip(new)
-                .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax()));
-        })
+        self.add(
+            AssistId("sort_items", AssistKind::RefactorRewrite),
+            label,
+            target.text_range(),
+            |builder| {
+                let mut editor = builder.make_editor(target);
+
+                old.into_iter()
+                    .zip(new)
+                    .for_each(|(old, new)| editor.replace(old.syntax(), new.syntax()));
+
+                builder.add_file_edits(builder.file_id, editor)
+            },
+        )
     }
 }
 
@@ -167,7 +174,7 @@ fn add_sort_methods_assist(
         return None;
     }
 
-    acc.add_rewrite("Sort methods alphabetically", methods, sorted, item_list.syntax().text_range())
+    acc.add_rewrite("Sort methods alphabetically", methods, sorted, item_list.syntax())
 }
 
 fn add_sort_fields_assist(
@@ -182,12 +189,7 @@ fn add_sort_fields_assist(
         return None;
     }
 
-    acc.add_rewrite(
-        "Sort fields alphabetically",
-        fields,
-        sorted,
-        record_field_list.syntax().text_range(),
-    )
+    acc.add_rewrite("Sort fields alphabetically", fields, sorted, record_field_list.syntax())
 }
 
 fn add_sort_variants_assist(acc: &mut Assists, variant_list: ast::VariantList) -> Option<()> {
@@ -199,12 +201,7 @@ fn add_sort_variants_assist(acc: &mut Assists, variant_list: ast::VariantList) -
         return None;
     }
 
-    acc.add_rewrite(
-        "Sort variants alphabetically",
-        variants,
-        sorted,
-        variant_list.syntax().text_range(),
-    )
+    acc.add_rewrite("Sort variants alphabetically", variants, sorted, variant_list.syntax())
 }
 
 fn sort_by_name<T: HasName + Clone>(initial: &[T]) -> Vec<T> {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index eef4da55e94..69ea200db16 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -1392,7 +1392,7 @@ pub fn add(a: i32, b: i32) -> i32 { a + b }
 /// # Examples
 ///
 /// ```
-/// use test::add;
+/// use ra_test_fixture::add;
 ///
 /// assert_eq!(add(a, b), );
 /// ```
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
index d0b489c4e83..cf5427bae38 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
@@ -86,10 +86,21 @@ pub(crate) fn complete_attribute_path(
     acc: &mut Completions,
     ctx: &CompletionContext<'_>,
     path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
-    &AttrCtx { kind, annotated_item_kind }: &AttrCtx,
+    &AttrCtx { kind, annotated_item_kind, ref derive_helpers }: &AttrCtx,
 ) {
     let is_inner = kind == AttrKind::Inner;
 
+    for (derive_helper, derive_name) in derive_helpers {
+        let mut item = CompletionItem::new(
+            SymbolKind::Attribute,
+            ctx.source_range(),
+            derive_helper.as_str(),
+            ctx.edition,
+        );
+        item.detail(format!("derive helper of `{derive_name}`"));
+        item.add_to(acc, ctx.db);
+    }
+
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
index b0e417e6b33..847fa4cf889 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
@@ -38,7 +38,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
     "system-unwind",
     "rust-intrinsic",
     "rust-call",
-    "platform-intrinsic",
     "unadjusted",
 ];
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
index 9efc52428ef..0692446381b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
@@ -8,7 +8,6 @@
 //! show up for normal completions, or they won't show completions other than lifetimes depending
 //! on the fixture input.
 use hir::{sym, Name, ScopeDef};
-use syntax::{ast, ToSmolStr, TokenText};
 
 use crate::{
     completions::Completions,
@@ -21,33 +20,24 @@ pub(crate) fn complete_lifetime(
     ctx: &CompletionContext<'_>,
     lifetime_ctx: &LifetimeContext,
 ) {
-    let (lp, lifetime) = match lifetime_ctx {
-        LifetimeContext { kind: LifetimeKind::Lifetime, lifetime } => (None, lifetime),
-        LifetimeContext {
-            kind: LifetimeKind::LifetimeParam { is_decl: false, param },
-            lifetime,
-        } => (Some(param), lifetime),
-        _ => return,
-    };
-    let param_lifetime = match (lifetime, lp.and_then(|lp| lp.lifetime())) {
-        (Some(lt), Some(lp)) if lp == lt.clone() => return,
-        (Some(_), Some(lp)) => Some(lp),
-        _ => None,
+    let &LifetimeContext { kind: LifetimeKind::Lifetime { in_lifetime_param_bound, def }, .. } =
+        lifetime_ctx
+    else {
+        return;
     };
-    let param_lifetime = param_lifetime.as_ref().map(ast::Lifetime::text);
-    let param_lifetime = param_lifetime.as_ref().map(TokenText::as_str);
 
     ctx.process_all_names_raw(&mut |name, res| {
-        if matches!(
-            res,
-            ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))
-                 if param_lifetime != Some(&*name.display_no_db(ctx.edition).to_smolstr())
-        ) {
+        if matches!(res, ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))) {
             acc.add_lifetime(ctx, name);
         }
     });
-    if param_lifetime.is_none() {
-        acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static.clone()));
+    acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static.clone()));
+    if !in_lifetime_param_bound
+        && def.is_some_and(|def| {
+            !matches!(def, hir::GenericDef::Function(_) | hir::GenericDef::Impl(_))
+        })
+    {
+        acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_underscore.clone()));
     }
 }
 
@@ -222,6 +212,8 @@ fn foo<'footime, 'lifetime: 'a$0>() {}
 "#,
             expect![[r#"
                 lt 'footime
+                lt 'lifetime
+                lt 'static
             "#]],
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index efbee39a2d4..3a661706336 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -7,8 +7,8 @@ mod tests;
 use std::{iter, ops::ControlFlow};
 
 use hir::{
-    HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type,
-    TypeInfo,
+    HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope,
+    Symbol, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -133,6 +133,7 @@ pub(crate) type ExistingDerives = FxHashSet<hir::Macro>;
 pub(crate) struct AttrCtx {
     pub(crate) kind: AttrKind,
     pub(crate) annotated_item_kind: Option<SyntaxKind>,
+    pub(crate) derive_helpers: Vec<(Symbol, Symbol)>,
 }
 
 #[derive(Debug, PartialEq, Eq)]
@@ -289,15 +290,14 @@ pub(crate) struct ParamContext {
 /// The state of the lifetime we are completing.
 #[derive(Debug)]
 pub(crate) struct LifetimeContext {
-    pub(crate) lifetime: Option<ast::Lifetime>,
     pub(crate) kind: LifetimeKind,
 }
 
 /// The kind of lifetime we are completing.
 #[derive(Debug)]
 pub(crate) enum LifetimeKind {
-    LifetimeParam { is_decl: bool, param: ast::LifetimeParam },
-    Lifetime,
+    LifetimeParam,
+    Lifetime { in_lifetime_param_bound: bool, def: Option<hir::GenericDef> },
     LabelRef,
     LabelDef,
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 468ad81ad2f..4a678963b93 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -562,7 +562,7 @@ fn expected_type_and_name(
 }
 
 fn classify_lifetime(
-    _sema: &Semantics<'_, RootDatabase>,
+    sema: &Semantics<'_, RootDatabase>,
     original_file: &SyntaxNode,
     lifetime: ast::Lifetime,
 ) -> Option<LifetimeContext> {
@@ -571,21 +571,22 @@ fn classify_lifetime(
         return None;
     }
 
+    let lifetime =
+        find_node_at_offset::<ast::Lifetime>(original_file, lifetime.syntax().text_range().start());
     let kind = match_ast! {
         match parent {
-            ast::LifetimeParam(param) => LifetimeKind::LifetimeParam {
-                is_decl: param.lifetime().as_ref() == Some(&lifetime),
-                param
-            },
+            ast::LifetimeParam(_) => LifetimeKind::LifetimeParam,
             ast::BreakExpr(_) => LifetimeKind::LabelRef,
             ast::ContinueExpr(_) => LifetimeKind::LabelRef,
             ast::Label(_) => LifetimeKind::LabelDef,
-            _ => LifetimeKind::Lifetime,
+            _ => {
+                let def = lifetime.as_ref().and_then(|lt| sema.scope(lt.syntax())?.generic_def());
+                LifetimeKind::Lifetime { in_lifetime_param_bound: ast::TypeBound::can_cast(parent.kind()), def }
+            },
         }
     };
-    let lifetime = find_node_at_offset(original_file, lifetime.syntax().text_range().start());
 
-    Some(LifetimeContext { lifetime, kind })
+    Some(LifetimeContext { kind })
 }
 
 fn classify_name(
@@ -1129,7 +1130,22 @@ fn classify_name_ref(
         let is_trailing_outer_attr = kind != AttrKind::Inner
             && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next).is_none();
         let annotated_item_kind = if is_trailing_outer_attr { None } else { Some(attached.kind()) };
-        Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } })
+        let derive_helpers = annotated_item_kind
+            .filter(|kind| {
+                matches!(
+                    kind,
+                    SyntaxKind::STRUCT
+                        | SyntaxKind::ENUM
+                        | SyntaxKind::UNION
+                        | SyntaxKind::VARIANT
+                        | SyntaxKind::TUPLE_FIELD
+                        | SyntaxKind::RECORD_FIELD
+                )
+            })
+            .and_then(|_| nameref.as_ref()?.syntax().ancestors().find_map(ast::Adt::cast))
+            .and_then(|adt| sema.derive_helpers_in_scope(&adt))
+            .unwrap_or_default();
+        Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind, derive_helpers } })
     };
 
     // Infer the path kind
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index 52f6bedaaa9..8878fbbea30 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -346,8 +346,7 @@ pub enum CompletionItemKind {
 impl_from!(SymbolKind for CompletionItemKind);
 
 impl CompletionItemKind {
-    #[cfg(test)]
-    pub(crate) fn tag(self) -> &'static str {
+    pub fn tag(self) -> &'static str {
         match self {
             CompletionItemKind::SymbolKind(kind) => match kind {
                 SymbolKind::Attribute => "at",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index dfee01b187e..14f42b40055 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -19,7 +19,7 @@ use ide_db::{
     },
     items_locator,
     syntax_helpers::tree_diff::diff,
-    FilePosition, RootDatabase,
+    FilePosition, FxHashSet, RootDatabase,
 };
 
 use crate::{
@@ -34,6 +34,7 @@ pub use crate::{
     config::{CallableSnippets, CompletionConfig},
     item::{
         CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
+        CompletionRelevanceReturnType, CompletionRelevanceTypeMatch,
     },
     snippet::{Snippet, SnippetScope},
 };
@@ -50,6 +51,18 @@ pub struct CompletionFieldsToResolve {
 }
 
 impl CompletionFieldsToResolve {
+    pub fn from_client_capabilities(client_capability_fields: &FxHashSet<&str>) -> Self {
+        Self {
+            resolve_label_details: client_capability_fields.contains("labelDetails"),
+            resolve_tags: client_capability_fields.contains("tags"),
+            resolve_detail: client_capability_fields.contains("detail"),
+            resolve_documentation: client_capability_fields.contains("documentation"),
+            resolve_filter_text: client_capability_fields.contains("filterText"),
+            resolve_text_edit: client_capability_fields.contains("textEdit"),
+            resolve_command: client_capability_fields.contains("command"),
+        }
+    }
+
     pub const fn empty() -> Self {
         Self {
             resolve_label_details: false,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
index 45679355b42..1443ebc6c0c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
@@ -9,6 +9,70 @@ fn check(ra_fixture: &str, expect: Expect) {
 }
 
 #[test]
+fn derive_helpers() {
+    check(
+        r#"
+//- /mac.rs crate:mac
+#![crate_type = "proc-macro"]
+
+#[proc_macro_derive(MyDerive, attributes(my_cool_helper_attribute))]
+pub fn my_derive() {}
+
+//- /lib.rs crate:lib deps:mac
+#[rustc_builtin_macro]
+pub macro derive($item:item) {}
+
+#[derive(mac::MyDerive)]
+pub struct Foo(#[m$0] i32);
+"#,
+        expect![[r#"
+            at allow(…)
+            at automatically_derived
+            at cfg(…)
+            at cfg_attr(…)
+            at cold
+            at deny(…)
+            at deprecated
+            at derive                 macro derive
+            at derive(…)
+            at doc = "…"
+            at doc(alias = "…")
+            at doc(hidden)
+            at expect(…)
+            at export_name = "…"
+            at forbid(…)
+            at global_allocator
+            at ignore = "…"
+            at inline
+            at link
+            at link_name = "…"
+            at link_section = "…"
+            at macro_export
+            at macro_use
+            at must_use
+            at my_cool_helper_attribute derive helper of `MyDerive`
+            at no_mangle
+            at non_exhaustive
+            at panic_handler
+            at path = "…"
+            at proc_macro
+            at proc_macro_attribute
+            at proc_macro_derive(…)
+            at repr(…)
+            at should_panic
+            at target_feature(enable = "…")
+            at test
+            at track_caller
+            at used
+            at warn(…)
+            md mac
+            kw crate::
+            kw self::
+        "#]],
+    )
+}
+
+#[test]
 fn proc_macros() {
     check(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index fdac4dd2efb..932ca373020 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -733,6 +733,12 @@ impl NameRefClass {
                     }
                     None
                 },
+                ast::UseBoundGenericArgs(_) => {
+                    sema.resolve_use_type_arg(name_ref)
+                        .map(GenericParam::TypeParam)
+                        .map(Definition::GenericParam)
+                        .map(NameRefClass::Definition)
+                },
                 ast::ExternCrate(extern_crate_ast) => {
                     let extern_crate = sema.to_def(&extern_crate_ast)?;
                     let krate = extern_crate.resolved_crate(sema.db)?;
@@ -764,6 +770,7 @@ impl NameRefClass {
                 sema.resolve_label(lifetime).map(Definition::Label).map(NameRefClass::Definition)
             }
             SyntaxKind::LIFETIME_ARG
+            | SyntaxKind::USE_BOUND_GENERIC_ARGS
             | SyntaxKind::SELF_PARAM
             | SyntaxKind::TYPE_BOUND
             | SyntaxKind::WHERE_PRED
@@ -772,16 +779,6 @@ impl NameRefClass {
                 .map(GenericParam::LifetimeParam)
                 .map(Definition::GenericParam)
                 .map(NameRefClass::Definition),
-            // lifetime bounds, as in the 'b in 'a: 'b aren't wrapped in TypeBound nodes so we gotta check
-            // if our lifetime is in a LifetimeParam without being the constrained lifetime
-            _ if ast::LifetimeParam::cast(parent).and_then(|param| param.lifetime()).as_ref()
-                != Some(lifetime) =>
-            {
-                sema.resolve_lifetime_param(lifetime)
-                    .map(GenericParam::LifetimeParam)
-                    .map(Definition::GenericParam)
-                    .map(NameRefClass::Definition)
-            }
             _ => None,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 49b3ca290f0..a508f2fedd6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -286,7 +286,8 @@ impl Ctx<'_> {
             return None;
         }
         if path.segment().map_or(false, |s| {
-            s.param_list().is_some() || (s.self_token().is_some() && path.parent_path().is_none())
+            s.parenthesized_arg_list().is_some()
+                || (s.self_token().is_some() && path.parent_path().is_none())
         }) {
             // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
             // don't try to qualify sole `self` either, they are usually locals, but are returned as modules due to namespace clashing
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
index 2679cbef61b..b3ecc26cb22 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
@@ -29,7 +29,7 @@ const USELESS_NAME_PREFIXES: &[&str] = &["from_", "with_", "into_"];
 /// # Examples
 /// `Option<Name>` -> `Name`
 /// `Result<User, Error>` -> `User`
-const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"];
+const WRAPPER_TYPES: &[&str] = &["Box", "Arc", "Rc", "Option", "Result"];
 
 /// Prefixes to strip from methods names
 ///
@@ -859,6 +859,32 @@ fn foo() { $0(bar())$0; }
     }
 
     #[test]
+    fn arc_value() {
+        check(
+            r#"
+struct Arc<T>(*const T);
+struct Seed;
+fn bar() -> Arc<Seed> {}
+fn foo() { $0(bar())$0; }
+"#,
+            "seed",
+        );
+    }
+
+    #[test]
+    fn rc_value() {
+        check(
+            r#"
+struct Rc<T>(*const T);
+struct Seed;
+fn bar() -> Rc<Seed> {}
+fn foo() { $0(bar())$0; }
+"#,
+            "seed",
+        );
+    }
+
+    #[test]
     fn ref_call() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
index 02299197b12..e3a1e12e029 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
@@ -37,4 +37,25 @@ fn foo() {
 "#,
         );
     }
+
+    #[test]
+    fn no_error_for_async_fn_traits() {
+        check_diagnostics(
+            r#"
+//- minicore: async_fn
+async fn f(it: impl AsyncFn(u32) -> i32) {
+    let fut = it(0);
+    let _: i32 = fut.await;
+}
+async fn g(mut it: impl AsyncFnMut(u32) -> i32) {
+    let fut = it(0);
+    let _: i32 = fut.await;
+}
+async fn h(it: impl AsyncFnOnce(u32) -> i32) {
+    let fut = it(0);
+    let _: i32 = fut.await;
+}
+        "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
new file mode 100644
index 00000000000..a319a0bcf6d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
@@ -0,0 +1,442 @@
+use either::Either;
+use hir::GenericArgsProhibitedReason;
+use ide_db::assists::Assist;
+use ide_db::source_change::SourceChange;
+use ide_db::text_edit::TextEdit;
+use syntax::{ast, AstNode, TextRange};
+
+use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: generic-args-prohibited
+//
+// This diagnostic is shown when generic arguments are provided for a type that does not accept
+// generic arguments.
+pub(crate) fn generic_args_prohibited(
+    ctx: &DiagnosticsContext<'_>,
+    d: &hir::GenericArgsProhibited,
+) -> Diagnostic {
+    Diagnostic::new_with_syntax_node_ptr(
+        ctx,
+        DiagnosticCode::RustcHardError("E0109"),
+        describe_reason(d.reason),
+        d.args.map(Into::into),
+    )
+    .with_fixes(fixes(ctx, d))
+}
+
+fn describe_reason(reason: GenericArgsProhibitedReason) -> String {
+    let kind = match reason {
+        GenericArgsProhibitedReason::Module => "modules",
+        GenericArgsProhibitedReason::TyParam => "type parameters",
+        GenericArgsProhibitedReason::SelfTy => "`Self`",
+        GenericArgsProhibitedReason::PrimitiveTy => "builtin types",
+        GenericArgsProhibitedReason::EnumVariant => {
+            return "you can specify generic arguments on either the enum or the variant, but not both"
+                .to_owned();
+        }
+    };
+    format!("generic arguments are not allowed on {kind}")
+}
+
+fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::GenericArgsProhibited) -> Option<Vec<Assist>> {
+    let file_id = d.args.file_id.file_id()?;
+    let syntax = d.args.to_node(ctx.sema.db);
+    let range = match &syntax {
+        Either::Left(_) => syntax.syntax().text_range(),
+        Either::Right(param_list) => {
+            let path_segment = ast::PathSegment::cast(param_list.syntax().parent()?)?;
+            let start = if let Some(coloncolon) = path_segment.coloncolon_token() {
+                coloncolon.text_range().start()
+            } else {
+                param_list.syntax().text_range().start()
+            };
+            let end = if let Some(ret_type) = path_segment.ret_type() {
+                ret_type.syntax().text_range().end()
+            } else {
+                param_list.syntax().text_range().end()
+            };
+            TextRange::new(start, end)
+        }
+    };
+    Some(vec![fix(
+        "remove_generic_args",
+        "Remove these generics",
+        SourceChange::from_text_edit(file_id, TextEdit::delete(range)),
+        syntax.syntax().text_range(),
+    )])
+}
+
+#[cfg(test)]
+mod tests {
+    // This diagnostic was the first to be emitted in ty lowering, so the tests here also test
+    // diagnostics in ty lowering in general (which is why there are so many of them).
+
+    use crate::tests::{check_diagnostics, check_fix};
+
+    #[test]
+    fn primitives() {
+        check_diagnostics(
+            r#"
+//- /core.rs crate:core library
+#![rustc_coherence_is_core]
+impl str {
+    pub fn trim() {}
+}
+
+//- /lib.rs crate:foo deps:core
+fn bar<T>() {}
+
+fn foo() {
+    let _: (bool<()>, ());
+             // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+    let _ = <str<'_>>::trim;
+             // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+    bar::<u32<{ const { 1 + 1 } }>>();
+          // ^^^^^^^^^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+            "#,
+        );
+    }
+
+    #[test]
+    fn modules() {
+        check_diagnostics(
+            r#"
+pub mod foo {
+    pub mod bar {
+        pub struct Baz;
+
+        impl Baz {
+            pub fn qux() {}
+        }
+    }
+}
+
+fn foo() {
+    let _: foo::<'_>::bar::Baz;
+           // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    let _ = <foo::bar<()>::Baz>::qux;
+                  // ^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn type_parameters() {
+        check_diagnostics(
+            r#"
+fn foo<T, U>() {
+    let _: T<'a>;
+         // ^^^^ 💡 error: generic arguments are not allowed on type parameters
+    let _: U::<{ 1 + 2 }>;
+         // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on type parameters
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn fn_like_generic_args() {
+        check_diagnostics(
+            r#"
+fn foo() {
+    let _: bool(bool, i32) -> ();
+            // ^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn fn_signature() {
+        check_diagnostics(
+            r#"
+fn foo(
+    _a: bool<'_>,
+         // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+    _b: i32::<i64>,
+        // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    _c: &(&str<1>)
+           // ^^^ 💡 error: generic arguments are not allowed on builtin types
+) -> ((), i32<bool>) {
+          // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    ((), 0)
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn const_static_type() {
+        check_diagnostics(
+            r#"
+const A: i32<bool> = 0;
+         // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+static A: i32::<{ 1 + 3 }> = 0;
+          // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+        "#,
+        );
+    }
+
+    #[test]
+    fn fix() {
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool<'_, (), { 1 + 1 }>$0;
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool::$0<'_, (), { 1 + 1 }>;
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool(i$032);
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool$0(i32) -> i64;
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool::(i$032) -> i64;
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+        check_fix(
+            r#"
+fn foo() {
+    let _: bool::(i32)$0;
+}"#,
+            r#"
+fn foo() {
+    let _: bool;
+}"#,
+        );
+    }
+
+    #[test]
+    fn in_fields() {
+        check_diagnostics(
+            r#"
+struct A(bool<i32>);
+          // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+struct B { v: bool<(), 1> }
+               // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+union C {
+    a: bool<i32>,
+        // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    b: i32<bool>,
+       // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+       }
+enum D {
+    A(bool<i32>),
+       // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    B { v: i32<bool> },
+           // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn in_generics() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub trait Trait {}
+}
+
+struct A<A: foo::<()>::Trait>(A)
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait;
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+union B<A: foo::<()>::Trait>
+           // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{ a: A }
+enum C<A: foo::<()>::Trait>
+          // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{}
+
+fn f<A: foo::<()>::Trait>()
+        // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{}
+
+type D<A: foo::<()>::Trait> = A
+          // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait;
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+
+trait E<A: foo::<()>::Trait>
+           // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{
+    fn f<B: foo::<()>::Trait>()
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+        where bool<i32>: foo::Trait
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    {}
+
+    type D<B: foo::<()>::Trait> = A
+              // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+        where bool<i32>: foo::Trait;
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl<A: foo::<()>::Trait> E for ()
+        // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    where bool<i32>: foo::Trait
+           // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{
+    fn f<B: foo::<()>::Trait>()
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+        where bool<i32>: foo::Trait
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    {}
+
+    type D<B: foo::<()>::Trait> = A
+              // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+        where bool<i32>: foo::Trait;
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn assoc_items() {
+        check_diagnostics(
+            r#"
+struct Foo;
+
+trait Trait {
+    fn f() -> bool<i32> { true }
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    type T = i32<bool>;
+             // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl Trait for Foo {
+    fn f() -> bool<i32> { true }
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    type T = i32<bool>;
+             // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl Foo {
+    fn f() -> bool<i32> { true }
+               // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    type T = i32<bool>;
+             // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn const_param_ty() {
+        check_diagnostics(
+            r#"
+fn foo<
+    const A: bool<i32>,
+              // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    B,
+    C,
+    const D: bool<i32>,
+              // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+    const E: bool<i32>,
+              // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+>() {}
+        "#,
+        );
+    }
+
+    #[test]
+    fn generic_defaults() {
+        check_diagnostics(
+            r#"
+struct Foo<A = bool<i32>>(A);
+                // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+        "#,
+        );
+    }
+
+    #[test]
+    fn impl_self_ty() {
+        check_diagnostics(
+            r#"
+struct Foo<A>(A);
+trait Trait {}
+impl Foo<bool<i32>> {}
+          // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+impl Trait for Foo<bool<i32>> {}
+                    // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+        "#,
+        );
+    }
+
+    #[test]
+    fn impl_trait() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub trait Trait {}
+}
+impl foo::<()>::Trait for () {}
+     // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+        "#,
+        );
+    }
+
+    #[test]
+    fn type_alias() {
+        check_diagnostics(
+            r#"
+pub trait Trait {
+    type Assoc;
+}
+type T = bool<i32>;
+          // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+impl Trait for () {
+    type Assoc = i32<bool>;
+                 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+        "#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
index f39738f2fb8..08e6e7dced9 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
@@ -1114,6 +1114,25 @@ fn test(x: Option<lib::PrivatelyUninhabited>) {
         }
     }
 
+    #[test]
+    fn non_exhaustive_may_be_empty() {
+        check_diagnostics_no_bails(
+            r"
+//- /main.rs crate:main deps:dep
+// In a different crate
+fn empty_match_on_empty_struct<T>(x: dep::UninhabitedStruct) -> T {
+    match x {}
+}
+//- /dep.rs crate:dep
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+    pub never: !,
+    // other fields
+}
+",
+        );
+    }
+
     mod false_negatives {
         //! The implementation of match checking here is a work in progress. As we roll this out, we
         //! prefer false negatives to false positives (ideally there would be no false positives). This
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index a630d3c7c36..2bfdda35659 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -1,5 +1,5 @@
 use hir::db::ExpandDatabase;
-use hir::HirFileIdExt;
+use hir::{HirFileIdExt, UnsafetyReason};
 use ide_db::text_edit::TextEdit;
 use ide_db::{assists::Assist, source_change::SourceChange};
 use syntax::{ast, SyntaxNode};
@@ -16,23 +16,35 @@ pub(crate) fn missing_unsafe(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsaf
     } else {
         DiagnosticCode::RustcHardError("E0133")
     };
+    let operation = display_unsafety_reason(d.reason);
     Diagnostic::new_with_syntax_node_ptr(
         ctx,
         code,
-        "this operation is unsafe and requires an unsafe function or block",
-        d.expr.map(|it| it.into()),
+        format!("{operation} is unsafe and requires an unsafe function or block"),
+        d.node.map(|it| it.into()),
     )
     .with_fixes(fixes(ctx, d))
 }
 
+fn display_unsafety_reason(reason: UnsafetyReason) -> &'static str {
+    match reason {
+        UnsafetyReason::UnionField => "access to union field",
+        UnsafetyReason::UnsafeFnCall => "call to unsafe function",
+        UnsafetyReason::InlineAsm => "use of inline assembly",
+        UnsafetyReason::RawPtrDeref => "dereference of raw pointer",
+        UnsafetyReason::MutableStatic => "use of mutable static",
+        UnsafetyReason::ExternStatic => "use of extern static",
+    }
+}
+
 fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Option<Vec<Assist>> {
     // The fixit will not work correctly for macro expansions, so we don't offer it in that case.
-    if d.expr.file_id.is_macro() {
+    if d.node.file_id.is_macro() {
         return None;
     }
 
-    let root = ctx.sema.db.parse_or_expand(d.expr.file_id);
-    let node = d.expr.value.to_node(&root);
+    let root = ctx.sema.db.parse_or_expand(d.node.file_id);
+    let node = d.node.value.to_node(&root);
     let expr = node.syntax().ancestors().find_map(ast::Expr::cast)?;
 
     let node_to_add_unsafe_block = pick_best_node_to_add_unsafe_block(&expr)?;
@@ -40,7 +52,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Option<Vec<Ass
     let replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text());
     let edit = TextEdit::replace(node_to_add_unsafe_block.text_range(), replacement);
     let source_change =
-        SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
+        SourceChange::from_text_edit(d.node.file_id.original_file(ctx.sema.db), edit);
     Some(vec![fix("add_unsafe", "Add unsafe block", source_change, expr.syntax().text_range())])
 }
 
@@ -110,7 +122,7 @@ fn main() {
     let x = &5_usize as *const usize;
     unsafe { let _y = *x; }
     let _z = *x;
-}          //^^💡 error: this operation is unsafe and requires an unsafe function or block
+}          //^^💡 error: dereference of raw pointer is unsafe and requires an unsafe function or block
 "#,
         )
     }
@@ -136,9 +148,9 @@ unsafe fn unsafe_fn() {
 
 fn main() {
     unsafe_fn();
-  //^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+  //^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
     HasUnsafe.unsafe_fn();
-  //^^^^^^^^^^^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+  //^^^^^^^^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
     unsafe {
         unsafe_fn();
         HasUnsafe.unsafe_fn();
@@ -162,7 +174,7 @@ static mut STATIC_MUT: Ty = Ty { a: 0 };
 
 fn main() {
     let _x = STATIC_MUT.a;
-           //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+           //^^^^^^^^^^💡 error: use of mutable static is unsafe and requires an unsafe function or block
     unsafe {
         let _x = STATIC_MUT.a;
     }
@@ -184,9 +196,9 @@ extern "C" {
 
 fn main() {
     let _x = EXTERN;
-           //^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+           //^^^^^^💡 error: use of extern static is unsafe and requires an unsafe function or block
     let _x = EXTERN_MUT;
-           //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+           //^^^^^^^^^^💡 error: use of mutable static is unsafe and requires an unsafe function or block
     unsafe {
         let _x = EXTERN;
         let _x = EXTERN_MUT;
@@ -234,7 +246,7 @@ extern "rust-intrinsic" {
 fn main() {
     let _ = bitreverse(12);
     let _ = floorf32(12.0);
-          //^^^^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+          //^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
 }
 "#,
         );
@@ -567,7 +579,7 @@ unsafe fn not_safe() -> u8 {
 fn main() {
     ed2021::safe();
     ed2024::not_safe();
-  //^^^^^^^^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
+  //^^^^^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
 }
             "#,
         )
@@ -591,7 +603,7 @@ unsafe fn foo(p: *mut i32) {
 #![warn(unsafe_op_in_unsafe_fn)]
 unsafe fn foo(p: *mut i32) {
     *p = 123;
-  //^^💡 warn: this operation is unsafe and requires an unsafe function or block
+  //^^💡 warn: dereference of raw pointer is unsafe and requires an unsafe function or block
 }
             "#,
         )
@@ -618,17 +630,119 @@ unsafe extern {
 fn main() {
     f();
     g();
-  //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+  //^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
     h();
-  //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+  //^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
 
     let _ = S1;
     let _ = S2;
-          //^^💡 error: this operation is unsafe and requires an unsafe function or block
+          //^^💡 error: use of extern static is unsafe and requires an unsafe function or block
     let _ = S3;
-          //^^💡 error: this operation is unsafe and requires an unsafe function or block
+          //^^💡 error: use of extern static is unsafe and requires an unsafe function or block
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn no_unsafe_diagnostic_when_destructuring_union_with_wildcard() {
+        check_diagnostics(
+            r#"
+union Union { field: i32 }
+fn foo(v: &Union) {
+    let Union { field: _ } = v;
+    let Union { field: _ | _ } = v;
+    Union { field: _ } = *v;
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn union_destructuring() {
+        check_diagnostics(
+            r#"
+union Union { field: u8 }
+fn foo(v @ Union { field: _field }: &Union) {
+                       // ^^^^^^ error: access to union field is unsafe and requires an unsafe function or block
+    let Union { mut field } = v;
+             // ^^^^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    let Union { field: 0..=255 } = v;
+                    // ^^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    let Union { field: 0
+                    // ^💡 error: access to union field is unsafe and requires an unsafe function or block
+        | 1..=255 } = v;
+       // ^^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    Union { field } = *v;
+         // ^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    match v {
+        Union { field: _field } => {}
+                    // ^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    }
+    if let Union { field: _field } = v {}
+                       // ^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+    (|&Union { field }| { _ = field; })(v);
+            // ^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn union_field_access() {
+        check_diagnostics(
+            r#"
+union Union { field: u8 }
+fn foo(v: &Union) {
+    v.field;
+ // ^^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
 }
 "#,
         );
     }
+
+    #[test]
+    fn inline_asm() {
+        check_diagnostics(
+            r#"
+//- minicore: asm
+fn foo() {
+    core::arch::asm!("");
+                 // ^^^^ error: use of inline assembly is unsafe and requires an unsafe function or block
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unsafe_op_in_unsafe_fn_dismissed_in_signature() {
+        check_diagnostics(
+            r#"
+#![warn(unsafe_op_in_unsafe_fn)]
+union Union { field: u32 }
+unsafe fn foo(Union { field: _field }: Union) {}
+            "#,
+        )
+    }
+
+    #[test]
+    fn union_assignment_allowed() {
+        check_diagnostics(
+            r#"
+union Union { field: u32 }
+fn foo(mut v: Union) {
+    v.field = 123;
+    (v.field,) = (123,);
+    *&mut v.field = 123;
+       // ^^^^^^^💡 error: access to union field is unsafe and requires an unsafe function or block
+}
+struct Struct { field: u32 }
+union Union2 { field: Struct }
+fn bar(mut v: Union2) {
+    v.field.field = 123;
+}
+
+            "#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 93fe9374a3e..bfdda537405 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1,12 +1,16 @@
 use either::Either;
-use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type};
-use ide_db::text_edit::TextEdit;
-use ide_db::{famous_defs::FamousDefs, source_change::SourceChange};
+use hir::{db::ExpandDatabase, CallableKind, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type};
+use ide_db::{
+    famous_defs::FamousDefs,
+    source_change::{SourceChange, SourceChangeBuilder},
+    text_edit::TextEdit,
+};
 use syntax::{
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        BlockExpr, Expr, ExprStmt,
+        syntax_factory::SyntaxFactory,
+        BlockExpr, Expr, ExprStmt, HasArgList,
     },
     AstNode, AstPtr, TextSize,
 };
@@ -63,6 +67,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option<Vec<Assi
         let expr_ptr = &InFile { file_id: d.expr_or_pat.file_id, value: expr_ptr };
         add_reference(ctx, d, expr_ptr, &mut fixes);
         add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes);
+        remove_unnecessary_wrapper(ctx, d, expr_ptr, &mut fixes);
         remove_semicolon(ctx, d, expr_ptr, &mut fixes);
         str_ref_to_owned(ctx, d, expr_ptr, &mut fixes);
     }
@@ -184,6 +189,89 @@ fn add_missing_ok_or_some(
     Some(())
 }
 
+fn remove_unnecessary_wrapper(
+    ctx: &DiagnosticsContext<'_>,
+    d: &hir::TypeMismatch,
+    expr_ptr: &InFile<AstPtr<ast::Expr>>,
+    acc: &mut Vec<Assist>,
+) -> Option<()> {
+    let db = ctx.sema.db;
+    let root = db.parse_or_expand(expr_ptr.file_id);
+    let expr = expr_ptr.value.to_node(&root);
+    let expr = ctx.sema.original_ast_node(expr.clone())?;
+
+    let Expr::CallExpr(call_expr) = expr else {
+        return None;
+    };
+
+    let callable = ctx.sema.resolve_expr_as_callable(&call_expr.expr()?)?;
+    let CallableKind::TupleEnumVariant(variant) = callable.kind() else {
+        return None;
+    };
+
+    let actual_enum = d.actual.as_adt()?.as_enum()?;
+    let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(call_expr.syntax())?.krate());
+    let core_option = famous_defs.core_option_Option();
+    let core_result = famous_defs.core_result_Result();
+    if Some(actual_enum) != core_option && Some(actual_enum) != core_result {
+        return None;
+    }
+
+    let inner_type = variant.fields(db).first()?.ty_with_args(db, d.actual.type_arguments());
+    if !d.expected.could_unify_with(db, &inner_type) {
+        return None;
+    }
+
+    let inner_arg = call_expr.arg_list()?.args().next()?;
+
+    let file_id = expr_ptr.file_id.original_file(db);
+    let mut builder = SourceChangeBuilder::new(file_id);
+    let mut editor;
+    match inner_arg {
+        // We're returning `()`
+        Expr::TupleExpr(tup) if tup.fields().next().is_none() => {
+            let parent = call_expr
+                .syntax()
+                .parent()
+                .and_then(Either::<ast::ReturnExpr, ast::StmtList>::cast)?;
+
+            editor = builder.make_editor(parent.syntax());
+            let make = SyntaxFactory::new();
+
+            match parent {
+                Either::Left(ret_expr) => {
+                    editor.replace(ret_expr.syntax(), make.expr_return(None).syntax());
+                }
+                Either::Right(stmt_list) => {
+                    let new_block = if stmt_list.statements().next().is_none() {
+                        make.expr_empty_block()
+                    } else {
+                        make.block_expr(stmt_list.statements(), None)
+                    };
+
+                    editor.replace(stmt_list.syntax().parent()?, new_block.syntax());
+                }
+            }
+
+            editor.add_mappings(make.finish_with_mappings());
+        }
+        _ => {
+            editor = builder.make_editor(call_expr.syntax());
+            editor.replace(call_expr.syntax(), inner_arg.syntax());
+        }
+    }
+
+    builder.add_file_edits(file_id, editor);
+    let name = format!("Remove unnecessary {}() wrapper", variant.name(db).as_str());
+    acc.push(fix(
+        "remove_unnecessary_wrapper",
+        &name,
+        builder.finish(),
+        call_expr.syntax().text_range(),
+    ));
+    Some(())
+}
+
 fn remove_semicolon(
     ctx: &DiagnosticsContext<'_>,
     d: &hir::TypeMismatch,
@@ -243,7 +331,7 @@ fn str_ref_to_owned(
 #[cfg(test)]
 mod tests {
     use crate::tests::{
-        check_diagnostics, check_diagnostics_with_disabled, check_fix, check_no_fix,
+        check_diagnostics, check_diagnostics_with_disabled, check_fix, check_has_fix, check_no_fix,
     };
 
     #[test]
@@ -260,7 +348,7 @@ fn test(_arg: &i32) {}
     }
 
     #[test]
-    fn test_add_reference_to_int() {
+    fn add_reference_to_int() {
         check_fix(
             r#"
 fn main() {
@@ -278,7 +366,7 @@ fn test(_arg: &i32) {}
     }
 
     #[test]
-    fn test_add_mutable_reference_to_int() {
+    fn add_mutable_reference_to_int() {
         check_fix(
             r#"
 fn main() {
@@ -296,7 +384,7 @@ fn test(_arg: &mut i32) {}
     }
 
     #[test]
-    fn test_add_reference_to_array() {
+    fn add_reference_to_array() {
         check_fix(
             r#"
 //- minicore: coerce_unsized
@@ -315,7 +403,7 @@ fn test(_arg: &[i32]) {}
     }
 
     #[test]
-    fn test_add_reference_with_autoderef() {
+    fn add_reference_with_autoderef() {
         check_fix(
             r#"
 //- minicore: coerce_unsized, deref
@@ -348,7 +436,7 @@ fn test(_arg: &Bar) {}
     }
 
     #[test]
-    fn test_add_reference_to_method_call() {
+    fn add_reference_to_method_call() {
         check_fix(
             r#"
 fn main() {
@@ -372,7 +460,7 @@ impl Test {
     }
 
     #[test]
-    fn test_add_reference_to_let_stmt() {
+    fn add_reference_to_let_stmt() {
         check_fix(
             r#"
 fn main() {
@@ -388,7 +476,7 @@ fn main() {
     }
 
     #[test]
-    fn test_add_reference_to_macro_call() {
+    fn add_reference_to_macro_call() {
         check_fix(
             r#"
 macro_rules! thousand {
@@ -416,7 +504,7 @@ fn main() {
     }
 
     #[test]
-    fn test_add_mutable_reference_to_let_stmt() {
+    fn add_mutable_reference_to_let_stmt() {
         check_fix(
             r#"
 fn main() {
@@ -432,29 +520,6 @@ fn main() {
     }
 
     #[test]
-    fn test_wrap_return_type_option() {
-        check_fix(
-            r#"
-//- minicore: option, result
-fn div(x: i32, y: i32) -> Option<i32> {
-    if y == 0 {
-        return None;
-    }
-    x / y$0
-}
-"#,
-            r#"
-fn div(x: i32, y: i32) -> Option<i32> {
-    if y == 0 {
-        return None;
-    }
-    Some(x / y)
-}
-"#,
-        );
-    }
-
-    #[test]
     fn const_generic_type_mismatch() {
         check_diagnostics(
             r#"
@@ -487,59 +552,82 @@ fn div(x: i32, y: i32) -> Option<i32> {
     }
 
     #[test]
-    fn test_wrap_return_type_option_tails() {
+    fn wrap_return_type() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div(x: i32, y: i32) -> Result<i32, ()> {
+    if y == 0 {
+        return Err(());
+    }
+    x / y$0
+}
+"#,
+            r#"
+fn div(x: i32, y: i32) -> Result<i32, ()> {
+    if y == 0 {
+        return Err(());
+    }
+    Ok(x / y)
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_option() {
         check_fix(
             r#"
 //- minicore: option, result
 fn div(x: i32, y: i32) -> Option<i32> {
     if y == 0 {
-        Some(0)
-    } else if true {
-        100$0
-    } else {
-        None
+        return None;
     }
+    x / y$0
 }
 "#,
             r#"
 fn div(x: i32, y: i32) -> Option<i32> {
     if y == 0 {
-        Some(0)
-    } else if true {
-        Some(100)
-    } else {
-        None
+        return None;
     }
+    Some(x / y)
 }
 "#,
         );
     }
 
     #[test]
-    fn test_wrap_return_type() {
+    fn wrap_return_type_option_tails() {
         check_fix(
             r#"
 //- minicore: option, result
-fn div(x: i32, y: i32) -> Result<i32, ()> {
+fn div(x: i32, y: i32) -> Option<i32> {
     if y == 0 {
-        return Err(());
+        Some(0)
+    } else if true {
+        100$0
+    } else {
+        None
     }
-    x / y$0
 }
 "#,
             r#"
-fn div(x: i32, y: i32) -> Result<i32, ()> {
+fn div(x: i32, y: i32) -> Option<i32> {
     if y == 0 {
-        return Err(());
+        Some(0)
+    } else if true {
+        Some(100)
+    } else {
+        None
     }
-    Ok(x / y)
 }
 "#,
         );
     }
 
     #[test]
-    fn test_wrap_return_type_handles_generic_functions() {
+    fn wrap_return_type_handles_generic_functions() {
         check_fix(
             r#"
 //- minicore: option, result
@@ -562,7 +650,7 @@ fn div<T>(x: T) -> Result<T, i32> {
     }
 
     #[test]
-    fn test_wrap_return_type_handles_type_aliases() {
+    fn wrap_return_type_handles_type_aliases() {
         check_fix(
             r#"
 //- minicore: option, result
@@ -589,7 +677,7 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
     }
 
     #[test]
-    fn test_wrapped_unit_as_block_tail_expr() {
+    fn wrapped_unit_as_block_tail_expr() {
         check_fix(
             r#"
 //- minicore: result
@@ -619,7 +707,7 @@ fn foo() -> Result<(), ()> {
     }
 
     #[test]
-    fn test_wrapped_unit_as_return_expr() {
+    fn wrapped_unit_as_return_expr() {
         check_fix(
             r#"
 //- minicore: result
@@ -642,7 +730,7 @@ fn foo(b: bool) -> Result<(), String> {
     }
 
     #[test]
-    fn test_in_const_and_static() {
+    fn wrap_in_const_and_static() {
         check_fix(
             r#"
 //- minicore: option, result
@@ -664,7 +752,7 @@ const _: Option<()> = {Some(())};
     }
 
     #[test]
-    fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
+    fn wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
         check_no_fix(
             r#"
 //- minicore: option, result
@@ -674,7 +762,7 @@ fn foo() -> Result<(), i32> { 0$0 }
     }
 
     #[test]
-    fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
+    fn wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
         check_no_fix(
             r#"
 //- minicore: option, result
@@ -686,6 +774,254 @@ fn foo() -> SomeOtherEnum { 0$0 }
     }
 
     #[test]
+    fn unwrap_return_type() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        panic!();
+    }
+    Ok(x / y)$0
+}
+"#,
+            r#"
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        panic!();
+    }
+    x / y
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_option() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        panic!();
+    }
+    Some(x / y)$0
+}
+"#,
+            r#"
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        panic!();
+    }
+    x / y
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_option_tails() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        42
+    } else if true {
+        Some(100)$0
+    } else {
+        0
+    }
+}
+"#,
+            r#"
+fn div(x: i32, y: i32) -> i32 {
+    if y == 0 {
+        42
+    } else if true {
+        100
+    } else {
+        0
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_option_tail_unit() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div(x: i32, y: i32) {
+    if y == 0 {
+        panic!();
+    }
+
+    Ok(())$0
+}
+"#,
+            r#"
+fn div(x: i32, y: i32) {
+    if y == 0 {
+        panic!();
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_handles_generic_functions() {
+        check_fix(
+            r#"
+//- minicore: option, result
+fn div<T>(x: T) -> T {
+    if x == 0 {
+        panic!();
+    }
+    $0Ok(x)
+}
+"#,
+            r#"
+fn div<T>(x: T) -> T {
+    if x == 0 {
+        panic!();
+    }
+    x
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_handles_type_aliases() {
+        check_fix(
+            r#"
+//- minicore: option, result
+type MyResult<T> = T;
+
+fn div(x: i32, y: i32) -> MyResult<i32> {
+    if y == 0 {
+        panic!();
+    }
+    Ok(x $0/ y)
+}
+"#,
+            r#"
+type MyResult<T> = T;
+
+fn div(x: i32, y: i32) -> MyResult<i32> {
+    if y == 0 {
+        panic!();
+    }
+    x / y
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_tail_expr() {
+        check_fix(
+            r#"
+//- minicore: result
+fn foo() -> () {
+    println!("Hello, world!");
+    Ok(())$0
+}
+            "#,
+            r#"
+fn foo() -> () {
+    println!("Hello, world!");
+}
+            "#,
+        );
+    }
+
+    #[test]
+    fn unwrap_to_empty_block() {
+        check_fix(
+            r#"
+//- minicore: result
+fn foo() -> () {
+    Ok(())$0
+}
+            "#,
+            r#"
+fn foo() -> () {}
+            "#,
+        );
+    }
+
+    #[test]
+    fn unwrap_to_return_expr() {
+        check_has_fix(
+            r#"
+//- minicore: result
+fn foo(b: bool) -> () {
+    if b {
+        return $0Ok(());
+    }
+
+    panic!("oh dear");
+}"#,
+            r#"
+fn foo(b: bool) -> () {
+    if b {
+        return;
+    }
+
+    panic!("oh dear");
+}"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_in_const_and_static() {
+        check_fix(
+            r#"
+//- minicore: option, result
+static A: () = {Some(($0))};
+            "#,
+            r#"
+static A: () = {};
+            "#,
+        );
+        check_fix(
+            r#"
+//- minicore: option, result
+const _: () = {Some(($0))};
+            "#,
+            r#"
+const _: () = {};
+            "#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_not_applicable_when_inner_type_does_not_match_return_type() {
+        check_no_fix(
+            r#"
+//- minicore: result
+fn foo() -> i32 { $0Ok(()) }
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_return_type_not_applicable_when_wrapper_type_is_not_result_or_option() {
+        check_no_fix(
+            r#"
+//- minicore: option, result
+enum SomeOtherEnum { Ok(i32), Err(String) }
+
+fn foo() -> i32 { SomeOtherEnum::Ok($042) }
+"#,
+        );
+    }
+
+    #[test]
     fn remove_semicolon() {
         check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
     }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index 81cb4521218..4ab649cc162 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -167,9 +167,9 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
         }
 
         let method_name = call.name_ref()?;
-        let assoc_func_call = format!("{receiver_type_adt_name}::{method_name}()");
+        let assoc_func_path = format!("{receiver_type_adt_name}::{method_name}");
 
-        let assoc_func_call = make::expr_path(make::path_from_text(&assoc_func_call));
+        let assoc_func_path = make::expr_path(make::path_from_text(&assoc_func_path));
 
         let args: Vec<_> = if need_to_take_receiver_as_first_arg {
             std::iter::once(receiver).chain(call.arg_list()?.args()).collect()
@@ -178,7 +178,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
         };
         let args = make::arg_list(args);
 
-        let assoc_func_call_expr_string = make::expr_call(assoc_func_call, args).to_string();
+        let assoc_func_call_expr_string = make::expr_call(assoc_func_path, args).to_string();
 
         let file_id = ctx.sema.original_range_opt(call.receiver()?.syntax())?.file_id;
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 1f1b6478d36..ad339569081 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -27,6 +27,7 @@ mod handlers {
     pub(crate) mod await_outside_of_async;
     pub(crate) mod break_outside_of_loop;
     pub(crate) mod expected_function;
+    pub(crate) mod generic_args_prohibited;
     pub(crate) mod inactive_code;
     pub(crate) mod incoherent_impl;
     pub(crate) mod incorrect_case;
@@ -468,6 +469,7 @@ pub fn semantic_diagnostics(
                 Some(it) => it,
                 None => continue,
             },
+            AnyDiagnostic::GenericArgsProhibited(d) => handlers::generic_args_prohibited::generic_args_prohibited(&ctx, &d)
         };
         res.push(d)
     }
@@ -542,7 +544,13 @@ fn handle_diag_from_macros(
         sema.db.lookup_intern_syntax_context(span.ctx).outer_expn.is_some_and(|expansion| {
             let macro_call =
                 sema.db.lookup_intern_macro_call(expansion.as_macro_file().macro_call_id);
+            // We don't want to show diagnostics for non-local macros at all, but proc macros authors
+            // seem to rely on being able to emit non-warning-free code, so we don't want to show warnings
+            // for them even when the proc macro comes from the same workspace (in rustc that's not a
+            // problem because it doesn't have the concept of workspaces, and proc macros always reside
+            // in a different crate).
             !Crate::from(macro_call.def.krate).origin(sema.db).is_local()
+                || !macro_call.def.kind.is_declarative()
         })
     }) {
         // Disable suggestions for external macros, they'll change library code and it's just bad.
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index 6569f0f5552..4edc3633fbe 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -359,8 +359,8 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                 )?;
                 self.attempt_match_opt(
                     phase,
-                    pattern_segment.param_list(),
-                    code_segment.param_list(),
+                    pattern_segment.parenthesized_arg_list(),
+                    code_segment.parenthesized_arg_list(),
                 )?;
             }
             if matches!(phase, Phase::Second(_)) {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 0986d5542cd..ea18b89c5c9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -288,7 +288,7 @@ m!(ab$0c);
             *abc*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -301,7 +301,7 @@ m!(ab$0c);
             ---
 
             ```rust
-            test::module
+            ra_test_fixture::module
             ```
 
             ```rust
@@ -327,7 +327,7 @@ fn main() {
 "#,
         expect![[r#"
             *foo*
-            test
+            ra_test_fixture
 
             pub fn foo() -> u32
         "#]],
@@ -487,7 +487,7 @@ fn main() {
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::S2",
+                            mod_path: "ra_test_fixture::S2",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -500,7 +500,7 @@ fn main() {
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -583,7 +583,7 @@ fn main() { let foo_test = fo$0o(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -605,7 +605,7 @@ fn main() { f$0oo(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -627,7 +627,7 @@ fn main() { m::f$0oo(); }
             *foo*
 
             ```rust
-            test::m
+            ra_test_fixture::m
             ```
 
             ```rust
@@ -649,7 +649,7 @@ fn main() { fo$0o(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -667,7 +667,7 @@ fn main() { fo$0o(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -691,7 +691,7 @@ fn main() { let foo_test = fo$0o(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -715,7 +715,7 @@ fn main() { }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -743,7 +743,7 @@ fn main() { }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -776,7 +776,7 @@ fn main() { }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -801,7 +801,7 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
             *field_a*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -830,7 +830,7 @@ fn main() {
             *field_a*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -852,7 +852,7 @@ fn main() {
             *field_a*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -880,7 +880,7 @@ fn main() {
             *0*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -900,7 +900,7 @@ fn foo(foo: Foo) {
             *0*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -920,7 +920,7 @@ struct Foo$0(pub u32) where u32: Copy;
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -946,7 +946,7 @@ struct Foo$0 { field: u32 }
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -968,7 +968,7 @@ struct Foo$0 where u32: Copy { field: u32 }
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -998,7 +998,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1023,7 +1023,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1046,7 +1046,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1072,7 +1072,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1093,7 +1093,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1116,7 +1116,7 @@ fn hover_record_struct_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1141,7 +1141,7 @@ fn hover_record_variant_limit() {
             *A*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -1162,7 +1162,7 @@ fn hover_record_variant_limit() {
             *A*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -1183,7 +1183,7 @@ fn hover_record_variant_limit() {
             *A*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -1204,7 +1204,7 @@ fn hover_record_variant_limit() {
             *A*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -1225,7 +1225,7 @@ fn hover_record_variant_limit() {
             *A*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -1248,7 +1248,7 @@ fn hover_enum_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1270,7 +1270,7 @@ fn hover_enum_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1292,7 +1292,7 @@ fn hover_enum_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1311,7 +1311,7 @@ fn hover_enum_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1339,7 +1339,7 @@ fn hover_enum_limit() {
             *Enum*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1371,7 +1371,7 @@ fn hover_union_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1393,7 +1393,7 @@ fn hover_union_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1415,7 +1415,7 @@ fn hover_union_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1434,7 +1434,7 @@ fn hover_union_limit() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1458,7 +1458,7 @@ struct Foo$0 where u32: Copy;
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1484,7 +1484,7 @@ type Fo$0o: Trait = S where T: Trait;
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1504,7 +1504,7 @@ fn hover_const_static() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1522,7 +1522,7 @@ const foo$0: u32 = {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1540,7 +1540,7 @@ const foo$0: u32 = {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1555,7 +1555,7 @@ const foo$0: u32 = {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1573,7 +1573,7 @@ const foo$0: u32 = {
             *BAR*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1591,7 +1591,7 @@ fn hover_unsigned_max_const() {
             *A*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1612,7 +1612,7 @@ fn hover_eval_complex_constants() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -1667,16 +1667,16 @@ use Option::Some;
 fn main() { So$0me(12); }
 "#,
         expect![[r#"
-                *Some*
+            *Some*
 
-                ```rust
-                test::Option
-                ```
+            ```rust
+            ra_test_fixture::Option
+            ```
 
-                ```rust
-                Some(T)
-                ```
-            "#]],
+            ```rust
+            Some(T)
+            ```
+        "#]],
     );
 
     check(
@@ -1711,20 +1711,20 @@ enum Option<T> {
 }
 "#,
         expect![[r#"
-                *None*
+            *None*
 
-                ```rust
-                test::Option
-                ```
+            ```rust
+            ra_test_fixture::Option
+            ```
 
-                ```rust
-                None
-                ```
+            ```rust
+            None
+            ```
 
-                ---
+            ---
 
-                The None variant
-            "#]],
+            The None variant
+        "#]],
     );
 
     check(
@@ -1738,20 +1738,20 @@ fn main() {
 }
 "#,
         expect![[r#"
-                *Some*
+            *Some*
 
-                ```rust
-                test::Option
-                ```
+            ```rust
+            ra_test_fixture::Option
+            ```
 
-                ```rust
-                Some(T)
-                ```
+            ```rust
+            Some(T)
+            ```
 
-                ---
+            ---
 
-                The Some variant
-            "#]],
+            The Some variant
+        "#]],
     );
 }
 
@@ -1885,7 +1885,7 @@ fn main() { let foo_test = wrapper::Thing::new$0(); }
             *new*
 
             ```rust
-            test::wrapper::Thing
+            ra_test_fixture::wrapper::Thing
             ```
 
             ```rust
@@ -1916,7 +1916,7 @@ fn main() {
             *C*
 
             ```rust
-            test::X
+            ra_test_fixture::X
             ```
 
             ```rust
@@ -1936,18 +1936,18 @@ impl Thing {
 }
 "#,
         expect![[r#"
-                *Self*
+            *Self*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                struct Thing {
-                    x: u32,
-                }
-                ```
-            "#]],
+            ```rust
+            struct Thing {
+                x: u32,
+            }
+            ```
+        "#]],
     );
     check_hover_fields_limit(
         None,
@@ -1958,16 +1958,16 @@ impl Thing {
 }
 "#,
         expect![[r#"
-                *Self*
+            *Self*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                struct Thing
-                ```
-            "#]],
+            ```rust
+            struct Thing
+            ```
+        "#]],
     );
     check(
         r#"
@@ -1977,18 +1977,18 @@ impl Thing {
 }
 "#,
         expect![[r#"
-                *Self*
+            *Self*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                struct Thing {
-                    x: u32,
-                }
-                ```
-            "#]],
+            ```rust
+            struct Thing {
+                x: u32,
+            }
+            ```
+        "#]],
     );
     check(
         r#"
@@ -2001,7 +2001,7 @@ impl Thing {
             *Self*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2022,7 +2022,7 @@ impl Thing {
             *Self*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2042,7 +2042,7 @@ impl usize {
             *Self*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2060,7 +2060,7 @@ impl fn() -> usize {
             *Self*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2103,7 +2103,7 @@ fn f() { fo$0o!(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2128,7 +2128,7 @@ fn f() { fo$0o!(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2172,7 +2172,7 @@ id! {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2194,7 +2194,7 @@ fn foo$0() {}
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2252,7 +2252,7 @@ fn foo() { let a = id!([0u32, bar$0()] ); }
             *bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2278,7 +2278,7 @@ fn foo() {
             *bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2302,7 +2302,7 @@ fn foo(Foo { b$0ar }: &Foo) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Bar",
+                            mod_path: "ra_test_fixture::Bar",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -2334,7 +2334,7 @@ fn bar() { fo$0o(); }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2356,7 +2356,7 @@ fn test_hover_function_show_qualifiers() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2370,7 +2370,7 @@ fn test_hover_function_show_qualifiers() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2385,7 +2385,7 @@ fn test_hover_function_show_qualifiers() {
             *foo*
 
             ```rust
-            test::m
+            ra_test_fixture::m
             ```
 
             ```rust
@@ -2403,7 +2403,7 @@ fn test_hover_function_show_types() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2426,7 +2426,7 @@ fn main() { foo$0; }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2446,7 +2446,7 @@ fn main() { foo$0; }
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2464,7 +2464,7 @@ fn test_hover_function_pointer_show_identifiers() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2486,7 +2486,7 @@ fn test_hover_function_pointer_no_identifier() {
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2601,16 +2601,16 @@ mod my { pub struct Bar; }
 fn my() {}
 "#,
         expect![[r#"
-                *my*
+            *my*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                mod my
-                ```
-            "#]],
+            ```rust
+            mod my
+            ```
+        "#]],
     );
 }
 
@@ -2636,7 +2636,7 @@ fn foo() { let bar = Ba$0r; }
             *Bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2672,7 +2672,7 @@ fn foo() { let bar = Ba$0r; }
             *Bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2701,7 +2701,7 @@ fn foo() { let bar = Ba$0r; }
             *Bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2729,7 +2729,7 @@ pub struct B$0ar
             *Bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2760,7 +2760,7 @@ pub struct B$0ar
             *Bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2809,7 +2809,7 @@ pub fn fo$0o() {}
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2853,7 +2853,7 @@ fn test_hover_layout_of_variant() {
             *Variant1*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -2878,7 +2878,7 @@ fn test_hover_layout_of_variant_generic() {
             *None*
 
             ```rust
-            test::Option
+            ra_test_fixture::Option
             ```
 
             ```rust
@@ -2899,7 +2899,7 @@ struct S$0<T>(core::marker::PhantomData<T>);
             *S*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2924,7 +2924,7 @@ fn test_hover_layout_of_enum() {
             *Foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -2949,7 +2949,7 @@ fn test_hover_no_memory_layout() {
             *field_a*
 
             ```rust
-            test::Foo
+            ra_test_fixture::Foo
             ```
 
             ```rust
@@ -3003,7 +3003,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); }
             *foo*
 
             ```rust
-            test::Bar
+            ra_test_fixture::Bar
             ```
 
             ```rust
@@ -3041,7 +3041,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); }
             *foo*
 
             ```rust
-            test::Bar
+            ra_test_fixture::Bar
             ```
 
             ```rust
@@ -3069,7 +3069,7 @@ fn main() { let foo_test = unsafe { fo$0o(1, 2, 3); } }
             *foo*
 
             ```rust
-            test::<extern>
+            ra_test_fixture::<extern>
             ```
 
             ```rust
@@ -3267,7 +3267,7 @@ fn main() { let s$0t = S{ f1:0 }; }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3300,7 +3300,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Arg",
+                            mod_path: "ra_test_fixture::Arg",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3313,7 +3313,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3359,7 +3359,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Arg",
+                            mod_path: "ra_test_fixture::Arg",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3372,7 +3372,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3408,7 +3408,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::A",
+                            mod_path: "ra_test_fixture::A",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3421,7 +3421,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::B",
+                            mod_path: "ra_test_fixture::B",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3434,7 +3434,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::M::C",
+                            mod_path: "ra_test_fixture::M::C",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3468,7 +3468,7 @@ fn main() { let s$0t = foo(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3502,7 +3502,7 @@ fn main() { let s$0t = foo(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3515,7 +3515,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3549,7 +3549,7 @@ fn main() { let s$0t = foo(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Bar",
+                            mod_path: "ra_test_fixture::Bar",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3562,7 +3562,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3599,7 +3599,7 @@ fn main() { let s$0t = foo(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Bar",
+                            mod_path: "ra_test_fixture::Bar",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3612,7 +3612,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3625,7 +3625,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S1",
+                            mod_path: "ra_test_fixture::S1",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3638,7 +3638,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S2",
+                            mod_path: "ra_test_fixture::S2",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3669,7 +3669,7 @@ fn foo(ar$0g: &impl Foo) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3703,7 +3703,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Bar",
+                            mod_path: "ra_test_fixture::Bar",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3716,7 +3716,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3729,7 +3729,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3816,7 +3816,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3829,7 +3829,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3866,7 +3866,7 @@ fn main() { let s$0t = foo(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::B",
+                            mod_path: "ra_test_fixture::B",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3879,7 +3879,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3892,7 +3892,7 @@ fn main() { let s$0t = foo(); }
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3923,7 +3923,7 @@ fn foo(ar$0g: &dyn Foo) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3955,7 +3955,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -3968,7 +3968,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4003,7 +4003,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::B",
+                            mod_path: "ra_test_fixture::B",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4016,7 +4016,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::DynTrait",
+                            mod_path: "ra_test_fixture::DynTrait",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4029,7 +4029,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::ImplTrait",
+                            mod_path: "ra_test_fixture::ImplTrait",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4042,7 +4042,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S",
+                            mod_path: "ra_test_fixture::S",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4084,7 +4084,7 @@ fn main() { let s$0t = test().get(); }
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4117,7 +4117,7 @@ impl<const BAR: Bar> Foo<BAR$0> {}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Bar",
+                            mod_path: "ra_test_fixture::Bar",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4149,7 +4149,7 @@ fn foo<T: Foo>(t: T$0){}
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4182,7 +4182,7 @@ impl Foo {
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -4257,7 +4257,7 @@ fn main() {
             ---
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -4282,7 +4282,7 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
             *ST*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -4307,7 +4307,7 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
             *ST*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -4333,7 +4333,7 @@ struct S$0T<const C: usize = VAL, T = Foo>(T);
             *ST*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -4527,21 +4527,21 @@ mod Foo$0 {
 }
 "#,
         expect![[r#"
-                *Foo*
+            *Foo*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                mod Foo
-                ```
+            ```rust
+            mod Foo
+            ```
 
-                ---
+            ---
 
-                Be quick;
-                time is mana
-            "#]],
+            Be quick;
+            time is mana
+        "#]],
     );
 }
 
@@ -4558,21 +4558,21 @@ mod Foo$0 {
 }
 "#,
         expect![[r#"
-                *Foo*
+            *Foo*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                mod Foo
-                ```
+            ```rust
+            mod Foo
+            ```
 
-                ---
+            ---
 
-                Be quick;
-                time is mana
-            "#]],
+            Be quick;
+            time is mana
+        "#]],
     );
 }
 
@@ -4592,7 +4592,7 @@ fn foo$0() {}
             *foo*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -4902,7 +4902,7 @@ type Fo$0o2 = Foo<2>;
             *Foo2*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -4948,7 +4948,7 @@ enum E {
             *A*
 
             ```rust
-            test::E
+            ra_test_fixture::E
             ```
 
             ```rust
@@ -4977,7 +4977,7 @@ enum E {
             *A*
 
             ```rust
-            test::E
+            ra_test_fixture::E
             ```
 
             ```rust
@@ -5007,7 +5007,7 @@ enum E {
             *B*
 
             ```rust
-            test::E
+            ra_test_fixture::E
             ```
 
             ```rust
@@ -5037,7 +5037,7 @@ enum E {
             *B*
 
             ```rust
-            test::E
+            ra_test_fixture::E
             ```
 
             ```rust
@@ -5074,7 +5074,7 @@ fn main() {
             *B*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5111,7 +5111,7 @@ fn main() {
             *AA*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5138,7 +5138,7 @@ fn main() {
             *B*
 
             ```rust
-            test::T
+            ra_test_fixture::T
             ```
 
             ```rust
@@ -5167,7 +5167,7 @@ fn main() {
             *B*
 
             ```rust
-            test::T
+            ra_test_fixture::T
             ```
 
             ```rust
@@ -5199,7 +5199,7 @@ fn main() {
             *B*
 
             ```rust
-            test::T
+            ra_test_fixture::T
             ```
 
             ```rust
@@ -5222,7 +5222,7 @@ const FOO$0: usize = 1 << 3;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5243,7 +5243,7 @@ const FOO$0: usize = (1 << 3) + (1 << 2);
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5265,7 +5265,7 @@ const FOO$0: usize = 2 - 3;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5287,7 +5287,7 @@ const FOO$0: i32 = 2 - 3;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5308,7 +5308,7 @@ const FOO$0: &str = "bar";
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5330,7 +5330,7 @@ const FOO$0: char = 'a';
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5352,7 +5352,7 @@ const FOO$0: char = '\x61';
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5374,7 +5374,7 @@ const FOO$0: u8 = b'a';
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5396,7 +5396,7 @@ const FOO$0: u8 = b'\x61';
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5418,7 +5418,7 @@ const FOO$0: u8 = b'\x61';
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5440,7 +5440,7 @@ const FOO$0: f32 = 1f32;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5462,7 +5462,7 @@ const FOO$0: &i32 = &2;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5484,7 +5484,7 @@ const FOO$0: f64 = 1.0f64;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5512,7 +5512,7 @@ const FOO$0: f64 = expf64(1.2);
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5530,7 +5530,7 @@ const FOO$0: f32 = 1.9999999403953552_f32;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5552,7 +5552,7 @@ const FOO$0: f16 = -1.0f16;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5573,7 +5573,7 @@ const FOO$0: f128 = -1.0f128;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5604,7 +5604,7 @@ const FOO$0: Enum = VX;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5621,7 +5621,7 @@ const FOO$0: Option<i32> = Some(2);
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5638,7 +5638,7 @@ const FOO$0: Option<&i32> = Some(2).as_ref();
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5661,7 +5661,7 @@ const FOO$0: &dyn Debug = &2i32;
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5682,7 +5682,7 @@ const FOO$0: &[i32] = &[1, 2, 3 + 4];
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5699,7 +5699,7 @@ const FOO$0: &[i32; 5] = &[12; 5];
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5720,7 +5720,7 @@ const FOO$0: (&i32, &[i32], &i32) = {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5743,7 +5743,7 @@ const FOO$0: Tree = {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5763,7 +5763,7 @@ const FOO$0: &S<[u8]> = core::mem::transmute::<&[u8], _>(&[1, 2, 3]);
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5783,7 +5783,7 @@ const FOO$0: &str = "foo";
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5806,7 +5806,7 @@ const FOO$0: X = X {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5825,7 +5825,7 @@ const FOO$0: (&str, &str) = {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5856,7 +5856,7 @@ fn test() {
             *FOO*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -5883,7 +5883,7 @@ fn foo() {
             *FOO*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5912,7 +5912,7 @@ fn foo(e: E) {
             *A*
 
             ```rust
-            test::E
+            ra_test_fixture::E
             ```
 
             ```rust
@@ -5942,7 +5942,7 @@ pub fn the_function() -> AA {
             *CONST*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -5984,20 +5984,20 @@ mod foo$0;
 //! For the horde!
 "#,
         expect![[r#"
-                *foo*
+            *foo*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                mod foo
-                ```
+            ```rust
+            mod foo
+            ```
 
-                ---
+            ---
 
-                For the horde!
-            "#]],
+            For the horde!
+        "#]],
     );
 }
 
@@ -6013,20 +6013,20 @@ mod foo {
 use foo::bar::{self$0};
 "#,
         expect![[r#"
-                *self*
+            *self*
 
-                ```rust
-                test::foo
-                ```
+            ```rust
+            ra_test_fixture::foo
+            ```
 
-                ```rust
-                mod bar
-                ```
+            ```rust
+            mod bar
+            ```
 
-                ---
+            ---
 
-                But this should appear
-            "#]],
+            But this should appear
+        "#]],
     )
 }
 
@@ -6166,7 +6166,7 @@ fn main() {
             *bar*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -6200,7 +6200,7 @@ pub fn gimme() -> theitem::TheItem {
             *[`TheItem`]*
 
             ```rust
-            test::theitem
+            ra_test_fixture::theitem
             ```
 
             ```rust
@@ -6248,7 +6248,7 @@ impl T1 for Foo {
             *Bar*
 
             ```rust
-            test::t2::T2
+            ra_test_fixture::t2::T2
             ```
 
             ```rust
@@ -6270,7 +6270,7 @@ trait A {
             *Assoc*
 
             ```rust
-            test::A
+            ra_test_fixture::A
             ```
 
             ```rust
@@ -6291,7 +6291,7 @@ trait A {
             *Assoc*
 
             ```rust
-            test::A
+            ra_test_fixture::A
             ```
 
             ```rust
@@ -6310,7 +6310,7 @@ trait A where
             *Assoc*
 
             ```rust
-            test::A
+            ra_test_fixture::A
             ```
 
             ```rust
@@ -6572,12 +6572,12 @@ fn hover_rename() {
 use self as foo$0;
 "#,
         expect![[r#"
-                *foo*
+            *foo*
 
-                ```rust
-                extern crate test
-                ```
-            "#]],
+            ```rust
+            extern crate ra_test_fixture
+            ```
+        "#]],
     );
     check(
         r#"
@@ -6585,16 +6585,16 @@ mod bar {}
 use bar::{self as foo$0};
 "#,
         expect![[r#"
-                *foo*
+            *foo*
 
-                ```rust
-                test
-                ```
+            ```rust
+            ra_test_fixture
+            ```
 
-                ```rust
-                mod bar
-                ```
-            "#]],
+            ```rust
+            mod bar
+            ```
+        "#]],
     );
     check(
         r#"
@@ -6603,24 +6603,24 @@ mod bar {
 }
 "#,
         expect![[r#"
-                *foo*
+            *foo*
 
-                ```rust
-                extern crate test
-                ```
-            "#]],
+            ```rust
+            extern crate ra_test_fixture
+            ```
+        "#]],
     );
     check(
         r#"
 use crate as foo$0;
 "#,
         expect![[r#"
-                *foo*
+            *foo*
 
-                ```rust
-                extern crate test
-                ```
-            "#]],
+            ```rust
+            extern crate ra_test_fixture
+            ```
+        "#]],
     );
 }
 
@@ -6645,7 +6645,7 @@ identity!{
             *Copy*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -6669,7 +6669,7 @@ struct Foo;
             *Copy*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -6691,7 +6691,7 @@ struct Foo;
             *Copy*
 
             ```rust
-            test::foo
+            ra_test_fixture::foo
             ```
 
             ```rust
@@ -6910,7 +6910,7 @@ fn foo() {
                 GoToType(
                     [
                         HoverGotoTypeData {
-                            mod_path: "test::Foo",
+                            mod_path: "ra_test_fixture::Foo",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -7110,7 +7110,7 @@ foo_macro!(
             *[`Foo`]*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7119,7 +7119,7 @@ foo_macro!(
 
             ---
 
-            Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
+            Doc comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/struct.Foo.html)
         "#]],
     );
 }
@@ -7135,7 +7135,7 @@ pub struct Foo(i32);
             *[`Foo`]*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7144,7 +7144,7 @@ pub struct Foo(i32);
 
             ---
 
-            Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
+            Doc comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/struct.Foo.html)
         "#]],
     );
 }
@@ -7160,7 +7160,7 @@ pub struct Foo<T>(T);
             *[`Foo<T>`]*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7169,7 +7169,7 @@ pub struct Foo<T>(T);
 
             ---
 
-            Doc comment for [`Foo<T>`](https://docs.rs/test/*/test/struct.Foo.html)
+            Doc comment for [`Foo<T>`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/struct.Foo.html)
         "#]],
     );
 }
@@ -7259,7 +7259,7 @@ enum Enum {
             *RecordV*
 
             ```rust
-            test::Enum
+            ra_test_fixture::Enum
             ```
 
             ```rust
@@ -7285,7 +7285,7 @@ enum Enum {
             *field*
 
             ```rust
-            test::RecordV
+            ra_test_fixture::RecordV
             ```
 
             ```rust
@@ -7315,7 +7315,7 @@ impl T for () {
             *func*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7341,7 +7341,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7360,7 +7360,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7383,7 +7383,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7406,7 +7406,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7433,7 +7433,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7460,7 +7460,7 @@ impl T$0 for () {}
             *T*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7529,7 +7529,7 @@ fn f() {
             ***
 
             ```rust
-            test::Struct
+            ra_test_fixture::Struct
             ```
 
             ```rust
@@ -7558,7 +7558,7 @@ fn main() { $0V; }
             *V*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7585,7 +7585,7 @@ fn main() { $0V; }
             *V*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -7765,7 +7765,7 @@ fn test() {
             *foo*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7794,7 +7794,7 @@ fn test() {
             *foo*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7824,7 +7824,7 @@ mod m {
             *foo*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7854,7 +7854,7 @@ fn test() {
             *A*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7883,7 +7883,7 @@ fn test() {
             *A*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7913,7 +7913,7 @@ mod m {
             *A*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -7936,7 +7936,7 @@ fn test() {
             *f*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -8091,7 +8091,7 @@ fn main() {
             *foo*
 
             ```rust
-            test::S
+            ra_test_fixture::S
             ```
 
             ```rust
@@ -8573,7 +8573,7 @@ impl Iterator for S {
             *S*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -8595,7 +8595,7 @@ extern "C" {
             *STATIC*
 
             ```rust
-            test::<extern>
+            ra_test_fixture::<extern>
             ```
 
             ```rust
@@ -8613,7 +8613,7 @@ extern "C" {
             *fun*
 
             ```rust
-            test::<extern>
+            ra_test_fixture::<extern>
             ```
 
             ```rust
@@ -8631,7 +8631,7 @@ extern "C" {
             *Ty*
 
             ```rust
-            test::<extern>
+            ra_test_fixture::<extern>
             ```
 
             ```rust
@@ -8731,7 +8731,7 @@ impl Iterator for S {
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::Notable",
+                            mod_path: "ra_test_fixture::Notable",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -8744,7 +8744,7 @@ impl Iterator for S {
                             },
                         },
                         HoverGotoTypeData {
-                            mod_path: "test::S2",
+                            mod_path: "ra_test_fixture::S2",
                             nav: NavigationTarget {
                                 file_id: FileId(
                                     0,
@@ -8775,7 +8775,7 @@ struct Pedro$0<'a> {
             *Pedro*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -8962,7 +8962,7 @@ fn test_hover_function_with_pat_param() {
             *test_1*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -8978,7 +8978,7 @@ fn test_hover_function_with_pat_param() {
             *test_2*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -8994,7 +8994,7 @@ fn test_hover_function_with_pat_param() {
             *test_3*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9010,7 +9010,7 @@ fn test_hover_function_with_pat_param() {
             *test_4*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9026,7 +9026,7 @@ fn test_hover_function_with_pat_param() {
             *test_5*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9042,7 +9042,7 @@ fn test_hover_function_with_pat_param() {
             *test_6*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9058,7 +9058,7 @@ fn test_hover_function_with_pat_param() {
             *test_7*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9074,7 +9074,7 @@ fn test_hover_function_with_pat_param() {
             *test_8*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9090,7 +9090,7 @@ fn test_hover_function_with_pat_param() {
             *test_9*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9106,7 +9106,7 @@ fn test_hover_function_with_pat_param() {
             *test_10*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9122,7 +9122,7 @@ fn test_hover_function_with_pat_param() {
             *test_10*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9148,7 +9148,7 @@ mod m {
             *C*
 
             ```rust
-            test::m::m2
+            ra_test_fixture::m::m2
             ```
 
             ```rust
@@ -9173,17 +9173,17 @@ macro_rules! foo {
 foo!(BAR_$0);
 "#,
         expect![[r#"
-        *BAR_*
+            *BAR_*
 
-        ```rust
-        test
-        ```
+            ```rust
+            ra_test_fixture
+            ```
 
-        ```rust
-        pub static BAR_: {error} = Foo::new(||{
-            crate;
-        })
-        ```
+            ```rust
+            pub static BAR_: {error} = Foo::new(||{
+                crate;
+            })
+            ```
         "#]],
     );
 }
@@ -9202,7 +9202,7 @@ type A$0 = B;
             *A*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9235,7 +9235,7 @@ type A$0 = B;
             *A*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9269,7 +9269,7 @@ type A$0 = B;
             *A*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9301,7 +9301,7 @@ type A$0 = B;
             *A*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9362,7 +9362,7 @@ trait Compat$0 {}
             *Compat*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9384,7 +9384,7 @@ trait UnCompat$0 {
             *UnCompat*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9407,7 +9407,7 @@ fn f<T: UnCompat$0>
             *UnCompat*
 
             ```rust
-            test
+            ra_test_fixture
             ```
 
             ```rust
@@ -9416,3 +9416,53 @@ fn f<T: UnCompat$0>
         "#]],
     );
 }
+
+#[test]
+fn issue_18613() {
+    check(
+        r#"
+fn main() {
+    struct S<T, D = bool>();
+    let x$0 = S::<()>;
+}"#,
+        expect![[r#"
+            *x*
+
+            ```rust
+            let x: fn S<()>() -> S<()>
+            ```
+
+            ---
+
+            size = 0, align = 1
+        "#]],
+    );
+
+    check(
+        r#"
+pub struct Global;
+pub struct Box<T, A = Global>(T, A);
+
+impl<T> Box<T> {
+    pub fn new(x: T) -> Self { loop {} }
+}
+
+pub struct String;
+
+fn main() {
+    let box_value$0 = Box::<String>new();
+}
+"#,
+        expect![[r#"
+            *box_value*
+
+            ```rust
+            let box_value: fn Box<String>(String, Global) -> Box<String>
+            ```
+
+            ---
+
+            size = 0, align = 1
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index c58ca0f01cd..aa99ba49bc8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -8,8 +8,8 @@ use hir::{
     sym, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
     ModuleDefId, Semantics,
 };
-use ide_db::text_edit::TextEdit;
 use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase};
+use ide_db::{text_edit::TextEdit, FxHashSet};
 use itertools::Itertools;
 use smallvec::{smallvec, SmallVec};
 use span::{Edition, EditionedFileId};
@@ -29,6 +29,7 @@ mod closing_brace;
 mod closure_captures;
 mod closure_ret;
 mod discriminant;
+mod extern_block;
 mod generic_param;
 mod implicit_drop;
 mod implicit_static;
@@ -116,6 +117,7 @@ pub(crate) fn inlay_hints(
 #[derive(Default)]
 struct InlayHintCtx {
     lifetime_stacks: Vec<Vec<SmolStr>>,
+    extern_block_parent: Option<ast::ExternBlock>,
 }
 
 pub(crate) fn inlay_hints_resolve(
@@ -174,12 +176,18 @@ fn handle_event(ctx: &mut InlayHintCtx, node: WalkEvent<SyntaxNode>) -> Option<S
                     .unwrap_or_default();
                 ctx.lifetime_stacks.push(params);
             }
+            if let Some(node) = ast::ExternBlock::cast(node.clone()) {
+                ctx.extern_block_parent = Some(node);
+            }
             Some(node)
         }
         WalkEvent::Leave(n) => {
             if ast::AnyHasGenericParams::can_cast(n.kind()) {
                 ctx.lifetime_stacks.pop();
             }
+            if ast::ExternBlock::can_cast(n.kind()) {
+                ctx.extern_block_parent = None;
+            }
             None
         }
     }
@@ -234,12 +242,20 @@ fn hints(
             ast::Item(it) => match it {
                 ast::Item::Fn(it) => {
                     implicit_drop::hints(hints, famous_defs, config, file_id, &it);
+                    if let Some(extern_block) = &ctx.extern_block_parent {
+                        extern_block::fn_hints(hints, famous_defs, config, file_id, &it, extern_block);
+                    }
                     lifetime::fn_hints(hints, ctx, famous_defs, config, file_id, it)
                 },
-                // static type elisions
-                ast::Item::Static(it) => implicit_static::hints(hints, famous_defs, config, file_id, Either::Left(it)),
+                ast::Item::Static(it) => {
+                    if let Some(extern_block) = &ctx.extern_block_parent {
+                        extern_block::static_hints(hints, famous_defs, config, file_id, &it, extern_block);
+                    }
+                    implicit_static::hints(hints, famous_defs, config, file_id, Either::Left(it))
+                },
                 ast::Item::Const(it) => implicit_static::hints(hints, famous_defs, config, file_id, Either::Right(it)),
                 ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it),
+                ast::Item::ExternBlock(it) => extern_block::extern_block_hints(hints, famous_defs, config, file_id, it),
                 _ => None,
             },
             // FIXME: trait object type elisions
@@ -289,6 +305,16 @@ pub struct InlayFieldsToResolve {
 }
 
 impl InlayFieldsToResolve {
+    pub fn from_client_capabilities(client_capability_fields: &FxHashSet<&str>) -> Self {
+        Self {
+            resolve_text_edits: client_capability_fields.contains("textEdits"),
+            resolve_hint_tooltip: client_capability_fields.contains("tooltip"),
+            resolve_label_tooltip: client_capability_fields.contains("label.tooltip"),
+            resolve_label_location: client_capability_fields.contains("label.location"),
+            resolve_label_command: client_capability_fields.contains("label.command"),
+        }
+    }
+
     pub const fn empty() -> Self {
         Self {
             resolve_text_edits: false,
@@ -358,6 +384,7 @@ pub enum InlayKind {
     Type,
     Drop,
     RangeExclusive,
+    ExternUnsafety,
 }
 
 #[derive(Debug, Hash)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs
new file mode 100644
index 00000000000..4cc4925cda6
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs
@@ -0,0 +1,138 @@
+//! Extern block hints
+use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit};
+use span::EditionedFileId;
+use syntax::{ast, AstNode, SyntaxToken};
+
+use crate::{InlayHint, InlayHintsConfig};
+
+pub(super) fn extern_block_hints(
+    acc: &mut Vec<InlayHint>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
+    _config: &InlayHintsConfig,
+    _file_id: EditionedFileId,
+    extern_block: ast::ExternBlock,
+) -> Option<()> {
+    if extern_block.unsafe_token().is_some() {
+        return None;
+    }
+    let abi = extern_block.abi()?;
+    acc.push(InlayHint {
+        range: abi.syntax().text_range(),
+        position: crate::InlayHintPosition::Before,
+        pad_left: false,
+        pad_right: true,
+        kind: crate::InlayKind::ExternUnsafety,
+        label: crate::InlayHintLabel::from("unsafe"),
+        text_edit: Some(TextEdit::insert(abi.syntax().text_range().start(), "unsafe ".to_owned())),
+        resolve_parent: Some(extern_block.syntax().text_range()),
+    });
+    Some(())
+}
+
+pub(super) fn fn_hints(
+    acc: &mut Vec<InlayHint>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
+    _config: &InlayHintsConfig,
+    _file_id: EditionedFileId,
+    fn_: &ast::Fn,
+    extern_block: &ast::ExternBlock,
+) -> Option<()> {
+    let implicit_unsafe = fn_.safe_token().is_none() && fn_.unsafe_token().is_none();
+    if !implicit_unsafe {
+        return None;
+    }
+    let fn_ = fn_.fn_token()?;
+    acc.push(item_hint(extern_block, fn_));
+    Some(())
+}
+
+pub(super) fn static_hints(
+    acc: &mut Vec<InlayHint>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
+    _config: &InlayHintsConfig,
+    _file_id: EditionedFileId,
+    static_: &ast::Static,
+    extern_block: &ast::ExternBlock,
+) -> Option<()> {
+    let implicit_unsafe = static_.safe_token().is_none() && static_.unsafe_token().is_none();
+    if !implicit_unsafe {
+        return None;
+    }
+    let static_ = static_.static_token()?;
+    acc.push(item_hint(extern_block, static_));
+    Some(())
+}
+
+fn item_hint(extern_block: &ast::ExternBlock, token: SyntaxToken) -> InlayHint {
+    InlayHint {
+        range: token.text_range(),
+        position: crate::InlayHintPosition::Before,
+        pad_left: false,
+        pad_right: true,
+        kind: crate::InlayKind::ExternUnsafety,
+        label: crate::InlayHintLabel::from("unsafe"),
+        text_edit: {
+            let mut builder = TextEdit::builder();
+            builder.insert(token.text_range().start(), "unsafe ".to_owned());
+            if extern_block.unsafe_token().is_none() {
+                if let Some(abi) = extern_block.abi() {
+                    builder.insert(abi.syntax().text_range().start(), "unsafe ".to_owned());
+                }
+            }
+            Some(builder.finish())
+        },
+        resolve_parent: Some(extern_block.syntax().text_range()),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::inlay_hints::tests::{check_with_config, DISABLED_CONFIG};
+
+    #[test]
+    fn unadorned() {
+        check_with_config(
+            DISABLED_CONFIG,
+            r#"
+  extern "C" {
+//^^^^^^^^^^ unsafe
+    static FOO: ();
+ // ^^^^^^ unsafe
+    pub static FOO: ();
+     // ^^^^^^unsafe
+    unsafe static FOO: ();
+    safe static FOO: ();
+    fn foo();
+ // ^^ unsafe
+    pub fn foo();
+     // ^^ unsafe
+    unsafe fn foo();
+    safe fn foo();
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn adorned() {
+        check_with_config(
+            DISABLED_CONFIG,
+            r#"
+unsafe extern "C" {
+    static FOO: ();
+ // ^^^^^^ unsafe
+    pub static FOO: ();
+     // ^^^^^^unsafe
+    unsafe static FOO: ();
+    safe static FOO: ();
+    fn foo();
+ // ^^ unsafe
+    pub fn foo();
+     // ^^ unsafe
+    unsafe fn foo();
+    safe fn foo();
+}
+"#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
index 2163c959b18..1fdd6989917 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
@@ -41,7 +41,15 @@ pub(super) fn fn_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.params().filter_map(|it| {
+            Some((
+                it.pat().and_then(|it| match it {
+                    ast::Pat::IdentPat(p) => p.name(),
+                    _ => None,
+                }),
+                it.ty()?,
+            ))
+        }),
         generic_param_list,
         ret_type,
         self_param,
@@ -90,7 +98,15 @@ pub(super) fn fn_ptr_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.params().filter_map(|it| {
+            Some((
+                it.pat().and_then(|it| match it {
+                    ast::Pat::IdentPat(p) => p.name(),
+                    _ => None,
+                }),
+                it.ty()?,
+            ))
+        }),
         generic_param_list,
         ret_type,
         None,
@@ -148,7 +164,7 @@ pub(super) fn fn_path_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.type_args().filter_map(|it| Some((None, it.ty()?))),
         generic_param_list,
         ret_type,
         None,
@@ -177,8 +193,8 @@ pub(super) fn fn_path_hints(
     )
 }
 
-fn path_as_fn(path: &ast::Path) -> Option<(ast::ParamList, Option<ast::RetType>)> {
-    path.segment().and_then(|it| it.param_list().zip(Some(it.ret_type())))
+fn path_as_fn(path: &ast::Path) -> Option<(ast::ParenthesizedArgList, Option<ast::RetType>)> {
+    path.segment().and_then(|it| it.parenthesized_arg_list().zip(Some(it.ret_type())))
 }
 
 fn hints_(
@@ -187,7 +203,7 @@ fn hints_(
     FamousDefs(_, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
-    param_list: ast::ParamList,
+    params: impl Iterator<Item = (Option<ast::Name>, ast::Type)>,
     generic_param_list: Option<ast::GenericParamList>,
     ret_type: Option<ast::RetType>,
     self_param: Option<ast::SelfParam>,
@@ -217,45 +233,34 @@ fn hints_(
             let is_elided = is_elided(&lifetime);
             acc.push((None, self_param.amp_token(), lifetime, is_elided));
         }
-        param_list
-            .params()
-            .filter_map(|it| {
-                Some((
-                    it.pat().and_then(|it| match it {
-                        ast::Pat::IdentPat(p) => p.name(),
-                        _ => None,
-                    }),
-                    it.ty()?,
-                ))
-            })
-            .for_each(|(name, ty)| {
-                // FIXME: check path types
-                walk_ty(&ty, &mut |ty| match ty {
-                    ast::Type::RefType(r) => {
-                        let lifetime = r.lifetime();
-                        let is_elided = is_elided(&lifetime);
-                        acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
-                        false
-                    }
-                    ast::Type::FnPtrType(_) => {
+        params.for_each(|(name, ty)| {
+            // FIXME: check path types
+            walk_ty(&ty, &mut |ty| match ty {
+                ast::Type::RefType(r) => {
+                    let lifetime = r.lifetime();
+                    let is_elided = is_elided(&lifetime);
+                    acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
+                    false
+                }
+                ast::Type::FnPtrType(_) => {
+                    is_trivial = false;
+                    true
+                }
+                ast::Type::PathType(t) => {
+                    if t.path()
+                        .and_then(|it| it.segment())
+                        .and_then(|it| it.parenthesized_arg_list())
+                        .is_some()
+                    {
                         is_trivial = false;
                         true
+                    } else {
+                        false
                     }
-                    ast::Type::PathType(t) => {
-                        if t.path()
-                            .and_then(|it| it.segment())
-                            .and_then(|it| it.param_list())
-                            .is_some()
-                        {
-                            is_trivial = false;
-                            true
-                        } else {
-                            false
-                        }
-                    }
-                    _ => false,
-                })
-            });
+                }
+                _ => false,
+            })
+        });
         acc
     };
 
@@ -339,7 +344,10 @@ fn hints_(
                     true
                 }
                 ast::Type::PathType(t) => {
-                    if t.path().and_then(|it| it.segment()).and_then(|it| it.param_list()).is_some()
+                    if t.path()
+                        .and_then(|it| it.segment())
+                        .and_then(|it| it.parenthesized_arg_list())
+                        .is_some()
                     {
                         is_trivial = false;
                         true
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index d4ef9570e1a..c960b88a3e9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -402,6 +402,8 @@ impl Analysis {
         self.with_db(|db| typing::on_enter(db, position))
     }
 
+    pub const SUPPORTED_TRIGGER_CHARS: &'static str = typing::TRIGGER_CHARS;
+
     /// Returns an edit which should be applied after a character was typed.
     ///
     /// This is useful for some on-the-fly fixups, like adding `;` to `let =`
@@ -410,14 +412,16 @@ impl Analysis {
         &self,
         position: FilePosition,
         char_typed: char,
-        autoclose: bool,
+        chars_to_exclude: Option<String>,
     ) -> Cancellable<Option<SourceChange>> {
         // Fast path to not even parse the file.
         if !typing::TRIGGER_CHARS.contains(char_typed) {
             return Ok(None);
         }
-        if char_typed == '<' && !autoclose {
-            return Ok(None);
+        if let Some(chars_to_exclude) = chars_to_exclude {
+            if chars_to_exclude.contains(char_typed) {
+                return Ok(None);
+            }
         }
 
         self.with_db(|db| typing::on_char_typed(db, position, char_typed))
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index 665fc954d23..a9519c03b32 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -3105,4 +3105,73 @@ fn main() { let _: Baz; }
 "#,
         );
     }
+
+    #[test]
+    fn rename_type_param_ref_in_use_bound() {
+        check(
+            "U",
+            r#"
+fn foo<T>() -> impl use<T$0> Trait {}
+"#,
+            r#"
+fn foo<U>() -> impl use<U> Trait {}
+"#,
+        );
+    }
+
+    #[test]
+    fn rename_type_param_in_use_bound() {
+        check(
+            "U",
+            r#"
+fn foo<T$0>() -> impl use<T> Trait {}
+"#,
+            r#"
+fn foo<U>() -> impl use<U> Trait {}
+"#,
+        );
+    }
+
+    #[test]
+    fn rename_lifetime_param_ref_in_use_bound() {
+        check(
+            "u",
+            r#"
+fn foo<'t>() -> impl use<'t$0> Trait {}
+"#,
+            r#"
+fn foo<'u>() -> impl use<'u> Trait {}
+"#,
+        );
+    }
+
+    #[test]
+    fn rename_lifetime_param_in_use_bound() {
+        check(
+            "u",
+            r#"
+fn foo<'t$0>() -> impl use<'t> Trait {}
+"#,
+            r#"
+fn foo<'u>() -> impl use<'u> Trait {}
+"#,
+        );
+    }
+
+    #[test]
+    fn rename_parent_type_param_in_use_bound() {
+        check(
+            "U",
+            r#"
+trait Trait<T> {
+    fn foo() -> impl use<T$0> Trait {}
+}
+"#,
+            r#"
+trait Trait<U> {
+    fn foo() -> impl use<U> Trait {}
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
index 96375937a12..3767a3917ce 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
@@ -151,6 +151,14 @@ fn punctuation(
             T!['['] | T![']'] => HlPunct::Bracket,
             T!['{'] | T!['}'] => HlPunct::Brace,
             T!['('] | T![')'] => HlPunct::Parenthesis,
+            T![>]
+                if parent
+                    .as_ref()
+                    .and_then(SyntaxNode::parent)
+                    .map_or(false, |it| it.kind() == MACRO_RULES) =>
+            {
+                return HlOperator::Other.into()
+            }
             T![<] | T![>] => HlPunct::Angle,
             T![,] => HlPunct::Comma,
             T![:] => HlPunct::Colon,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
index 70f2d7203e9..edd9639768a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
@@ -46,7 +46,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>foo<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>foo<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="keyword">mod</span> y <span class="brace">{</span>
             <span class="keyword">pub</span> <span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span>
         <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
index a14f2cc88cd..05289cfe3fe 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
@@ -46,7 +46,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
@@ -79,7 +79,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 35650bbe87f..aa9d23250c1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -147,11 +147,11 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="comment documentation">/// ```</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="angle injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
 <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span>expr
     <span class="brace">}</span>
 <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
index a790b385786..c2bf94fd9b6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
@@ -54,7 +54,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
index 6dac066bfaa..a30d16d5327 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
@@ -54,7 +54,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
index 6dac066bfaa..a30d16d5327 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
@@ -54,7 +54,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
index 4ccc4079908..b82a3f9f819 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
@@ -54,7 +54,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 196552020ab..06673d1a73c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -54,7 +54,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace macro proc_macro">}</span> <span class="struct declaration macro proc_macro">Foo</span> <span class="keyword macro proc_macro">struct</span>
 <span class="brace macro proc_macro">}</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">def_fn</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="macro">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
@@ -64,24 +64,24 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace macro">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">dont_color_me_braces</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span>expr
     <span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="comment documentation">/// textually shadow previous definition</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span>expr
     <span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro</span> <span class="macro declaration">with_args</span><span class="parenthesis">(</span><span class="punctuation">$</span>i<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="brace">{</span>
@@ -95,7 +95,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 5594a36e731..1385ae0510a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -46,7 +46,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
         <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span><span class="parenthesis">)</span>
 <span class="brace">}</span>
@@ -74,12 +74,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">reuse_twice</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="colon">:</span>literal<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">{</span>stringify<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="semicolon">;</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="colon">:</span>literal<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">{</span>stringify<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="semicolon">;</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index be6176894b4..4e69c82f3da 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -46,12 +46,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs
index 9bb5de9f2e3..3d9146cc4c7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/typing.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs
@@ -15,12 +15,14 @@
 
 mod on_enter;
 
+use std::iter;
+
 use ide_db::{base_db::SourceDatabase, FilePosition, RootDatabase};
-use span::EditionedFileId;
+use span::{Edition, EditionedFileId};
 use syntax::{
     algo::{ancestors_at_offset, find_node_at_offset},
     ast::{self, edit::IndentLevel, AstToken},
-    AstNode, Parse, SourceFile, SyntaxKind, TextRange, TextSize, T,
+    AstNode, Parse, SourceFile, SyntaxKind, TextRange, TextSize,
 };
 
 use ide_db::text_edit::TextEdit;
@@ -30,7 +32,7 @@ use crate::SourceChange;
 pub(crate) use on_enter::on_enter;
 
 // Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
-pub(crate) const TRIGGER_CHARS: &str = ".=<>{(";
+pub(crate) const TRIGGER_CHARS: &str = ".=<>{(|";
 
 struct ExtendedTextEdit {
     edit: TextEdit,
@@ -47,6 +49,7 @@ struct ExtendedTextEdit {
 // - typing `.` in a chain method call auto-indents
 // - typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression
 // - typing `{` in a use item adds a closing `}` in the right place
+// - typing `>` to complete a return type `->` will insert a whitespace after it
 //
 // VS Code::
 //
@@ -66,55 +69,67 @@ pub(crate) fn on_char_typed(
     if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
         return None;
     }
-    let file = &db.parse(EditionedFileId::current_edition(position.file_id));
-    if !stdx::always!(file.tree().syntax().text().char_at(position.offset) == Some(char_typed)) {
+    // FIXME: We need to figure out the edition of the file here, but that means hitting the
+    // database for more than just parsing the file which is bad.
+    // FIXME: We are hitting the database here, if we are unlucky this call might block momentarily
+    // causing the editor to feel sluggish!
+    let edition = Edition::CURRENT_FIXME;
+    let file = &db.parse(EditionedFileId::new(position.file_id, edition));
+    let char_matches_position =
+        file.tree().syntax().text().char_at(position.offset) == Some(char_typed);
+    if !stdx::always!(char_matches_position) {
         return None;
     }
-    let edit = on_char_typed_inner(file, position.offset, char_typed)?;
+
+    let edit = on_char_typed_(file, position.offset, char_typed, edition)?;
+
     let mut sc = SourceChange::from_text_edit(position.file_id, edit.edit);
     sc.is_snippet = edit.is_snippet;
     Some(sc)
 }
 
-fn on_char_typed_inner(
+fn on_char_typed_(
     file: &Parse<SourceFile>,
     offset: TextSize,
     char_typed: char,
+    edition: Edition,
 ) -> Option<ExtendedTextEdit> {
-    if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
-        return None;
-    }
-    let conv = |text_edit: Option<TextEdit>| {
-        Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
-    };
     match char_typed {
-        '.' => conv(on_dot_typed(&file.tree(), offset)),
-        '=' => conv(on_eq_typed(&file.tree(), offset)),
-        '<' => on_left_angle_typed(&file.tree(), offset),
-        '>' => conv(on_right_angle_typed(&file.tree(), offset)),
-        '{' => conv(on_opening_bracket_typed(file, offset, '{')),
-        '(' => conv(on_opening_bracket_typed(file, offset, '(')),
+        '.' => on_dot_typed(&file.tree(), offset),
+        '=' => on_eq_typed(&file.tree(), offset),
+        '>' => on_right_angle_typed(&file.tree(), offset),
+        '{' | '(' | '<' => on_opening_delimiter_typed(file, offset, char_typed, edition),
+        '|' => on_pipe_typed(&file.tree(), offset),
         _ => None,
     }
+    .map(conv)
+}
+
+fn conv(edit: TextEdit) -> ExtendedTextEdit {
+    ExtendedTextEdit { edit, is_snippet: false }
 }
 
-/// Inserts a closing bracket when the user types an opening bracket, wrapping an existing expression in a
+/// Inserts a closing delimiter when the user types an opening bracket, wrapping an existing expression in a
 /// block, or a part of a `use` item (for `{`).
-fn on_opening_bracket_typed(
+fn on_opening_delimiter_typed(
     file: &Parse<SourceFile>,
     offset: TextSize,
     opening_bracket: char,
+    edition: Edition,
 ) -> Option<TextEdit> {
-    let (closing_bracket, expected_ast_bracket) = match opening_bracket {
-        '{' => ('}', SyntaxKind::L_CURLY),
-        '(' => (')', SyntaxKind::L_PAREN),
+    type FilterFn = fn(SyntaxKind) -> bool;
+    let (closing_bracket, expected_ast_bracket, allowed_kinds) = match opening_bracket {
+        '{' => ('}', SyntaxKind::L_CURLY, &[ast::Expr::can_cast as FilterFn] as &[FilterFn]),
+        '(' => (
+            ')',
+            SyntaxKind::L_PAREN,
+            &[ast::Expr::can_cast as FilterFn, ast::Pat::can_cast, ast::Type::can_cast]
+                as &[FilterFn],
+        ),
+        '<' => ('>', SyntaxKind::L_ANGLE, &[ast::Type::can_cast as FilterFn] as &[FilterFn]),
         _ => return None,
     };
 
-    if !stdx::always!(file.tree().syntax().text().char_at(offset) == Some(opening_bracket)) {
-        return None;
-    }
-
     let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?;
     if brace_token.kind() != expected_ast_bracket {
         return None;
@@ -125,58 +140,53 @@ fn on_opening_bracket_typed(
     if !stdx::always!(range.len() == TextSize::of(opening_bracket)) {
         return None;
     }
-    // FIXME: Edition
-    let file = file.reparse(range, "", span::Edition::CURRENT_FIXME);
+    let reparsed = file.reparse(range, "", edition).tree();
 
-    if let Some(edit) = bracket_expr(&file.tree(), offset, opening_bracket, closing_bracket) {
+    if let Some(edit) =
+        on_delimited_node_typed(&reparsed, offset, opening_bracket, closing_bracket, allowed_kinds)
+    {
         return Some(edit);
     }
 
-    if closing_bracket == '}' {
-        if let Some(edit) = brace_use_path(&file.tree(), offset) {
-            return Some(edit);
-        }
+    match opening_bracket {
+        '{' => on_left_brace_typed(&reparsed, offset),
+        '<' => on_left_angle_typed(&file.tree(), &reparsed, offset),
+        _ => None,
     }
+}
 
-    return None;
-
-    fn brace_use_path(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let segment: ast::PathSegment = find_node_at_offset(file.syntax(), offset)?;
-        if segment.syntax().text_range().start() != offset {
-            return None;
-        }
-
-        let tree: ast::UseTree = find_node_at_offset(file.syntax(), offset)?;
-
-        Some(TextEdit::insert(tree.syntax().text_range().end() + TextSize::of("{"), "}".to_owned()))
+fn on_left_brace_typed(reparsed: &SourceFile, offset: TextSize) -> Option<TextEdit> {
+    let segment: ast::PathSegment = find_node_at_offset(reparsed.syntax(), offset)?;
+    if segment.syntax().text_range().start() != offset {
+        return None;
     }
 
-    fn bracket_expr(
-        file: &SourceFile,
-        offset: TextSize,
-        opening_bracket: char,
-        closing_bracket: char,
-    ) -> Option<TextEdit> {
-        let mut expr: ast::Expr = find_node_at_offset(file.syntax(), offset)?;
-        if expr.syntax().text_range().start() != offset {
-            return None;
-        }
-
-        // Enclose the outermost expression starting at `offset`
-        while let Some(parent) = expr.syntax().parent() {
-            if parent.text_range().start() != expr.syntax().text_range().start() {
-                break;
-            }
+    let tree: ast::UseTree = find_node_at_offset(reparsed.syntax(), offset)?;
 
-            match ast::Expr::cast(parent) {
-                Some(parent) => expr = parent,
-                None => break,
-            }
-        }
+    Some(TextEdit::insert(tree.syntax().text_range().end() + TextSize::of("{"), "}".to_owned()))
+}
 
-        if let Some(parent) = expr.syntax().parent().and_then(ast::Expr::cast) {
-            let mut node = expr.syntax().clone();
-            let all_prev_sib_attr = loop {
+fn on_delimited_node_typed(
+    reparsed: &SourceFile,
+    offset: TextSize,
+    opening_bracket: char,
+    closing_bracket: char,
+    kinds: &[fn(SyntaxKind) -> bool],
+) -> Option<TextEdit> {
+    let t = reparsed.syntax().token_at_offset(offset).right_biased()?;
+    let (filter, node) = t
+        .parent_ancestors()
+        .take_while(|n| n.text_range().start() == offset)
+        .find_map(|n| kinds.iter().find(|&kind_filter| kind_filter(n.kind())).zip(Some(n)))?;
+    let mut node = node
+        .ancestors()
+        .take_while(|n| n.text_range().start() == offset && filter(n.kind()))
+        .last()?;
+
+    if let Some(parent) = node.parent().filter(|it| filter(it.kind())) {
+        let all_prev_sib_attr = {
+            let mut node = node.clone();
+            loop {
                 match node.prev_sibling() {
                     Some(sib) if sib.kind().is_trivia() || sib.kind() == SyntaxKind::ATTR => {
                         node = sib
@@ -184,26 +194,32 @@ fn on_opening_bracket_typed(
                     Some(_) => break false,
                     None => break true,
                 };
-            };
-
-            if all_prev_sib_attr {
-                expr = parent;
             }
-        }
+        };
 
-        // Insert the closing bracket right after the expression.
-        Some(TextEdit::insert(
-            expr.syntax().text_range().end() + TextSize::of(opening_bracket),
-            closing_bracket.to_string(),
-        ))
+        if all_prev_sib_attr {
+            node = parent;
+        }
     }
-}
 
+    // Insert the closing bracket right after the node.
+    Some(TextEdit::insert(
+        node.text_range().end() + TextSize::of(opening_bracket),
+        closing_bracket.to_string(),
+    ))
+}
 /// Returns an edit which should be applied after `=` was typed. Primarily,
 /// this works when adding `let =`.
 // FIXME: use a snippet completion instead of this hack here.
 fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-    if !stdx::always!(file.syntax().text().char_at(offset) == Some('=')) {
+    let text = file.syntax().text();
+    let has_newline = iter::successors(Some(offset), |&offset| Some(offset + TextSize::new(1)))
+        .filter_map(|offset| text.char_at(offset))
+        .find(|&c| !c.is_whitespace() || c == '\n')
+        == Some('n');
+    // don't attempt to add `;` if there is a newline after the `=`, the intent is likely to write
+    // out the expression afterwards!
+    if has_newline {
         return None;
     }
 
@@ -289,9 +305,6 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
 
 /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
 fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-    if !stdx::always!(file.syntax().text().char_at(offset) == Some('.')) {
-        return None;
-    }
     let whitespace =
         file.syntax().token_at_offset(offset).left_biased().and_then(ast::Whitespace::cast)?;
 
@@ -342,14 +355,15 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
 }
 
 /// Add closing `>` for generic arguments/parameters.
-fn on_left_angle_typed(file: &SourceFile, offset: TextSize) -> Option<ExtendedTextEdit> {
-    let file_text = file.syntax().text();
-    if !stdx::always!(file_text.char_at(offset) == Some('<')) {
-        return None;
-    }
+fn on_left_angle_typed(
+    file: &SourceFile,
+    reparsed: &SourceFile,
+    offset: TextSize,
+) -> Option<TextEdit> {
+    let file_text = reparsed.syntax().text();
 
-    // Find the next non-whitespace char in the line.
-    let mut next_offset = offset + TextSize::of('<');
+    // Find the next non-whitespace char in the line, check if its a `>`
+    let mut next_offset = offset;
     while file_text.char_at(next_offset) == Some(' ') {
         next_offset += TextSize::of(' ')
     }
@@ -357,34 +371,36 @@ fn on_left_angle_typed(file: &SourceFile, offset: TextSize) -> Option<ExtendedTe
         return None;
     }
 
-    let range = TextRange::at(offset, TextSize::of('<'));
-    if let Some(t) = file.syntax().token_at_offset(offset).left_biased() {
-        if T![impl] == t.kind() {
-            return Some(ExtendedTextEdit {
-                edit: TextEdit::replace(range, "<$0>".to_owned()),
-                is_snippet: true,
-            });
-        }
-    }
-
-    if ancestors_at_offset(file.syntax(), offset).any(|n| {
-        ast::GenericParamList::can_cast(n.kind()) || ast::GenericArgList::can_cast(n.kind())
-    }) {
-        Some(ExtendedTextEdit {
-            edit: TextEdit::replace(range, "<$0>".to_owned()),
-            is_snippet: true,
+    if ancestors_at_offset(file.syntax(), offset)
+        .take_while(|n| !ast::Item::can_cast(n.kind()))
+        .any(|n| {
+            ast::GenericParamList::can_cast(n.kind())
+                || ast::GenericArgList::can_cast(n.kind())
+                || ast::UseBoundGenericArgs::can_cast(n.kind())
         })
+    {
+        // Insert the closing bracket right after
+        Some(TextEdit::insert(offset + TextSize::of('<'), '>'.to_string()))
     } else {
         None
     }
 }
 
+fn on_pipe_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
+    let pipe_token = file.syntax().token_at_offset(offset).right_biased()?;
+    if pipe_token.kind() != SyntaxKind::PIPE {
+        return None;
+    }
+    if pipe_token.parent().and_then(ast::ParamList::cast)?.r_paren_token().is_some() {
+        return None;
+    }
+    let after_lpipe = offset + TextSize::of('|');
+    Some(TextEdit::insert(after_lpipe, "|".to_owned()))
+}
+
 /// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }`
 fn on_right_angle_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
     let file_text = file.syntax().text();
-    if !stdx::always!(file_text.char_at(offset) == Some('>')) {
-        return None;
-    }
     let after_arrow = offset + TextSize::of('>');
     if file_text.char_at(after_arrow) != Some('{') {
         return None;
@@ -411,7 +427,7 @@ mod tests {
         let edit = TextEdit::insert(offset, char_typed.to_string());
         edit.apply(&mut before);
         let parse = SourceFile::parse(&before, span::Edition::CURRENT_FIXME);
-        on_char_typed_inner(&parse, offset, char_typed).map(|it| {
+        on_char_typed_(&parse, offset, char_typed, span::Edition::CURRENT_FIXME).map(|it| {
             it.apply(&mut before);
             before.to_string()
         })
@@ -426,7 +442,7 @@ mod tests {
 
     fn type_char_noop(char_typed: char, ra_fixture_before: &str) {
         let file_change = do_type_char(char_typed, ra_fixture_before);
-        assert!(file_change.is_none())
+        assert_eq!(file_change, None)
     }
 
     #[test]
@@ -471,6 +487,15 @@ fn foo() {
 }
 ",
         );
+        type_char_noop(
+            '=',
+            r"
+fn foo() {
+    let foo =$0
+     1 + 1
+}
+",
+        );
     }
 
     #[test]
@@ -1067,6 +1092,81 @@ fn f() {
     }
 
     #[test]
+    fn adds_closing_parenthesis_for_pat() {
+        type_char(
+            '(',
+            r#"
+fn f() { match () { $0() => () } }
+"#,
+            r#"
+fn f() { match () { (()) => () } }
+"#,
+        );
+        type_char(
+            '(',
+            r#"
+fn f($0n: ()) {}
+"#,
+            r#"
+fn f((n): ()) {}
+"#,
+        );
+    }
+
+    #[test]
+    fn adds_closing_parenthesis_for_ty() {
+        type_char(
+            '(',
+            r#"
+fn f(n: $0()) {}
+"#,
+            r#"
+fn f(n: (())) {}
+"#,
+        );
+        type_char(
+            '(',
+            r#"
+fn f(n: $0a::b::<d>::c) {}
+"#,
+            r#"
+fn f(n: (a::b::<d>::c)) {}
+"#,
+        );
+    }
+
+    #[test]
+    fn adds_closing_angles_for_ty() {
+        type_char(
+            '<',
+            r#"
+fn f(n: $0()) {}
+"#,
+            r#"
+fn f(n: <()>) {}
+"#,
+        );
+        type_char(
+            '<',
+            r#"
+fn f(n: $0a::b::<d>::c) {}
+"#,
+            r#"
+fn f(n: <a::b::<d>::c>) {}
+"#,
+        );
+        type_char(
+            '<',
+            r#"
+fn f(n: a$0b::<d>::c) {}
+"#,
+            r#"
+fn f(n: a<>b::<d>::c) {}
+"#,
+        );
+    }
+
+    #[test]
     fn parenthesis_noop_in_string_literal() {
         // Regression test for #9351
         type_char_noop(
@@ -1157,6 +1257,12 @@ use $0Thing as _;
 use some::pa$0th::to::Item;
             "#,
         );
+        type_char_noop(
+            '<',
+            r#"
+use some::pa$0th::to::Item;
+            "#,
+        );
     }
 
     #[test]
@@ -1170,7 +1276,7 @@ fn foo() {
             "#,
             r#"
 fn foo() {
-    bar::<$0>
+    bar::<>
 }
             "#,
         );
@@ -1184,7 +1290,7 @@ fn foo(bar: &[u64]) {
             "#,
             r#"
 fn foo(bar: &[u64]) {
-    bar.iter().collect::<$0>();
+    bar.iter().collect::<>();
 }
             "#,
         );
@@ -1198,7 +1304,7 @@ fn foo(bar: &[u64]) {
 fn foo$0() {}
             "#,
             r#"
-fn foo<$0>() {}
+fn foo<>() {}
             "#,
         );
         type_char(
@@ -1207,7 +1313,7 @@ fn foo<$0>() {}
 fn foo$0
             "#,
             r#"
-fn foo<$0>
+fn foo<>
             "#,
         );
         type_char(
@@ -1216,7 +1322,7 @@ fn foo<$0>
 struct Foo$0 {}
             "#,
             r#"
-struct Foo<$0> {}
+struct Foo<> {}
             "#,
         );
         type_char(
@@ -1225,7 +1331,7 @@ struct Foo<$0> {}
 struct Foo$0();
             "#,
             r#"
-struct Foo<$0>();
+struct Foo<>();
             "#,
         );
         type_char(
@@ -1234,7 +1340,7 @@ struct Foo<$0>();
 struct Foo$0
             "#,
             r#"
-struct Foo<$0>
+struct Foo<>
             "#,
         );
         type_char(
@@ -1243,7 +1349,7 @@ struct Foo<$0>
 enum Foo$0
             "#,
             r#"
-enum Foo<$0>
+enum Foo<>
             "#,
         );
         type_char(
@@ -1252,7 +1358,7 @@ enum Foo<$0>
 trait Foo$0
             "#,
             r#"
-trait Foo<$0>
+trait Foo<>
             "#,
         );
         type_char(
@@ -1261,16 +1367,7 @@ trait Foo<$0>
 type Foo$0 = Bar;
             "#,
             r#"
-type Foo<$0> = Bar;
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-impl$0 Foo {}
-            "#,
-            r#"
-impl<$0> Foo {}
+type Foo<> = Bar;
             "#,
         );
         type_char(
@@ -1279,7 +1376,7 @@ impl<$0> Foo {}
 impl<T> Foo$0 {}
             "#,
             r#"
-impl<T> Foo<$0> {}
+impl<T> Foo<> {}
             "#,
         );
         type_char(
@@ -1288,7 +1385,7 @@ impl<T> Foo<$0> {}
 impl Foo$0 {}
             "#,
             r#"
-impl Foo<$0> {}
+impl Foo<> {}
             "#,
         );
     }
@@ -1438,4 +1535,42 @@ fn foo() {
 "#,
         );
     }
+
+    #[test]
+    fn completes_pipe_param_list() {
+        type_char(
+            '|',
+            r#"
+fn foo() {
+    $0
+}
+"#,
+            r#"
+fn foo() {
+    ||
+}
+"#,
+        );
+        type_char(
+            '|',
+            r#"
+fn foo() {
+    $0 a
+}
+"#,
+            r#"
+fn foo() {
+    || a
+}
+"#,
+        );
+        type_char_noop(
+            '|',
+            r#"
+fn foo() {
+    let $0
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
index ef76192ba83..200b14027f8 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
@@ -77,8 +77,12 @@ impl TaggedArcPtr {
     }
 
     /// Retrieves the tag.
+    ///
+    /// # Safety
+    ///
+    /// You can only drop the `Arc` if the instance is dropped.
     #[inline]
-    pub(crate) fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
+    pub(crate) unsafe fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
         // Unpack the tag from the alignment niche
         let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS;
         if tag != 0 {
@@ -245,16 +249,14 @@ impl Symbol {
             }
         }
 
-        ManuallyDrop::into_inner(
-            match shard.raw_entry_mut().from_key_hashed_nocheck::<str>(hash, arc.as_ref()) {
-                RawEntryMut::Occupied(occ) => occ.remove_entry(),
-                RawEntryMut::Vacant(_) => unreachable!(),
-            }
-            .0
-             .0
-            .try_as_arc_owned()
-            .unwrap(),
-        );
+        let ptr = match shard.raw_entry_mut().from_key_hashed_nocheck::<str>(hash, arc.as_ref()) {
+            RawEntryMut::Occupied(occ) => occ.remove_entry(),
+            RawEntryMut::Vacant(_) => unreachable!(),
+        }
+        .0
+         .0;
+        // SAFETY: We're dropping, we have ownership.
+        ManuallyDrop::into_inner(unsafe { ptr.try_as_arc_owned().unwrap() });
         debug_assert_eq!(Arc::count(arc), 1);
 
         // Shrink the backing storage if the shard is less than 50% occupied.
@@ -267,7 +269,8 @@ impl Symbol {
 impl Drop for Symbol {
     #[inline]
     fn drop(&mut self) {
-        let Some(arc) = self.repr.try_as_arc_owned() else {
+        // SAFETY: We're dropping, we have ownership.
+        let Some(arc) = (unsafe { self.repr.try_as_arc_owned() }) else {
             return;
         };
         // When the last `Ref` is dropped, remove the object from the global map.
@@ -288,7 +291,8 @@ impl Clone for Symbol {
 }
 
 fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr {
-    let Some(arc) = repr.try_as_arc_owned() else {
+    // SAFETY: We're not dropping the `Arc`.
+    let Some(arc) = (unsafe { repr.try_as_arc_owned() }) else {
         return repr;
     };
     // increase the ref count
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 865518fe941..1120d3c7d60 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -80,6 +80,7 @@ define_symbols! {
     self_ = "self",
     Self_ = "Self",
     tick_static = "'static",
+    tick_underscore = "'_",
     dollar_crate = "$crate",
     MISSING_NAME = "[missing name]",
     fn_ = "fn",
@@ -99,7 +100,6 @@ define_symbols! {
     cdecl_dash_unwind = "cdecl-unwind",
     fastcall_dash_unwind = "fastcall-unwind",
     msp430_dash_interrupt = "msp430-interrupt",
-    platform_dash_intrinsic = "platform-intrinsic",
     ptx_dash_kernel = "ptx-kernel",
     riscv_dash_interrupt_dash_m = "riscv-interrupt-m",
     riscv_dash_interrupt_dash_s = "riscv-interrupt-s",
@@ -150,6 +150,9 @@ define_symbols! {
     C,
     call_mut,
     call_once,
+    async_call_once,
+    async_call_mut,
+    async_call,
     call,
     cdecl,
     Center,
@@ -221,6 +224,9 @@ define_symbols! {
     fn_mut,
     fn_once_output,
     fn_once,
+    async_fn_once,
+    async_fn_mut,
+    async_fn,
     fn_ptr_addr,
     fn_ptr_trait,
     format_alignment,
@@ -334,6 +340,8 @@ define_symbols! {
     Option,
     Ord,
     Output,
+    CallRefFuture,
+    CallOnceFuture,
     owned_box,
     packed,
     panic_2015,
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 0e1606a6991..cf26845b119 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -123,7 +123,7 @@ pub fn load_workspace(
             .collect()
     };
 
-    let project_folders = ProjectFolders::new(std::slice::from_ref(&ws), &[]);
+    let project_folders = ProjectFolders::new(std::slice::from_ref(&ws), &[], None);
     loader.set_config(vfs::loader::Config {
         load: project_folders.load,
         watch: vec![],
@@ -153,7 +153,11 @@ pub struct ProjectFolders {
 }
 
 impl ProjectFolders {
-    pub fn new(workspaces: &[ProjectWorkspace], global_excludes: &[AbsPathBuf]) -> ProjectFolders {
+    pub fn new(
+        workspaces: &[ProjectWorkspace],
+        global_excludes: &[AbsPathBuf],
+        user_config_dir_path: Option<&AbsPath>,
+    ) -> ProjectFolders {
         let mut res = ProjectFolders::default();
         let mut fsc = FileSetConfig::builder();
         let mut local_filesets = vec![];
@@ -291,6 +295,22 @@ impl ProjectFolders {
             }
         }
 
+        if let Some(user_config_path) = user_config_dir_path {
+            let ratoml_path = {
+                let mut p = user_config_path.to_path_buf();
+                p.push("rust-analyzer.toml");
+                p
+            };
+
+            let file_set_roots = vec![VfsPath::from(ratoml_path.to_owned())];
+            let entry = vfs::loader::Entry::Files(vec![ratoml_path.to_owned()]);
+
+            res.watch.push(res.load.len());
+            res.load.push(entry);
+            local_filesets.push(fsc.len() as u64);
+            fsc.add_file_set(file_set_roots)
+        }
+
         let fsc = fsc.build();
         res.source_root_config = SourceRootConfig { fsc, local_filesets };
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index a50a2182a7b..fe6b904bd88 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -242,7 +242,7 @@ fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
                 // struct MyStruct(pub ());
                 if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
                     p.bump(T!['(']);
-                    paths::use_path(p);
+                    paths::vis_path(p);
                     p.expect(T![')']);
                 }
             }
@@ -252,7 +252,7 @@ fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
             T![in] => {
                 p.bump(T!['(']);
                 p.bump(T![in]);
-                paths::use_path(p);
+                paths::vis_path(p);
                 p.expect(T![')']);
             }
             _ => {}
@@ -307,13 +307,49 @@ fn name(p: &mut Parser<'_>) {
     name_r(p, TokenSet::EMPTY);
 }
 
-fn name_ref(p: &mut Parser<'_>) {
-    if p.at(IDENT) {
+fn name_ref_or_self(p: &mut Parser<'_>) {
+    if matches!(p.current(), T![ident] | T![self]) {
         let m = p.start();
-        p.bump(IDENT);
+        p.bump_any();
+        m.complete(p, NAME_REF);
+    } else {
+        p.err_and_bump("expected identifier or `self`");
+    }
+}
+
+fn name_ref_or_upper_self(p: &mut Parser<'_>) {
+    if matches!(p.current(), T![ident] | T![Self]) {
+        let m = p.start();
+        p.bump_any();
+        m.complete(p, NAME_REF);
+    } else {
+        p.err_and_bump("expected identifier or `Self`");
+    }
+}
+
+const PATH_NAME_REF_KINDS: TokenSet =
+    TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self]]);
+
+fn name_ref_mod_path(p: &mut Parser<'_>) {
+    if p.at_ts(PATH_NAME_REF_KINDS) {
+        let m = p.start();
+        p.bump_any();
+        m.complete(p, NAME_REF);
+    } else {
+        p.err_and_bump("expected identifier, `self`, `super`, `crate`, or `Self`");
+    }
+}
+
+const PATH_NAME_REF_OR_INDEX_KINDS: TokenSet =
+    PATH_NAME_REF_KINDS.union(TokenSet::new(&[INT_NUMBER]));
+
+fn name_ref_mod_path_or_index(p: &mut Parser<'_>) {
+    if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
+        let m = p.start();
+        p.bump_any();
         m.complete(p, NAME_REF);
     } else {
-        p.err_and_bump("expected identifier");
+        p.err_and_bump("expected integer, identifier, `self`, `super`, `crate`, or `Self`");
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
index 82e4d661488..ccb556b2cca 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
@@ -36,6 +36,14 @@ fn attr(p: &mut Parser<'_>, inner: bool) {
     attr.complete(p, ATTR);
 }
 
+// test_err meta_recovery
+// #![]
+// #![p = ]
+// #![p::]
+// #![p:: =]
+// #![unsafe]
+// #![unsafe =]
+
 // test metas
 // #![simple_ident]
 // #![simple::path]
@@ -63,7 +71,7 @@ pub(super) fn meta(p: &mut Parser<'_>) {
     if is_unsafe {
         p.expect(T!['(']);
     }
-    paths::use_path(p);
+    paths::attr_path(p);
 
     match p.current() {
         T![=] => {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index e565874a421..3b3f11be130 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -449,7 +449,9 @@ fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
     let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
     let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
 
-    if p.nth(nth1) == IDENT && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::])) {
+    if PATH_NAME_REF_KINDS.contains(p.nth(nth1))
+        && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::]))
+    {
         return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
     }
 
@@ -510,22 +512,27 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
 //     y.bar::<T>(1, 2,);
 //     x.0.0.call();
 //     x.0. call();
+//     x.0()
 // }
 fn method_call_expr<const FLOAT_RECOVERY: bool>(
     p: &mut Parser<'_>,
     lhs: CompletedMarker,
 ) -> CompletedMarker {
     if FLOAT_RECOVERY {
-        assert!(p.nth(0) == IDENT && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
+        assert!(p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
     } else {
-        assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
+        assert!(
+            p.at(T![.])
+                && PATH_NAME_REF_KINDS.contains(p.nth(1))
+                && (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
+        );
     }
     let m = lhs.precede(p);
     if !FLOAT_RECOVERY {
         p.bump(T![.]);
     }
-    name_ref(p);
-    generic_args::opt_generic_arg_list(p, true);
+    name_ref_mod_path(p);
+    generic_args::opt_generic_arg_list_expr(p);
     if p.at(T!['(']) {
         arg_list(p);
     } else {
@@ -543,6 +550,8 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
 
 // test field_expr
 // fn foo() {
+//     x.self;
+//     x.Self;
 //     x.foo;
 //     x.0.bar;
 //     x.0.1;
@@ -560,8 +569,8 @@ fn field_expr<const FLOAT_RECOVERY: bool>(
     if !FLOAT_RECOVERY {
         p.bump(T![.]);
     }
-    if p.at(IDENT) || p.at(INT_NUMBER) {
-        name_ref_or_index(p);
+    if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
+        name_ref_mod_path_or_index(p);
     } else if p.at(FLOAT_NUMBER) {
         return match p.split_float(m) {
             (true, m) => {
@@ -679,34 +688,37 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
             IDENT | INT_NUMBER if p.nth_at(1, T![::]) => {
                 // test_err record_literal_missing_ellipsis_recovery
                 // fn main() {
-                //     S { S::default() }
+                //     S { S::default() };
+                //     S { 0::default() };
                 // }
                 m.abandon(p);
                 p.expect(T![..]);
                 expr(p);
             }
+            IDENT | INT_NUMBER if p.nth_at(1, T![..]) => {
+                // test_err record_literal_before_ellipsis_recovery
+                // fn main() {
+                //     S { field ..S::default() }
+                //     S { 0 ..S::default() }
+                // }
+                name_ref_or_index(p);
+                p.error("expected `:`");
+                m.complete(p, RECORD_EXPR_FIELD);
+            }
             IDENT | INT_NUMBER => {
-                if p.nth_at(1, T![..]) {
-                    // test_err record_literal_before_ellipsis_recovery
-                    // fn main() {
-                    //     S { field ..S::default() }
-                    // }
+                // test_err record_literal_field_eq_recovery
+                // fn main() {
+                //     S { field = foo }
+                //     S { 0 = foo }
+                // }
+                if p.nth_at(1, T![:]) {
                     name_ref_or_index(p);
-                    p.error("expected `:`");
-                } else {
-                    // test_err record_literal_field_eq_recovery
-                    // fn main() {
-                    //     S { field = foo }
-                    // }
-                    if p.nth_at(1, T![:]) {
-                        name_ref_or_index(p);
-                        p.bump(T![:]);
-                    } else if p.nth_at(1, T![=]) {
-                        name_ref_or_index(p);
-                        p.err_and_bump("expected `:`");
-                    }
-                    expr(p);
+                    p.bump(T![:]);
+                } else if p.nth_at(1, T![=]) {
+                    name_ref_or_index(p);
+                    p.err_and_bump("expected `:`");
                 }
+                expr(p);
                 m.complete(p, RECORD_EXPR_FIELD);
             }
             T![.] if p.at(T![..]) => {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index 97e0392ce15..407320e1d08 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -259,13 +259,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
         type_(p);
         p.expect(T![,]);
         while !p.at(EOF) && !p.at(T![')']) {
-            if p.at(IDENT) || p.at(INT_NUMBER) {
-                name_ref_or_index(p);
-            // } else if p.at(FLOAT_NUMBER) {
-            // FIXME: needs float hack
-            } else {
-                p.err_and_bump("expected field name or number");
-            }
+            name_ref_mod_path_or_index(p);
             if !p.at(T![')']) {
                 p.expect(T![.]);
             }
@@ -351,10 +345,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
             name(p);
             p.bump(T![=]);
             allow_templates = false;
-            true
-        } else {
-            false
-        };
+        }
 
         let op = p.start();
         let dir_spec = p.start();
@@ -405,6 +396,19 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
             op.abandon(p);
             op_n.abandon(p);
             p.err_and_bump("expected asm operand");
+
+            // improves error recovery and handles err_and_bump recovering from `{` which gets
+            // the parser stuck here
+            if p.at(T!['{']) {
+                // test_err bad_asm_expr
+                // fn foo() {
+                //     builtin#asm(
+                //         label crashy = { return; }
+                //     );
+                // }
+                expr(p);
+            }
+
             if p.at(T!['}']) {
                 break;
             }
@@ -465,9 +469,9 @@ fn parse_clobber_abi(p: &mut Parser<'_>) {
 
 fn parse_reg(p: &mut Parser<'_>) {
     p.expect(T!['(']);
-    if p.at(T![ident]) {
+    if p.at_ts(PATH_NAME_REF_KINDS) {
         let m = p.start();
-        name_ref(p);
+        name_ref_mod_path(p);
         m.complete(p, ASM_REG_SPEC);
     } else if p.at(T![string]) {
         let m = p.start();
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
index c62c8a9d3f9..b9d5bff6630 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
@@ -1,14 +1,13 @@
 use super::*;
 
-// test_err generic_arg_list_recover
-// type T = T<0, ,T>;
-pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: bool) {
+// test_err generic_arg_list_recover_expr
+// const _: () = T::<0, ,T>;
+// const _: () = T::<0, ,T>();
+pub(super) fn opt_generic_arg_list_expr(p: &mut Parser<'_>) {
     let m;
     if p.at(T![::]) && p.nth(2) == T![<] {
         m = p.start();
         p.bump(T![::]);
-    } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
-        m = p.start();
     } else {
         return;
     }
@@ -25,7 +24,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo
     m.complete(p, GENERIC_ARG_LIST);
 }
 
-const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
+pub(crate) const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
     LIFETIME_IDENT,
     IDENT,
     T!['{'],
@@ -46,21 +45,27 @@ const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
 const GENERIC_ARG_RECOVERY_SET: TokenSet = TokenSet::new(&[T![>], T![,]]);
 
 // test generic_arg
-// type T = S<i32>;
-fn generic_arg(p: &mut Parser<'_>) -> bool {
+// type T = S<i32, dyn T, fn()>;
+pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
     match p.current() {
         LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p),
         T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
         k if k.is_literal() => const_arg(p),
-        // test associated_type_bounds
-        // fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
+        // test generic_arg_bounds
+        // type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
+        // type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
+        // type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
+        // type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;
 
+        // test edition_2015_dyn_prefix_inside_generic_arg 2015
+        // type A = Foo<dyn T>;
+        T![ident] if !p.edition().at_least_2018() && types::is_dyn_weak(p) => type_arg(p),
         // test macro_inside_generic_arg
         // type A = Foo<syn::Token![_]>;
-        IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
+        k if PATH_NAME_REF_KINDS.contains(k) => {
             let m = p.start();
-            name_ref(p);
-            opt_generic_arg_list(p, false);
+            name_ref_mod_path(p);
+            paths::opt_path_type_args(p);
             match p.current() {
                 T![=] => {
                     p.bump_any();
@@ -88,45 +93,26 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
                 }
                 // test assoc_type_bound
                 // type T = StreamingIterator<Item<'a>: Clone>;
+                // type T = StreamingIterator<Item(T): Clone>;
                 T![:] if !p.at(T![::]) => {
                     generic_params::bounds(p);
                     m.complete(p, ASSOC_TYPE_ARG);
                 }
+                // Turned out to be just a normal path type (mirror `path_or_macro_type`)
                 _ => {
                     let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
                     let m = paths::type_path_for_qualifier(p, m);
-                    m.precede(p).complete(p, PATH_TYPE).precede(p).complete(p, TYPE_ARG);
+                    let m = if p.at(T![!]) && !p.at(T![!=]) {
+                        let m = m.precede(p);
+                        items::macro_call_after_excl(p);
+                        m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_TYPE)
+                    } else {
+                        m.precede(p).complete(p, PATH_TYPE)
+                    };
+                    types::opt_type_bounds_as_dyn_trait_type(p, m).precede(p).complete(p, TYPE_ARG);
                 }
             }
         }
-        IDENT if p.nth_at(1, T!['(']) => {
-            let m = p.start();
-            name_ref(p);
-            if p.nth_at(1, T![..]) {
-                let rtn = p.start();
-                p.bump(T!['(']);
-                p.bump(T![..]);
-                p.expect(T![')']);
-                rtn.complete(p, RETURN_TYPE_SYNTAX);
-                // test return_type_syntax_assoc_type_bound
-                // fn foo<T: Trait<method(..): Send>>() {}
-                generic_params::bounds(p);
-                m.complete(p, ASSOC_TYPE_ARG);
-            } else {
-                params::param_list_fn_trait(p);
-                // test bare_dyn_types_with_paren_as_generic_args
-                // type A = S<Fn(i32)>;
-                // type A = S<Fn(i32) + Send>;
-                // type B = S<Fn(i32) -> i32>;
-                // type C = S<Fn(i32) -> i32 + Send>;
-                opt_ret_type(p);
-                let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
-                let m = paths::type_path_for_qualifier(p, m);
-                let m = m.precede(p).complete(p, PATH_TYPE);
-                let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
-                m.precede(p).complete(p, TYPE_ARG);
-            }
-        }
         _ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
         _ => return false,
     }
@@ -168,10 +154,10 @@ pub(super) fn const_arg_expr(p: &mut Parser<'_>) {
             expressions::literal(p);
             lm.complete(p, PREFIX_EXPR);
         }
-        _ if paths::is_use_path_start(p) => {
+        _ if paths::is_path_start(p) => {
             // This shouldn't be hit by `const_arg`
             let lm = p.start();
-            paths::use_path(p);
+            paths::expr_path(p);
             lm.complete(p, PATH_EXPR);
         }
         _ => {
@@ -190,7 +176,7 @@ pub(super) fn const_arg(p: &mut Parser<'_>) {
     m.complete(p, CONST_ARG);
 }
 
-fn type_arg(p: &mut Parser<'_>) {
+pub(crate) fn type_arg(p: &mut Parser<'_>) {
     let m = p.start();
     types::type_(p);
     m.complete(p, TYPE_ARG);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
index 92311238c23..9d4fdbfaf2e 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
@@ -56,7 +56,7 @@ fn generic_param(p: &mut Parser<'_>, m: Marker) -> bool {
 fn lifetime_param(p: &mut Parser<'_>, m: Marker) {
     assert!(p.at(LIFETIME_IDENT));
     lifetime(p);
-    if p.at(T![:]) {
+    if p.eat(T![:]) {
         lifetime_bounds(p);
     }
     m.complete(p, LIFETIME_PARAM);
@@ -106,14 +106,19 @@ fn const_param(p: &mut Parser<'_>, m: Marker) {
 }
 
 fn lifetime_bounds(p: &mut Parser<'_>) {
-    assert!(p.at(T![:]));
-    p.bump(T![:]);
-    while p.at(LIFETIME_IDENT) {
-        lifetime(p);
+    let marker = p.start();
+    while {
+        if !matches!(p.current(), LIFETIME_IDENT | T![>] | T![,]) {
+            p.error("expected lifetime");
+        }
+
+        type_bound(p)
+    } {
         if !p.eat(T![+]) {
             break;
         }
     }
+    marker.complete(p, TYPE_BOUND_LIST);
 }
 
 // test type_param_bounds
@@ -145,6 +150,9 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
         T![for] => types::for_type(p, false),
         // test precise_capturing
         // fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
+
+        // test_err precise_capturing_invalid
+        // type T = impl use<self, 1>;
         T![use] if p.nth_at(1, T![<]) => {
             p.bump_any();
             let m = p.start();
@@ -156,14 +164,10 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
                 || "expected identifier or lifetime".into(),
                 TokenSet::new(&[T![Self], IDENT, LIFETIME_IDENT]),
                 |p| {
-                    if p.at(T![Self]) {
-                        let m = p.start();
-                        p.bump(T![Self]);
-                        m.complete(p, NAME_REF);
-                    } else if p.at(LIFETIME_IDENT) {
+                    if p.at(LIFETIME_IDENT) {
                         lifetime(p);
                     } else {
-                        name_ref(p);
+                        name_ref_or_upper_self(p);
                     }
                     true
                 },
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index 7d98499008d..8ece5af527d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -254,22 +254,16 @@ fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marke
 
 // test extern_crate
 // extern crate foo;
+// extern crate self;
 fn extern_crate(p: &mut Parser<'_>, m: Marker) {
     p.bump(T![extern]);
     p.bump(T![crate]);
 
-    if p.at(T![self]) {
-        // test extern_crate_self
-        // extern crate self;
-        let m = p.start();
-        p.bump(T![self]);
-        m.complete(p, NAME_REF);
-    } else {
-        name_ref(p);
-    }
+    name_ref_or_self(p);
 
     // test extern_crate_rename
     // extern crate foo as bar;
+    // extern crate self as bar;
     opt_rename(p);
     p.expect(T![;]);
     m.complete(p, EXTERN_CRATE);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
index c535267c165..51ffcd07069 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
@@ -14,12 +14,6 @@ pub(super) fn param_list_fn_def(p: &mut Parser<'_>) {
     list_(p, Flavor::FnDef);
 }
 
-// test param_list_opt_patterns
-// fn foo<F: FnMut(&mut Foo<'a>)>(){}
-pub(super) fn param_list_fn_trait(p: &mut Parser<'_>) {
-    list_(p, Flavor::FnTrait);
-}
-
 pub(super) fn param_list_fn_ptr(p: &mut Parser<'_>) {
     list_(p, Flavor::FnPointer);
 }
@@ -28,10 +22,9 @@ pub(super) fn param_list_closure(p: &mut Parser<'_>) {
     list_(p, Flavor::Closure);
 }
 
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 enum Flavor {
-    FnDef,   // Includes trait fn params; omitted param idents are not supported
-    FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
+    FnDef, // Includes trait fn params; omitted param idents are not supported
     FnPointer,
     Closure,
 }
@@ -41,7 +34,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
 
     let (bra, ket) = match flavor {
         Closure => (T![|], T![|]),
-        FnDef | FnTrait | FnPointer => (T!['('], T![')']),
+        FnDef | FnPointer => (T!['('], T![')']),
     };
 
     let list_marker = p.start();
@@ -119,11 +112,6 @@ fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
                 }
             }
         }
-        // test value_parameters_no_patterns
-        // type F = Box<Fn(i32, &i32, &i32, ())>;
-        Flavor::FnTrait => {
-            types::type_(p);
-        }
         // test fn_pointer_param_ident_path
         // type Foo = fn(Bar::Baz);
         // type Qux = fn(baz: Bar::Baz);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
index 09db921803f..3410505cd46 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
@@ -19,6 +19,14 @@ pub(super) fn use_path(p: &mut Parser<'_>) {
     path(p, Mode::Use);
 }
 
+pub(super) fn vis_path(p: &mut Parser<'_>) {
+    path(p, Mode::Vis);
+}
+
+pub(super) fn attr_path(p: &mut Parser<'_>) {
+    path(p, Mode::Attr);
+}
+
 pub(crate) fn type_path(p: &mut Parser<'_>) {
     path(p, Mode::Type);
 }
@@ -37,15 +45,20 @@ pub(crate) fn type_path_for_qualifier(
 #[derive(Clone, Copy, Eq, PartialEq)]
 enum Mode {
     Use,
+    Attr,
     Type,
     Expr,
+    Vis,
 }
 
-fn path(p: &mut Parser<'_>, mode: Mode) {
+fn path(p: &mut Parser<'_>, mode: Mode) -> Option<CompletedMarker> {
     let path = p.start();
-    path_segment(p, mode, true);
+    if path_segment(p, mode, true).is_none() {
+        path.abandon(p);
+        return None;
+    }
     let qual = path.complete(p, PATH);
-    path_for_qualifier(p, mode, qual);
+    Some(path_for_qualifier(p, mode, qual))
 }
 
 fn path_for_qualifier(
@@ -71,7 +84,7 @@ const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
     items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
 const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
 
-fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
+fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
     let m = p.start();
     // test qual_paths
     // type X = <A as B>::Output;
@@ -93,75 +106,105 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
             p.error("expected `::`");
         }
     } else {
-        let empty = if first {
-            p.eat(T![::]);
-            false
-        } else {
-            true
-        };
-        match p.current() {
-            IDENT => {
-                name_ref(p);
-                opt_path_type_args(p, mode);
-            }
+        let mut empty = if first { !p.eat(T![::]) } else { true };
+        if p.at_ts(PATH_NAME_REF_KINDS) {
             // test crate_path
             // use crate::foo;
-            T![self] | T![super] | T![crate] | T![Self] => {
-                let m = p.start();
-                p.bump_any();
-                m.complete(p, NAME_REF);
-            }
-            _ => {
-                let recover_set = match mode {
-                    Mode::Use => items::ITEM_RECOVERY_SET,
-                    Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
-                    Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
-                };
-                p.err_recover("expected identifier", recover_set);
-                if empty {
-                    // test_err empty_segment
-                    // use crate::;
-                    m.abandon(p);
-                    return;
+            name_ref_mod_path(p);
+            opt_path_args(p, mode);
+        } else {
+            let recover_set = match mode {
+                Mode::Use => items::ITEM_RECOVERY_SET,
+                Mode::Attr => {
+                    items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
                 }
+                Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
+                Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
+                Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
+            };
+            empty &= p.err_recover(
+                "expected identifier, `self`, `super`, `crate`, or `Self`",
+                recover_set,
+            );
+            if empty {
+                // test_err empty_segment
+                // use crate::;
+                m.abandon(p);
+                return None;
             }
-        };
+        }
     }
-    m.complete(p, PATH_SEGMENT);
+    Some(m.complete(p, PATH_SEGMENT))
 }
 
-fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
+pub(crate) fn opt_path_type_args(p: &mut Parser<'_>) {
+    // test typepathfn_with_coloncolon
+    // type F = Start::(Middle) -> (Middle)::End;
+    // type GenericArg = S<Start(Middle)::End>;
+    let m;
+    if p.at(T![::]) && matches!(p.nth(2), T![<] | T!['(']) {
+        m = p.start();
+        p.bump(T![::]);
+    } else if (p.current() == T![<] && p.nth(1) != T![=]) || p.current() == T!['('] {
+        m = p.start();
+    } else {
+        return;
+    }
+    let current = p.current();
+    if current == T![<] {
+        // test_err generic_arg_list_recover
+        // type T = T<0, ,T>;
+        // type T = T::<0, ,T>;
+        delimited(
+            p,
+            T![<],
+            T![>],
+            T![,],
+            || "expected generic argument".into(),
+            generic_args::GENERIC_ARG_FIRST,
+            generic_args::generic_arg,
+        );
+        m.complete(p, GENERIC_ARG_LIST);
+    } else if p.nth_at(1, T![..]) {
+        // test return_type_syntax_in_path
+        // fn foo<T>()
+        // where
+        //     T::method(..): Send,
+        //     method(..): Send,
+        //     method::(..): Send,
+        // {}
+        p.bump(T!['(']);
+        p.bump(T![..]);
+        p.expect(T![')']);
+        m.complete(p, RETURN_TYPE_SYNTAX);
+    } else {
+        // test path_fn_trait_args
+        // type F = Box<Fn(i32) -> ()>;
+        // type F = Box<::Fn(i32) -> ()>;
+        // type F = Box<Fn::(i32) -> ()>;
+        // type F = Box<::Fn::(i32) -> ()>;
+        delimited(
+            p,
+            T!['('],
+            T![')'],
+            T![,],
+            || "expected type".into(),
+            types::TYPE_FIRST,
+            |p| {
+                let progress = types::TYPE_FIRST.contains(p.current());
+                generic_args::type_arg(p);
+                progress
+            },
+        );
+        m.complete(p, PARENTHESIZED_ARG_LIST);
+        opt_ret_type(p);
+    }
+}
+
+fn opt_path_args(p: &mut Parser<'_>, mode: Mode) {
     match mode {
-        Mode::Use => {}
-        Mode::Type => {
-            // test typepathfn_with_coloncolon
-            // type F = Start::(Middle) -> (Middle)::End;
-            // type GenericArg = S<Start(Middle)::End>;
-            if p.at(T![::]) && p.nth_at(2, T!['(']) {
-                p.bump(T![::]);
-            }
-            if p.at(T!['(']) {
-                if p.nth_at(1, T![..]) {
-                    // test return_type_syntax_in_path
-                    // fn foo<T>()
-                    // where
-                    //     T::method(..): Send,
-                    // {}
-                    let rtn = p.start();
-                    p.bump(T!['(']);
-                    p.bump(T![..]);
-                    p.expect(T![')']);
-                    rtn.complete(p, RETURN_TYPE_SYNTAX);
-                } else {
-                    // test path_fn_trait_args
-                    // type F = Box<Fn(i32) -> ()>;
-                    params::param_list_fn_trait(p);
-                    opt_ret_type(p);
-                }
-            } else {
-                generic_args::opt_generic_arg_list(p, false);
-            }
-        }
-        Mode::Expr => generic_args::opt_generic_arg_list(p, true),
+        Mode::Use | Mode::Attr | Mode::Vis => {}
+        Mode::Type => opt_path_type_args(p),
+        Mode::Expr => generic_args::opt_generic_arg_list_expr(p),
     }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index f4e57d3d6f3..0133b7d5d82 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -50,7 +50,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
         // Some path types are not allowed to have bounds (no plus)
         T![<] => path_type_bounds(p, allow_bounds),
         T![ident] if !p.edition().at_least_2018() && is_dyn_weak(p) => dyn_trait_type_weak(p),
-        _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
+        _ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
         LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
         _ => {
             p.err_recover("expected type", TYPE_RECOVERY_SET);
@@ -58,7 +58,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
     }
 }
 
-fn is_dyn_weak(p: &Parser<'_>) -> bool {
+pub(crate) fn is_dyn_weak(p: &Parser<'_>) -> bool {
     const WEAK_DYN_PATH_FIRST: TokenSet = TokenSet::new(&[
         IDENT,
         T![self],
@@ -337,7 +337,7 @@ pub(super) fn path_type(p: &mut Parser<'_>) {
 // test macro_call_type
 // type A = foo!();
 // type B = crate::foo!();
-fn path_or_macro_type_(p: &mut Parser<'_>, allow_bounds: bool) {
+fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
     assert!(paths::is_path_start(p));
     let r = p.start();
     let m = p.start();
diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs
index f6b3783d1ca..75a75f601cf 100644
--- a/src/tools/rust-analyzer/crates/parser/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs
@@ -258,22 +258,25 @@ impl<'t> Parser<'t> {
         self.err_recover(message, TokenSet::EMPTY);
     }
 
-    /// Create an error node and consume the next token.
-    pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
+    /// Create an error node and consume the next token unless it is in the recovery set.
+    ///
+    /// Returns true if recovery kicked in.
+    pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) -> bool {
         if matches!(self.current(), T!['{'] | T!['}']) {
             self.error(message);
-            return;
+            return true;
         }
 
         if self.at_ts(recovery) {
             self.error(message);
-            return;
+            return true;
         }
 
         let m = self.start();
         self.error(message);
         self.bump_any();
         m.complete(self, ERROR);
+        false
     }
 
     fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
@@ -324,10 +327,10 @@ impl Marker {
         self.bomb.defuse();
         let idx = self.pos as usize;
         if idx == p.events.len() - 1 {
-            match p.events.pop() {
-                Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (),
-                _ => unreachable!(),
-            }
+            assert!(matches!(
+                p.events.pop(),
+                Some(Event::Start { kind: TOMBSTONE, forward_parent: None })
+            ));
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 21730244a33..0c9c6ffd715 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -256,6 +256,7 @@ pub enum SyntaxKind {
     OR_PAT,
     PARAM,
     PARAM_LIST,
+    PARENTHESIZED_ARG_LIST,
     PAREN_EXPR,
     PAREN_PAT,
     PAREN_TYPE,
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
index 62b381b6688..003b7fda947 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -39,10 +39,6 @@ mod ok {
     #[test]
     fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); }
     #[test]
-    fn associated_type_bounds() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs");
-    }
-    #[test]
     fn async_trait_bound() {
         run_and_expect_no_errors("test_data/parser/inline/ok/async_trait_bound.rs");
     }
@@ -59,12 +55,6 @@ mod ok {
         );
     }
     #[test]
-    fn bare_dyn_types_with_paren_as_generic_args() {
-        run_and_expect_no_errors(
-            "test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs",
-        );
-    }
-    #[test]
     fn become_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/become_expr.rs"); }
     #[test]
     fn bind_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/bind_pat.rs"); }
@@ -200,6 +190,13 @@ mod ok {
         );
     }
     #[test]
+    fn edition_2015_dyn_prefix_inside_generic_arg() {
+        run_and_expect_no_errors_with_edition(
+            "test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rs",
+            crate::Edition::Edition2015,
+        );
+    }
+    #[test]
     fn effect_blocks() { run_and_expect_no_errors("test_data/parser/inline/ok/effect_blocks.rs"); }
     #[test]
     fn exclusive_range_pat() {
@@ -220,10 +217,6 @@ mod ok {
         run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_rename.rs");
     }
     #[test]
-    fn extern_crate_self() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_self.rs");
-    }
-    #[test]
     fn field_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/field_expr.rs"); }
     #[test]
     fn fn_() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_.rs"); }
@@ -281,6 +274,10 @@ mod ok {
     #[test]
     fn generic_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg.rs"); }
     #[test]
+    fn generic_arg_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg_bounds.rs");
+    }
+    #[test]
     fn generic_param_attribute() {
         run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_attribute.rs");
     }
@@ -423,10 +420,6 @@ mod ok {
     #[test]
     fn param_list() { run_and_expect_no_errors("test_data/parser/inline/ok/param_list.rs"); }
     #[test]
-    fn param_list_opt_patterns() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/param_list_opt_patterns.rs");
-    }
-    #[test]
     fn param_list_vararg() {
         run_and_expect_no_errors("test_data/parser/inline/ok/param_list_vararg.rs");
     }
@@ -521,12 +514,6 @@ mod ok {
     #[test]
     fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); }
     #[test]
-    fn return_type_syntax_assoc_type_bound() {
-        run_and_expect_no_errors(
-            "test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs",
-        );
-    }
-    #[test]
     fn return_type_syntax_in_path() {
         run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
     }
@@ -685,10 +672,6 @@ mod ok {
     #[test]
     fn use_tree_star() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_star.rs"); }
     #[test]
-    fn value_parameters_no_patterns() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/value_parameters_no_patterns.rs");
-    }
-    #[test]
     fn variant_discriminant() {
         run_and_expect_no_errors("test_data/parser/inline/ok/variant_discriminant.rs");
     }
@@ -728,6 +711,8 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/async_without_semicolon.rs");
     }
     #[test]
+    fn bad_asm_expr() { run_and_expect_errors("test_data/parser/inline/err/bad_asm_expr.rs"); }
+    #[test]
     fn comma_after_functional_update_syntax() {
         run_and_expect_errors(
             "test_data/parser/inline/err/comma_after_functional_update_syntax.rs",
@@ -754,6 +739,10 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover.rs");
     }
     #[test]
+    fn generic_arg_list_recover_expr() {
+        run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover_expr.rs");
+    }
+    #[test]
     fn generic_param_list_recover() {
         run_and_expect_errors("test_data/parser/inline/err/generic_param_list_recover.rs");
     }
@@ -772,6 +761,8 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/match_arms_recovery.rs");
     }
     #[test]
+    fn meta_recovery() { run_and_expect_errors("test_data/parser/inline/err/meta_recovery.rs"); }
+    #[test]
     fn method_call_missing_argument_list() {
         run_and_expect_errors("test_data/parser/inline/err/method_call_missing_argument_list.rs");
     }
@@ -788,6 +779,10 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs");
     }
     #[test]
+    fn precise_capturing_invalid() {
+        run_and_expect_errors("test_data/parser/inline/err/precise_capturing_invalid.rs");
+    }
+    #[test]
     fn pub_expr() { run_and_expect_errors("test_data/parser/inline/err/pub_expr.rs"); }
     #[test]
     fn record_literal_before_ellipsis_recovery() {
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast
index 44e192a5fcb..7273c98456e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0004_use_path_bad_segment.rast
@@ -9,7 +9,8 @@ SOURCE_FILE
             NAME_REF
               IDENT "foo"
         COLON2 "::"
-        ERROR
-          INT_NUMBER "92"
+        PATH_SEGMENT
+          ERROR
+            INT_NUMBER "92"
     SEMICOLON ";"
-error 9: expected identifier
+error 9: expected identifier, `self`, `super`, `crate`, or `Self`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
index 207a5c24dff..47daaf7b3b3 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
@@ -39,8 +39,9 @@ SOURCE_FILE
                                         IDENT "lol"
                               R_ANGLE ">"
                         COLON2 "::"
-                        ERROR
-                          L_ANGLE "<"
+                        PATH_SEGMENT
+                          ERROR
+                            L_ANGLE "<"
                   TYPE_ARG
                     PATH_TYPE
                       PATH
@@ -91,8 +92,9 @@ SOURCE_FILE
                               IDENT "lol"
                     R_ANGLE ">"
               COLON2 "::"
-              ERROR
-                L_ANGLE "<"
+              PATH_SEGMENT
+                ERROR
+                  L_ANGLE "<"
         EXPR_STMT
           BIN_EXPR
             PATH_EXPR
@@ -113,10 +115,10 @@ SOURCE_FILE
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
-error 30: expected identifier
+error 30: expected identifier, `self`, `super`, `crate`, or `Self`
 error 31: expected COMMA
 error 37: expected expression
-error 75: expected identifier
+error 75: expected identifier, `self`, `super`, `crate`, or `Self`
 error 76: expected SEMICOLON
 error 82: expected expression
 error 83: expected SEMICOLON
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast
index cd5aa680c65..755b20bb271 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast
@@ -98,7 +98,7 @@ SOURCE_FILE
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
-error 25: expected identifier
+error 25: expected identifier, `self`, `super`, `crate`, or `Self`
 error 39: expected COMMA
 error 39: expected expression
 error 55: expected expression
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast
new file mode 100644
index 00000000000..306446e64dd
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast
@@ -0,0 +1,50 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          ASM_EXPR
+            BUILTIN_KW "builtin"
+            POUND "#"
+            ASM_KW "asm"
+            L_PAREN "("
+            WHITESPACE "\n        "
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "label"
+            WHITESPACE " "
+            NAME
+              IDENT "crashy"
+            WHITESPACE " "
+            EQ "="
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE " "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                  SEMICOLON ";"
+                WHITESPACE " "
+                R_CURLY "}"
+            WHITESPACE "\n    "
+            R_PAREN ")"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 41: expected COMMA
+error 50: expected asm operand
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs
new file mode 100644
index 00000000000..6056f925e33
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    builtin#asm(
+        label crashy = { return; }
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast
index 0fe4ca42d79..172bc099b58 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast
@@ -3,10 +3,7 @@ SOURCE_FILE
     VISIBILITY
       PUB_KW "pub"
       L_PAREN "("
-      PATH
-        PATH_SEGMENT
-          ERROR
-            R_PAREN ")"
+      R_PAREN ")"
     WHITESPACE " "
     STRUCT_KW "struct"
     WHITESPACE " "
@@ -14,5 +11,4 @@ SOURCE_FILE
       IDENT "S"
     SEMICOLON ";"
   WHITESPACE "\n"
-error 4: expected identifier
-error 5: expected R_PAREN
+error 4: expected identifier, `self`, `super`, `crate`, or `Self`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast
index b03f5ad9f7e..7f256218eff 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast
@@ -11,4 +11,4 @@ SOURCE_FILE
         COLON2 "::"
     SEMICOLON ";"
   WHITESPACE "\n"
-error 11: expected identifier
+error 11: expected identifier, `self`, `super`, `crate`, or `Self`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
index 4cf5a3386b9..16183ce9ef5 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
@@ -30,4 +30,37 @@ SOURCE_FILE
             R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "T"
+          GENERIC_ARG_LIST
+            COLON2 "::"
+            L_ANGLE "<"
+            CONST_ARG
+              LITERAL
+                INT_NUMBER "0"
+            COMMA ","
+            WHITESPACE " "
+            ERROR
+              COMMA ","
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "T"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
 error 14: expected generic argument
+error 35: expected generic argument
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
index 7d849aa1bee..aa65a0673a4 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
@@ -1 +1,2 @@
 type T = T<0, ,T>;
+type T = T::<0, ,T>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast
new file mode 100644
index 00000000000..de403d30494
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast
@@ -0,0 +1,79 @@
+SOURCE_FILE
+  CONST
+    CONST_KW "const"
+    WHITESPACE " "
+    UNDERSCORE "_"
+    COLON ":"
+    WHITESPACE " "
+    TUPLE_TYPE
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_EXPR
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "T"
+          GENERIC_ARG_LIST
+            COLON2 "::"
+            L_ANGLE "<"
+            CONST_ARG
+              LITERAL
+                INT_NUMBER "0"
+            COMMA ","
+            WHITESPACE " "
+            ERROR
+              COMMA ","
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "T"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  CONST
+    CONST_KW "const"
+    WHITESPACE " "
+    UNDERSCORE "_"
+    COLON ":"
+    WHITESPACE " "
+    TUPLE_TYPE
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    CALL_EXPR
+      PATH_EXPR
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "T"
+            GENERIC_ARG_LIST
+              COLON2 "::"
+              L_ANGLE "<"
+              CONST_ARG
+                LITERAL
+                  INT_NUMBER "0"
+              COMMA ","
+              WHITESPACE " "
+              ERROR
+                COMMA ","
+              TYPE_ARG
+                PATH_TYPE
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "T"
+              R_ANGLE ">"
+      ARG_LIST
+        L_PAREN "("
+        R_PAREN ")"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 21: expected generic argument
+error 47: expected generic argument
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs
new file mode 100644
index 00000000000..74cc63ac4a0
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs
@@ -0,0 +1,2 @@
+const _: () = T::<0, ,T>;
+const _: () = T::<0, ,T>();
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast
new file mode 100644
index 00000000000..b5c16e0798c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast
@@ -0,0 +1,83 @@
+SOURCE_FILE
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+    R_BRACK "]"
+  WHITESPACE "\n"
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "p"
+      WHITESPACE " "
+      EQ "="
+    WHITESPACE " "
+    R_BRACK "]"
+  WHITESPACE "\n"
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+      PATH
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "p"
+        COLON2 "::"
+    R_BRACK "]"
+  WHITESPACE "\n"
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+      PATH
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "p"
+        COLON2 "::"
+      WHITESPACE " "
+      EQ "="
+    R_BRACK "]"
+  WHITESPACE "\n"
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+      UNSAFE_KW "unsafe"
+    R_BRACK "]"
+  WHITESPACE "\n"
+  ATTR
+    POUND "#"
+    BANG "!"
+    L_BRACK "["
+    META
+      UNSAFE_KW "unsafe"
+      WHITESPACE " "
+      EQ "="
+    R_BRACK "]"
+  WHITESPACE "\n"
+error 3: expected identifier, `self`, `super`, `crate`, or `Self`
+error 11: expected expression
+error 11: expected expression
+error 20: expected identifier, `self`, `super`, `crate`, or `Self`
+error 28: expected identifier, `self`, `super`, `crate`, or `Self`
+error 30: expected expression
+error 30: expected expression
+error 41: expected L_PAREN
+error 41: expected identifier, `self`, `super`, `crate`, or `Self`
+error 41: expected R_PAREN
+error 52: expected L_PAREN
+error 52: expected identifier, `self`, `super`, `crate`, or `Self`
+error 54: expected expression
+error 54: expected expression
+error 54: expected R_PAREN
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rs
new file mode 100644
index 00000000000..51d30adf8b4
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rs
@@ -0,0 +1,6 @@
+#![]
+#![p = ]
+#![p::]
+#![p:: =]
+#![unsafe]
+#![unsafe =]
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rast
new file mode 100644
index 00000000000..5ae184c5feb
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    IMPL_TRAIT_TYPE
+      IMPL_KW "impl"
+      WHITESPACE " "
+      TYPE_BOUND_LIST
+        TYPE_BOUND
+          USE_KW "use"
+          USE_BOUND_GENERIC_ARGS
+            L_ANGLE "<"
+            ERROR
+              SELF_KW "self"
+            COMMA ","
+            WHITESPACE " "
+            ERROR
+              INT_NUMBER "1"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 18: expected identifier or `Self`
+error 24: expected identifier or `Self`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rs
new file mode 100644
index 00000000000..3180338d33f
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/precise_capturing_invalid.rs
@@ -0,0 +1 @@
+type T = impl use<self, 1>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast
index 741b7845e7f..08ae906421c 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast
@@ -12,6 +12,38 @@ SOURCE_FILE
       STMT_LIST
         L_CURLY "{"
         WHITESPACE "\n    "
+        EXPR_STMT
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
+            WHITESPACE " "
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              RECORD_EXPR_FIELD
+                NAME_REF
+                  IDENT "field"
+              WHITESPACE " "
+              DOT2 ".."
+              CALL_EXPR
+                PATH_EXPR
+                  PATH
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "S"
+                    COLON2 "::"
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "default"
+                ARG_LIST
+                  L_PAREN "("
+                  R_PAREN ")"
+              WHITESPACE " "
+              R_CURLY "}"
+        WHITESPACE "\n    "
         RECORD_EXPR
           PATH
             PATH_SEGMENT
@@ -23,7 +55,7 @@ SOURCE_FILE
             WHITESPACE " "
             RECORD_EXPR_FIELD
               NAME_REF
-                IDENT "field"
+                INT_NUMBER "0"
             WHITESPACE " "
             DOT2 ".."
             CALL_EXPR
@@ -47,3 +79,6 @@ SOURCE_FILE
   WHITESPACE "\n"
 error 25: expected `:`
 error 25: expected COMMA
+error 42: expected SEMICOLON
+error 52: expected `:`
+error 52: expected COMMA
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs
index a4e5b2f6933..65398ccb88e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs
@@ -1,3 +1,4 @@
 fn main() {
     S { field ..S::default() }
+    S { 0 ..S::default() }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast
index ad4deeb0b67..ad3b6f208e6 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast
@@ -12,6 +12,31 @@ SOURCE_FILE
       STMT_LIST
         L_CURLY "{"
         WHITESPACE "\n    "
+        EXPR_STMT
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
+            WHITESPACE " "
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              RECORD_EXPR_FIELD
+                NAME_REF
+                  IDENT "field"
+                WHITESPACE " "
+                ERROR
+                  EQ "="
+                WHITESPACE " "
+                PATH_EXPR
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "foo"
+              WHITESPACE " "
+              R_CURLY "}"
+        WHITESPACE "\n    "
         RECORD_EXPR
           PATH
             PATH_SEGMENT
@@ -23,7 +48,7 @@ SOURCE_FILE
             WHITESPACE " "
             RECORD_EXPR_FIELD
               NAME_REF
-                IDENT "field"
+                INT_NUMBER "0"
               WHITESPACE " "
               ERROR
                 EQ "="
@@ -39,3 +64,5 @@ SOURCE_FILE
         R_CURLY "}"
   WHITESPACE "\n"
 error 26: expected `:`
+error 33: expected SEMICOLON
+error 44: expected `:`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs
index 1eb1aa9b926..9ddc46e0daf 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs
@@ -1,3 +1,4 @@
 fn main() {
     S { field = foo }
+    S { 0 = foo }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast
index 0c5b618e6f0..9cd07d2ea38 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast
@@ -12,32 +12,70 @@ SOURCE_FILE
       STMT_LIST
         L_CURLY "{"
         WHITESPACE "\n    "
-        RECORD_EXPR
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "S"
-          WHITESPACE " "
-          RECORD_EXPR_FIELD_LIST
-            L_CURLY "{"
+        EXPR_STMT
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
             WHITESPACE " "
-            CALL_EXPR
-              PATH_EXPR
-                PATH
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              CALL_EXPR
+                PATH_EXPR
                   PATH
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "S"
+                    COLON2 "::"
                     PATH_SEGMENT
                       NAME_REF
-                        IDENT "S"
-                  COLON2 "::"
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "default"
-              ARG_LIST
-                L_PAREN "("
-                R_PAREN ")"
+                        IDENT "default"
+                ARG_LIST
+                  L_PAREN "("
+                  R_PAREN ")"
+              WHITESPACE " "
+              R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
             WHITESPACE " "
-            R_CURLY "}"
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              LITERAL
+                INT_NUMBER "0"
+              ERROR
+                COLON ":"
+              ERROR
+                COLON ":"
+              RECORD_EXPR_FIELD
+                CALL_EXPR
+                  PATH_EXPR
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "default"
+                  ARG_LIST
+                    L_PAREN "("
+                    R_PAREN ")"
+              WHITESPACE " "
+              R_CURLY "}"
+          SEMICOLON ";"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
 error 19: expected DOT2
+error 43: expected DOT2
+error 45: expected COMMA
+error 45: expected identifier
+error 46: expected COMMA
+error 46: expected identifier
+error 47: expected COMMA
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs
index 1b594e8ab96..a63c3c9e7c2 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs
@@ -1,3 +1,4 @@
 fn main() {
-    S { S::default() }
+    S { S::default() };
+    S { 0::default() };
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
index f2e4e01069c..0f62e1dd184 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
@@ -35,3 +35,42 @@ SOURCE_FILE
             R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "StreamingIterator"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Clone"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
index daae97e4fd5..83fea1c6c87 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
@@ -1 +1,2 @@
 type T = StreamingIterator<Item<'a>: Clone>;
+type T = StreamingIterator<Item(T): Clone>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
deleted file mode 100644
index 8cbc98c51ca..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
+++ /dev/null
@@ -1,111 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "print_all"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "T"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "Iterator"
-                  GENERIC_ARG_LIST
-                    L_ANGLE "<"
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    COMMA ","
-                    WHITESPACE " "
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Item"
-                          COLON2 "::"
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    COMMA ","
-                    WHITESPACE " "
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                            GENERIC_ARG_LIST
-                              COLON2 "::"
-                              L_ANGLE "<"
-                              CONST_ARG
-                                LITERAL
-                                  TRUE_KW "true"
-                              R_ANGLE ">"
-                    COMMA ","
-                    WHITESPACE " "
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "Item"
-                      COLON ":"
-                      WHITESPACE " "
-                      TYPE_BOUND_LIST
-                        TYPE_BOUND
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "Display"
-                    COMMA ","
-                    WHITESPACE " "
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "Item"
-                      GENERIC_ARG_LIST
-                        L_ANGLE "<"
-                        LIFETIME_ARG
-                          LIFETIME
-                            LIFETIME_IDENT "'a"
-                        R_ANGLE ">"
-                      WHITESPACE " "
-                      EQ "="
-                      WHITESPACE " "
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    R_ANGLE ">"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      PARAM
-        IDENT_PAT
-          NAME
-            IDENT "printables"
-        COLON ":"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "T"
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
deleted file mode 100644
index 0f7a2d16083..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
index ebf758286a7..df0ba55d03d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
@@ -23,9 +23,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "Fn"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         REF_TYPE
                           AMP "&"
                           PATH_TYPE
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
deleted file mode 100644
index d5f97bad898..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
+++ /dev/null
@@ -1,175 +0,0 @@
-SOURCE_FILE
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "A"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      R_PAREN ")"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "A"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              DYN_TRAIT_TYPE
-                TYPE_BOUND_LIST
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Fn"
-                          PARAM_LIST
-                            L_PAREN "("
-                            PARAM
-                              PATH_TYPE
-                                PATH
-                                  PATH_SEGMENT
-                                    NAME_REF
-                                      IDENT "i32"
-                            R_PAREN ")"
-                  WHITESPACE " "
-                  PLUS "+"
-                  WHITESPACE " "
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Send"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "B"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      R_PAREN ")"
-                    WHITESPACE " "
-                    RET_TYPE
-                      THIN_ARROW "->"
-                      WHITESPACE " "
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "i32"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "C"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              DYN_TRAIT_TYPE
-                TYPE_BOUND_LIST
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Fn"
-                          PARAM_LIST
-                            L_PAREN "("
-                            PARAM
-                              PATH_TYPE
-                                PATH
-                                  PATH_SEGMENT
-                                    NAME_REF
-                                      IDENT "i32"
-                            R_PAREN ")"
-                          WHITESPACE " "
-                          RET_TYPE
-                            THIN_ARROW "->"
-                            WHITESPACE " "
-                            PATH_TYPE
-                              PATH
-                                PATH_SEGMENT
-                                  NAME_REF
-                                    IDENT "i32"
-                  WHITESPACE " "
-                  PLUS "+"
-                  WHITESPACE " "
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Send"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
deleted file mode 100644
index 800002b1b82..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-type A = S<Fn(i32)>;
-type A = S<Fn(i32) + Send>;
-type B = S<Fn(i32) -> i32>;
-type C = S<Fn(i32) -> i32 + Send>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rast
new file mode 100644
index 00000000000..24e671b3438
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rast
@@ -0,0 +1,32 @@
+SOURCE_FILE
+  TYPE_ALIAS
+    COMMENT "// 2015"
+    WHITESPACE "\n"
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "A"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              DYN_TRAIT_TYPE
+                DYN_KW "dyn"
+                WHITESPACE " "
+                TYPE_BOUND_LIST
+                  TYPE_BOUND
+                    PATH_TYPE
+                      PATH
+                        PATH_SEGMENT
+                          NAME_REF
+                            IDENT "T"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rs
new file mode 100644
index 00000000000..84cece5748d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/edition_2015_dyn_prefix_inside_generic_arg.rs
@@ -0,0 +1,2 @@
+// 2015
+type A = Foo<dyn T>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast
index 0a660957d15..aa555ed2293 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast
@@ -8,3 +8,12 @@ SOURCE_FILE
       IDENT "foo"
     SEMICOLON ";"
   WHITESPACE "\n"
+  EXTERN_CRATE
+    EXTERN_KW "extern"
+    WHITESPACE " "
+    CRATE_KW "crate"
+    WHITESPACE " "
+    NAME_REF
+      SELF_KW "self"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs
index 49af74e1b74..3c498c8738f 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs
@@ -1 +1,2 @@
 extern crate foo;
+extern crate self;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast
index 5a5aca96f91..5f0a5b5bb05 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast
@@ -14,3 +14,18 @@ SOURCE_FILE
         IDENT "bar"
     SEMICOLON ";"
   WHITESPACE "\n"
+  EXTERN_CRATE
+    EXTERN_KW "extern"
+    WHITESPACE " "
+    CRATE_KW "crate"
+    WHITESPACE " "
+    NAME_REF
+      SELF_KW "self"
+    WHITESPACE " "
+    RENAME
+      AS_KW "as"
+      WHITESPACE " "
+      NAME
+        IDENT "bar"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs
index fc76e17dda4..6d1873d659e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs
@@ -1 +1,2 @@
 extern crate foo as bar;
+extern crate self as bar;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast
deleted file mode 100644
index edea4245f20..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast
+++ /dev/null
@@ -1,10 +0,0 @@
-SOURCE_FILE
-  EXTERN_CRATE
-    EXTERN_KW "extern"
-    WHITESPACE " "
-    CRATE_KW "crate"
-    WHITESPACE " "
-    NAME_REF
-      SELF_KW "self"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs
deleted file mode 100644
index c969ed10936..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs
+++ /dev/null
@@ -1 +0,0 @@
-extern crate self;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast
index dd27dc48964..3bac226d343 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast
@@ -21,6 +21,30 @@ SOURCE_FILE
                     IDENT "x"
             DOT "."
             NAME_REF
+              SELF_KW "self"
+          SEMICOLON ";"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          FIELD_EXPR
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "x"
+            DOT "."
+            NAME_REF
+              SELF_TYPE_KW "Self"
+          SEMICOLON ";"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          FIELD_EXPR
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "x"
+            DOT "."
+            NAME_REF
               IDENT "foo"
           SEMICOLON ";"
         WHITESPACE "\n    "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs
index 98dbe45a7ec..b156d6f7d88 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs
@@ -1,4 +1,6 @@
 fn foo() {
+    x.self;
+    x.Self;
     x.foo;
     x.0.bar;
     x.0.1;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast
index 5a01f154bad..e32cf085657 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast
@@ -20,6 +20,27 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "i32"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              DYN_TRAIT_TYPE
+                DYN_KW "dyn"
+                WHITESPACE " "
+                TYPE_BOUND_LIST
+                  TYPE_BOUND
+                    PATH_TYPE
+                      PATH
+                        PATH_SEGMENT
+                          NAME_REF
+                            IDENT "T"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              FN_PTR_TYPE
+                FN_KW "fn"
+                PARAM_LIST
+                  L_PAREN "("
+                  R_PAREN ")"
             R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs
index f2ccc558bb5..cf991b5b366 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs
@@ -1 +1 @@
-type T = S<i32>;
+type T = S<i32, dyn T, fn()>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast
new file mode 100644
index 00000000000..fee5913acaa
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast
@@ -0,0 +1,461 @@
+SOURCE_FILE
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "Plain"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "Item"
+                  COLON2 "::"
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "GenericArgs"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    GENERIC_ARG_LIST
+                      L_ANGLE "<"
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_ANGLE ">"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    GENERIC_ARG_LIST
+                      COLON2 "::"
+                      L_ANGLE "<"
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_ANGLE ">"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                COLON2 "::"
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                COLON2 "::"
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "ParenthesizedArgs"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    PARENTHESIZED_ARG_LIST
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                COLON2 "::"
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                COLON2 "::"
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "RTN"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    RETURN_TYPE_SYNTAX
+                      L_PAREN "("
+                      DOT2 ".."
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    RETURN_TYPE_SYNTAX
+                      L_PAREN "("
+                      DOT2 ".."
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs
new file mode 100644
index 00000000000..1abd0aeb592
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs
@@ -0,0 +1,4 @@
+type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
+type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
+type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
+type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast
index c595031f358..315200aca21 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast
@@ -11,8 +11,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
       R_ANGLE ">"
     PARAM_LIST
       L_PAREN "("
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast
index b28b8eb673a..3245042cf24 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast
@@ -101,6 +101,20 @@ SOURCE_FILE
               L_PAREN "("
               R_PAREN ")"
           SEMICOLON ";"
+        WHITESPACE "\n    "
+        CALL_EXPR
+          FIELD_EXPR
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "x"
+            DOT "."
+            NAME_REF
+              INT_NUMBER "0"
+          ARG_LIST
+            L_PAREN "("
+            R_PAREN ")"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs
index 48bb6381e80..bb54d75c19b 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs
@@ -3,4 +3,5 @@ fn foo() {
     y.bar::<T>(1, 2,);
     x.0.0.call();
     x.0. call();
+    x.0()
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
deleted file mode 100644
index e9d93a0d0a4..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
+++ /dev/null
@@ -1,48 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "F"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "FnMut"
-                  PARAM_LIST
-                    L_PAREN "("
-                    PARAM
-                      REF_TYPE
-                        AMP "&"
-                        MUT_KW "mut"
-                        WHITESPACE " "
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Foo"
-                              GENERIC_ARG_LIST
-                                L_ANGLE "<"
-                                LIFETIME_ARG
-                                  LIFETIME
-                                    LIFETIME_IDENT "'a"
-                                R_ANGLE ">"
-                    R_PAREN ")"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
deleted file mode 100644
index 9b93442c0f2..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo<F: FnMut(&mut Foo<'a>)>(){}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
index fd83daf841f..924f7ba2c9d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
@@ -20,9 +20,133 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "Fn"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    COLON2 "::"
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    COLON2 "::"
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
                         PATH_TYPE
                           PATH
                             PATH_SEGMENT
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
index 17ed20e5b13..7aa655d7ea9 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
@@ -1 +1,4 @@
 type F = Box<Fn(i32) -> ()>;
+type F = Box<::Fn(i32) -> ()>;
+type F = Box<Fn::(i32) -> ()>;
+type F = Box<::Fn::(i32) -> ()>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/precise_capturing.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/precise_capturing.rast
index f9c0a245af8..5a67cc21766 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/precise_capturing.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/precise_capturing.rast
@@ -11,8 +11,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'a"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'a"
       COMMA ","
       WHITESPACE " "
       LIFETIME_PARAM
@@ -20,8 +22,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'b"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
       COMMA ","
       WHITESPACE " "
       TYPE_PARAM
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast
deleted file mode 100644
index 30e0e73bbd6..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast
+++ /dev/null
@@ -1,49 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "T"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "Trait"
-                  GENERIC_ARG_LIST
-                    L_ANGLE "<"
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "method"
-                      RETURN_TYPE_SYNTAX
-                        L_PAREN "("
-                        DOT2 ".."
-                        R_PAREN ")"
-                      COLON ":"
-                      WHITESPACE " "
-                      TYPE_BOUND_LIST
-                        TYPE_BOUND
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "Send"
-                    R_ANGLE ">"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs
deleted file mode 100644
index 8a4cf4c3a07..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo<T: Trait<method(..): Send>>() {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
index 501dccd79db..15a0558b53d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
@@ -42,6 +42,49 @@ SOURCE_FILE
                   NAME_REF
                     IDENT "Send"
       COMMA ","
+      WHITESPACE "\n    "
+      WHERE_PRED
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "method"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+        COLON ":"
+        WHITESPACE " "
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "Send"
+      COMMA ","
+      WHITESPACE "\n    "
+      WHERE_PRED
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "method"
+              RETURN_TYPE_SYNTAX
+                COLON2 "::"
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+        COLON ":"
+        WHITESPACE " "
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "Send"
+      COMMA ","
     WHITESPACE "\n"
     BLOCK_EXPR
       STMT_LIST
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
index a9b63fb01c8..64b48c1638e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
@@ -1,4 +1,6 @@
 fn foo<T>()
 where
     T::method(..): Send,
+    method(..): Send,
+    method::(..): Send,
 {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
index 67277d0639a..fb442bfb739 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
@@ -13,10 +13,10 @@ SOURCE_FILE
           PATH_SEGMENT
             NAME_REF
               IDENT "Start"
-            COLON2 "::"
-            PARAM_LIST
+            PARENTHESIZED_ARG_LIST
+              COLON2 "::"
               L_PAREN "("
-              PARAM
+              TYPE_ARG
                 PATH_TYPE
                   PATH
                     PATH_SEGMENT
@@ -63,9 +63,9 @@ SOURCE_FILE
                     PATH_SEGMENT
                       NAME_REF
                         IDENT "Start"
-                      PARAM_LIST
+                      PARENTHESIZED_ARG_LIST
                         L_PAREN "("
-                        PARAM
+                        TYPE_ARG
                           PATH_TYPE
                             PATH
                               PATH_SEGMENT
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
deleted file mode 100644
index 902b06484c8..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
+++ /dev/null
@@ -1,60 +0,0 @@
-SOURCE_FILE
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "F"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "Box"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        REF_TYPE
-                          AMP "&"
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        REF_TYPE
-                          AMP "&"
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        TUPLE_TYPE
-                          L_PAREN "("
-                          R_PAREN ")"
-                      R_PAREN ")"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
deleted file mode 100644
index 93636e926e1..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
+++ /dev/null
@@ -1 +0,0 @@
-type F = Box<Fn(i32, &i32, &i32, ())>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
index 8407e99f614..0cc365efbe6 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
@@ -40,9 +40,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0018_struct_type_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0018_struct_type_params.rast
index 11ebc7efb9f..1e4eb156095 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0018_struct_type_params.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0018_struct_type_params.rast
@@ -96,6 +96,7 @@ SOURCE_FILE
         LIFETIME
           LIFETIME_IDENT "'a"
         COLON ":"
+        TYPE_BOUND_LIST
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
@@ -111,8 +112,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
@@ -128,10 +131,12 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
-        WHITESPACE " "
-        PLUS "+"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
+          WHITESPACE " "
+          PLUS "+"
       WHITESPACE " "
       R_ANGLE ">"
     SEMICOLON ";"
@@ -148,13 +153,16 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
-        WHITESPACE " "
-        PLUS "+"
-        WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'c"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
+          WHITESPACE " "
+          PLUS "+"
+          WHITESPACE " "
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'c"
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
@@ -202,9 +210,11 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
-        PLUS "+"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
+          PLUS "+"
       COMMA ","
       WHITESPACE " "
       LIFETIME_PARAM
@@ -212,8 +222,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'b"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'c"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'c"
       COMMA ","
       R_ANGLE ">"
     SEMICOLON ";"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0020_type_param_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0020_type_param_bounds.rast
index 043a966ff97..448cf49446e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0020_type_param_bounds.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0020_type_param_bounds.rast
@@ -237,8 +237,10 @@ SOURCE_FILE
           LIFETIME_IDENT "'a"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'d"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'d"
       COMMA ","
       WHITESPACE " "
       LIFETIME_PARAM
@@ -246,13 +248,16 @@ SOURCE_FILE
           LIFETIME_IDENT "'d"
         COLON ":"
         WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'a"
-        WHITESPACE " "
-        PLUS "+"
-        WHITESPACE " "
-        LIFETIME
-          LIFETIME_IDENT "'b"
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'a"
+          WHITESPACE " "
+          PLUS "+"
+          WHITESPACE " "
+          TYPE_BOUND
+            LIFETIME
+              LIFETIME_IDENT "'b"
       COMMA ","
       WHITESPACE " "
       TYPE_PARAM
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
index fad574a4769..c22d99f1ae1 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
@@ -180,7 +180,7 @@ SOURCE_FILE
                       PATH_SEGMENT
                         NAME_REF
                           IDENT "Fn"
-                        PARAM_LIST
+                        PARENTHESIZED_ARG_LIST
                           L_PAREN "("
                           R_PAREN ")"
                         WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
index f8b11e7782c..eafee90db42 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
@@ -138,63 +138,6 @@ SOURCE_FILE
       WHITESPACE " "
       R_CURLY "}"
   WHITESPACE "\n\n"
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "F"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "FnMut"
-                  PARAM_LIST
-                    L_PAREN "("
-                    PARAM
-                      ATTR
-                        POUND "#"
-                        L_BRACK "["
-                        META
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "attr"
-                        R_BRACK "]"
-                      WHITESPACE " "
-                      REF_TYPE
-                        AMP "&"
-                        MUT_KW "mut"
-                        WHITESPACE " "
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Foo"
-                              GENERIC_ARG_LIST
-                                L_ANGLE "<"
-                                LIFETIME_ARG
-                                  LIFETIME
-                                    LIFETIME_IDENT "'a"
-                                R_ANGLE ">"
-                    R_PAREN ")"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n\n"
   TRAIT
     TRAIT_KW "trait"
     WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
index de350d8587a..0a0100e5d00 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
@@ -3,8 +3,6 @@ fn g2(#[attr1] x: u8) {}
 
 extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
 
-fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
-
 trait Foo {
     fn bar(#[attr] _: u64, # [attr] mut x: i32);
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
index 4e1e31f3767..31cca601ca2 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
@@ -58,9 +58,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "FnMut"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         PATH_TYPE
                           PATH
                             PATH
@@ -101,9 +101,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "FnMut"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         REF_TYPE
                           AMP "&"
                           PATH_TYPE
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
index ba7b6042a9e..d7ee11077cd 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
@@ -32,7 +32,7 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
                     R_PAREN ")"
                   WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
index 136fce93d7e..cd3b21ae94f 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
@@ -40,9 +40,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
@@ -165,9 +165,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index f5ba71fcd05..988eff9be44 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -747,17 +747,14 @@ impl ProjectWorkspace {
         let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered();
 
         let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
-        let ((mut crate_graph, proc_macros), sysroot) = match kind {
-            ProjectWorkspaceKind::Json(project) => (
-                project_json_to_crate_graph(
-                    rustc_cfg.clone(),
-                    load,
-                    project,
-                    sysroot,
-                    extra_env,
-                    cfg_overrides,
-                ),
+        let (crate_graph, proc_macros) = match kind {
+            ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
+                rustc_cfg.clone(),
+                load,
+                project,
                 sysroot,
+                extra_env,
+                cfg_overrides,
             ),
             ProjectWorkspaceKind::Cargo {
                 cargo,
@@ -766,20 +763,17 @@ impl ProjectWorkspace {
                 cargo_config_extra_env: _,
                 error: _,
                 set_test,
-            } => (
-                cargo_to_crate_graph(
-                    load,
-                    rustc.as_ref().map(|a| a.as_ref()).ok(),
-                    cargo,
-                    sysroot,
-                    rustc_cfg.clone(),
-                    cfg_overrides,
-                    build_scripts,
-                    *set_test,
-                ),
+            } => cargo_to_crate_graph(
+                load,
+                rustc.as_ref().map(|a| a.as_ref()).ok(),
+                cargo,
                 sysroot,
+                rustc_cfg.clone(),
+                cfg_overrides,
+                build_scripts,
+                *set_test,
             ),
-            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => (
+            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => {
                 if let Some((cargo, build_scripts, _)) = cargo_script {
                     cargo_to_crate_graph(
                         &mut |path| load(path),
@@ -800,16 +794,10 @@ impl ProjectWorkspace {
                         cfg_overrides,
                         *set_test,
                     )
-                },
-                sysroot,
-            ),
+                }
+            }
         };
 
-        if matches!(sysroot.mode(), SysrootMode::Stitched(_)) && crate_graph.patch_cfg_if() {
-            debug!("Patched std to depend on cfg-if")
-        } else {
-            debug!("Did not patch std to depend on cfg-if")
-        }
         (crate_graph, proc_macros)
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 2dd2f2242a0..7c8610280b3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -21,9 +21,11 @@ path = "src/bin/main.rs"
 
 [dependencies]
 anyhow.workspace = true
+base64 = "0.22"
 crossbeam-channel.workspace = true
 dirs = "5.0.1"
 dissimilar.workspace = true
+ide-completion.workspace = true
 itertools.workspace = true
 scip = "0.5.1"
 lsp-types = { version = "=0.95.0", features = ["proposed"] }
@@ -34,6 +36,7 @@ rayon.workspace = true
 rustc-hash.workspace = true
 serde_json = { workspace = true, features = ["preserve_order"] }
 serde.workspace = true
+tenthash = "0.4.0"
 num_cpus = "1.15.0"
 mimalloc = { version = "0.1.30", default-features = false, optional = true }
 lsp-server.workspace = true
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index e872585c571..eac33be5664 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -20,7 +20,6 @@ use rust_analyzer::{
     config::{Config, ConfigChange, ConfigErrors},
     from_json,
 };
-use semver::Version;
 use tracing_subscriber::fmt::writer::BoxMakeWriter;
 use vfs::AbsPathBuf;
 
@@ -204,18 +203,12 @@ fn run_server() -> anyhow::Result<()> {
         }
     };
 
-    let mut visual_studio_code_version = None;
-    if let Some(client_info) = client_info {
+    if let Some(client_info) = &client_info {
         tracing::info!(
             "Client '{}' {}",
             client_info.name,
             client_info.version.as_deref().unwrap_or_default()
         );
-        visual_studio_code_version = client_info
-            .name
-            .starts_with("Visual Studio Code")
-            .then(|| client_info.version.as_deref().map(Version::parse).and_then(Result::ok))
-            .flatten();
     }
 
     let workspace_roots = workspace_folders
@@ -230,8 +223,7 @@ fn run_server() -> anyhow::Result<()> {
         })
         .filter(|workspaces| !workspaces.is_empty())
         .unwrap_or_else(|| vec![root_path.clone()]);
-    let mut config =
-        Config::new(root_path, capabilities, workspace_roots, visual_studio_code_version);
+    let mut config = Config::new(root_path, capabilities, workspace_roots, client_info);
     if let Some(json) = initialization_options {
         let mut change = ConfigChange::default();
         change.change_client_config(json);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 802d0c69a47..e3ea441f3ab 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -13,8 +13,9 @@ use hir::{
     ModuleDef, Name,
 };
 use hir_def::{
-    body::{BodySourceMap, SyntheticSyntax},
+    body::BodySourceMap,
     hir::{ExprId, PatId},
+    SyntheticSyntax,
 };
 use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
 use ide::{
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 37d45255e29..bf7aca42faf 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -3,11 +3,7 @@
 //! Of particular interest is the `feature_flags` hash map: while other fields
 //! configure the server itself, feature flags are passed into analysis, and
 //! tweak things like automatic insertion of `()` in completions.
-use std::{
-    env, fmt, iter,
-    ops::Not,
-    sync::{LazyLock, OnceLock},
-};
+use std::{env, fmt, iter, ops::Not, sync::OnceLock};
 
 use cfg::{CfgAtom, CfgDiff};
 use hir::Symbol;
@@ -308,8 +304,8 @@ config_data! {
         /// Show documentation.
         signatureInfo_documentation_enable: bool                       = true,
 
-        /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.
-        typing_autoClosingAngleBrackets_enable: bool = false,
+        /// Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.
+        typing_excludeChars: Option<String> = Some("|<".to_owned()),
 
 
         /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].
@@ -730,6 +726,12 @@ enum RatomlFile {
     Crate(LocalConfigInput),
 }
 
+#[derive(Clone, Debug)]
+struct ClientInfo {
+    name: String,
+    version: Option<Version>,
+}
+
 #[derive(Clone)]
 pub struct Config {
     /// Projects that have a Cargo.toml or a rust-project.json in a
@@ -744,7 +746,7 @@ pub struct Config {
     caps: ClientCapabilities,
     root_path: AbsPathBuf,
     snippets: Vec<Snippet>,
-    visual_studio_code_version: Option<Version>,
+    client_info: Option<ClientInfo>,
 
     default_config: &'static DefaultConfigData,
     /// Config node that obtains its initial value during the server initialization and
@@ -777,7 +779,7 @@ impl fmt::Debug for Config {
             .field("caps", &self.caps)
             .field("root_path", &self.root_path)
             .field("snippets", &self.snippets)
-            .field("visual_studio_code_version", &self.visual_studio_code_version)
+            .field("client_info", &self.client_info)
             .field("client_config", &self.client_config)
             .field("user_config", &self.user_config)
             .field("ratoml_file", &self.ratoml_file)
@@ -798,25 +800,14 @@ impl std::ops::Deref for Config {
 }
 
 impl Config {
-    /// Path to the root configuration file. This can be seen as a generic way to define what would be `$XDG_CONFIG_HOME/rust-analyzer/rust-analyzer.toml` in Linux.
-    /// This path is equal to:
-    ///
-    /// |Platform | Value                                 | Example                                  |
-    /// | ------- | ------------------------------------- | ---------------------------------------- |
-    /// | Linux   | `$XDG_CONFIG_HOME` or `$HOME`/.config | /home/alice/.config                      |
-    /// | macOS   | `$HOME`/Library/Application Support   | /Users/Alice/Library/Application Support |
-    /// | Windows | `{FOLDERID_RoamingAppData}`           | C:\Users\Alice\AppData\Roaming           |
-    pub fn user_config_path() -> Option<&'static AbsPath> {
-        static USER_CONFIG_PATH: LazyLock<Option<AbsPathBuf>> = LazyLock::new(|| {
-            let user_config_path = if let Some(path) = env::var_os("__TEST_RA_USER_CONFIG_DIR") {
-                std::path::PathBuf::from(path)
-            } else {
-                dirs::config_dir()?.join("rust-analyzer")
-            }
-            .join("rust-analyzer.toml");
-            Some(AbsPathBuf::assert_utf8(user_config_path))
-        });
-        USER_CONFIG_PATH.as_deref()
+    /// Path to the user configuration dir. This can be seen as a generic way to define what would be `$XDG_CONFIG_HOME/rust-analyzer` in Linux.
+    pub fn user_config_dir_path() -> Option<AbsPathBuf> {
+        let user_config_path = if let Some(path) = env::var_os("__TEST_RA_USER_CONFIG_DIR") {
+            std::path::PathBuf::from(path)
+        } else {
+            dirs::config_dir()?.join("rust-analyzer")
+        };
+        Some(AbsPathBuf::assert_utf8(user_config_path))
     }
 
     pub fn same_source_root_parent_map(
@@ -1256,7 +1247,7 @@ pub struct NotificationsConfig {
     pub cargo_toml_not_found: bool,
 }
 
-#[derive(Deserialize, Serialize, Debug, Clone)]
+#[derive(Debug, Clone)]
 pub enum RustfmtConfig {
     Rustfmt { extra_args: Vec<String>, enable_range_formatting: bool },
     CustomCommand { command: String, args: Vec<String> },
@@ -1335,7 +1326,7 @@ impl Config {
         root_path: AbsPathBuf,
         caps: lsp_types::ClientCapabilities,
         workspace_roots: Vec<AbsPathBuf>,
-        visual_studio_code_version: Option<Version>,
+        client_info: Option<lsp_types::ClientInfo>,
     ) -> Self {
         static DEFAULT_CONFIG_DATA: OnceLock<&'static DefaultConfigData> = OnceLock::new();
 
@@ -1346,7 +1337,10 @@ impl Config {
             root_path,
             snippets: Default::default(),
             workspace_roots,
-            visual_studio_code_version,
+            client_info: client_info.map(|it| ClientInfo {
+                name: it.name,
+                version: it.version.as_deref().map(Version::parse).and_then(Result::ok),
+            }),
             client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
             default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
             source_root_parent_map: Arc::new(FxHashMap::default()),
@@ -1446,14 +1440,10 @@ impl Config {
             limit: self.completion_limit(source_root).to_owned(),
             enable_term_search: self.completion_termSearch_enable(source_root).to_owned(),
             term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64,
-            fields_to_resolve: CompletionFieldsToResolve {
-                resolve_label_details: client_capability_fields.contains("labelDetails"),
-                resolve_tags: client_capability_fields.contains("tags"),
-                resolve_detail: client_capability_fields.contains("detail"),
-                resolve_documentation: client_capability_fields.contains("documentation"),
-                resolve_filter_text: client_capability_fields.contains("filterText"),
-                resolve_text_edit: client_capability_fields.contains("textEdit"),
-                resolve_command: client_capability_fields.contains("command"),
+            fields_to_resolve: if self.client_is_neovim() {
+                CompletionFieldsToResolve::empty()
+            } else {
+                CompletionFieldsToResolve::from_client_capabilities(&client_capability_fields)
             },
         }
     }
@@ -1614,13 +1604,9 @@ impl Config {
             } else {
                 None
             },
-            fields_to_resolve: InlayFieldsToResolve {
-                resolve_text_edits: client_capability_fields.contains("textEdits"),
-                resolve_hint_tooltip: client_capability_fields.contains("tooltip"),
-                resolve_label_tooltip: client_capability_fields.contains("label.tooltip"),
-                resolve_label_location: client_capability_fields.contains("label.location"),
-                resolve_label_command: client_capability_fields.contains("label.command"),
-            },
+            fields_to_resolve: InlayFieldsToResolve::from_client_capabilities(
+                &client_capability_fields,
+            ),
             implicit_drop_hints: self.inlayHints_implicitDrops_enable().to_owned(),
             range_exclusive_hints: self.inlayHints_rangeExclusiveHints_enable().to_owned(),
         }
@@ -2166,14 +2152,25 @@ impl Config {
         }
     }
 
-    pub fn typing_autoclose_angle(&self) -> bool {
-        *self.typing_autoClosingAngleBrackets_enable()
+    pub fn typing_exclude_chars(&self) -> Option<String> {
+        self.typing_excludeChars().clone()
     }
 
     // VSCode is our reference implementation, so we allow ourselves to work around issues by
     // special casing certain versions
     pub fn visual_studio_code_version(&self) -> Option<&Version> {
-        self.visual_studio_code_version.as_ref()
+        self.client_info
+            .as_ref()
+            .filter(|it| it.name.starts_with("Visual Studio Code"))
+            .and_then(|it| it.version.as_ref())
+    }
+
+    pub fn client_is_helix(&self) -> bool {
+        self.client_info.as_ref().map(|it| it.name == "helix").unwrap_or_default()
+    }
+
+    pub fn client_is_neovim(&self) -> bool {
+        self.client_info.as_ref().map(|it| it.name == "Neovim").unwrap_or_default()
     }
 }
 // Deserialization definitions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 7fbeaa4e3ea..5f835702840 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -392,7 +392,14 @@ impl GlobalState {
             || !self.config.same_source_root_parent_map(&self.local_roots_parent_map)
         {
             let config_change = {
-                let user_config_path = Config::user_config_path();
+                let user_config_path = (|| {
+                    let mut p = Config::user_config_dir_path()?;
+                    p.push("rust-analyzer.toml");
+                    Some(p)
+                })();
+
+                let user_config_abs_path = user_config_path.as_deref();
+
                 let mut change = ConfigChange::default();
                 let db = self.analysis_host.raw_database();
 
@@ -411,7 +418,7 @@ impl GlobalState {
                     .collect_vec();
 
                 for (file_id, (_change_kind, vfs_path)) in modified_ratoml_files {
-                    if vfs_path.as_path() == user_config_path {
+                    if vfs_path.as_path() == user_config_abs_path {
                         change.change_user_config(Some(db.file_text(file_id)));
                         continue;
                     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index bb03eb3c89b..5e7262b14ca 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -379,9 +379,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                 for (id, package) in workspace_ids.clone() {
                     if id == flycheck.id() {
                         updated = true;
-                        match package.filter(|_| {
-                            !world.config.flycheck_workspace(source_root_id) && target.is_some()
-                        }) {
+                        match package.filter(|_| !world.config.flycheck_workspace(source_root_id)) {
                             Some(package) => flycheck
                                 .restart_for_package(package, target.clone().map(TupleExt::head)),
                             None => flycheck.restart_workspace(saved_file.clone()),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 4975467ece9..fa78be5cb60 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -10,6 +10,7 @@ use std::{
 
 use anyhow::Context;
 
+use base64::{prelude::BASE64_STANDARD, Engine};
 use ide::{
     AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, CompletionFieldsToResolve,
     FilePosition, FileRange, HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query,
@@ -36,6 +37,7 @@ use triomphe::Arc;
 use vfs::{AbsPath, AbsPathBuf, FileId, VfsPath};
 
 use crate::{
+    completion_item_hash,
     config::{Config, RustfmtConfig, WorkspaceSymbolConfig},
     diagnostics::convert_diagnostic,
     global_state::{FetchWorkspaceRequest, GlobalState, GlobalStateSnapshot},
@@ -459,9 +461,9 @@ pub(crate) fn handle_on_type_formatting(
     if char_typed == '>' {
         return Ok(None);
     }
+    let chars_to_exclude = snap.config.typing_exclude_chars();
 
-    let edit =
-        snap.analysis.on_char_typed(position, char_typed, snap.config.typing_autoclose_angle())?;
+    let edit = snap.analysis.on_char_typed(position, char_typed, chars_to_exclude)?;
     let edit = match edit {
         Some(it) => it,
         None => return Ok(None),
@@ -1127,7 +1129,7 @@ pub(crate) fn handle_completion_resolve(
     forced_resolve_completions_config.fields_to_resolve = CompletionFieldsToResolve::empty();
 
     let position = FilePosition { file_id, offset };
-    let Some(resolved_completions) = snap.analysis.completions(
+    let Some(completions) = snap.analysis.completions(
         &forced_resolve_completions_config,
         position,
         resolve_data.trigger_character,
@@ -1135,6 +1137,19 @@ pub(crate) fn handle_completion_resolve(
     else {
         return Ok(original_completion);
     };
+    let Ok(resolve_data_hash) = BASE64_STANDARD.decode(resolve_data.hash) else {
+        return Ok(original_completion);
+    };
+
+    let Some(corresponding_completion) = completions.into_iter().find(|completion_item| {
+        // Avoid computing hashes for items that obviously do not match
+        // r-a might append a detail-based suffix to the label, so we cannot check for equality
+        original_completion.label.starts_with(completion_item.label.as_str())
+            && resolve_data_hash == completion_item_hash(completion_item, resolve_data.for_ref)
+    }) else {
+        return Ok(original_completion);
+    };
+
     let mut resolved_completions = to_proto::completion_items(
         &snap.config,
         &forced_resolve_completions_config.fields_to_resolve,
@@ -1142,15 +1157,11 @@ pub(crate) fn handle_completion_resolve(
         snap.file_version(position.file_id),
         resolve_data.position,
         resolve_data.trigger_character,
-        resolved_completions,
+        vec![corresponding_completion],
     );
-
-    let mut resolved_completion =
-        if resolved_completions.get(resolve_data.completion_item_index).is_some() {
-            resolved_completions.swap_remove(resolve_data.completion_item_index)
-        } else {
-            return Ok(original_completion);
-        };
+    let Some(mut resolved_completion) = resolved_completions.pop() else {
+        return Ok(original_completion);
+    };
 
     if !resolve_data.imports.is_empty() {
         let additional_edits = snap
@@ -2341,6 +2352,10 @@ fn run_rustfmt(
                 );
                 Ok(None)
             }
+            // rustfmt panicked at lexing/parsing the file
+            Some(101) if !rustfmt_not_installed && captured_stderr.starts_with("error[") => {
+                Ok(None)
+            }
             _ => {
                 // Something else happened - e.g. `rustfmt` is missing or caught a signal
                 Err(LspError::new(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
index 234204695cb..15d60c873fb 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
@@ -47,7 +47,9 @@ use self::lsp::ext as lsp_ext;
 #[cfg(test)]
 mod integrated_benchmarks;
 
+use ide::{CompletionItem, CompletionRelevance};
 use serde::de::DeserializeOwned;
+use tenthash::TentHasher;
 
 pub use crate::{
     lsp::capabilities::server_capabilities, main_loop::main_loop, reload::ws_to_crate_graph,
@@ -61,3 +63,79 @@ pub fn from_json<T: DeserializeOwned>(
     serde_json::from_value(json.clone())
         .map_err(|e| anyhow::format_err!("Failed to deserialize {what}: {e}; {json}"))
 }
+
+fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8; 20] {
+    fn hash_completion_relevance(hasher: &mut TentHasher, relevance: &CompletionRelevance) {
+        use ide_completion::{
+            CompletionRelevancePostfixMatch, CompletionRelevanceReturnType,
+            CompletionRelevanceTypeMatch,
+        };
+
+        hasher.update([
+            u8::from(relevance.exact_name_match),
+            u8::from(relevance.is_local),
+            u8::from(relevance.is_name_already_imported),
+            u8::from(relevance.requires_import),
+            u8::from(relevance.is_private_editable),
+        ]);
+        if let Some(type_match) = &relevance.type_match {
+            let label = match type_match {
+                CompletionRelevanceTypeMatch::CouldUnify => "could_unify",
+                CompletionRelevanceTypeMatch::Exact => "exact",
+            };
+            hasher.update(label);
+        }
+        if let Some(trait_) = &relevance.trait_ {
+            hasher.update([u8::from(trait_.is_op_method), u8::from(trait_.notable_trait)]);
+        }
+        if let Some(postfix_match) = &relevance.postfix_match {
+            let label = match postfix_match {
+                CompletionRelevancePostfixMatch::NonExact => "non_exact",
+                CompletionRelevancePostfixMatch::Exact => "exact",
+            };
+            hasher.update(label);
+        }
+        if let Some(function) = &relevance.function {
+            hasher.update([u8::from(function.has_params), u8::from(function.has_self_param)]);
+            let label = match function.return_type {
+                CompletionRelevanceReturnType::Other => "other",
+                CompletionRelevanceReturnType::DirectConstructor => "direct_constructor",
+                CompletionRelevanceReturnType::Constructor => "constructor",
+                CompletionRelevanceReturnType::Builder => "builder",
+            };
+            hasher.update(label);
+        }
+    }
+
+    let mut hasher = TentHasher::new();
+    hasher.update([
+        u8::from(is_ref_completion),
+        u8::from(item.is_snippet),
+        u8::from(item.deprecated),
+        u8::from(item.trigger_call_info),
+    ]);
+    hasher.update(&item.label);
+    if let Some(label_detail) = &item.label_detail {
+        hasher.update(label_detail);
+    }
+    // NB: do not hash edits or source range, as those may change between the time the client sends the resolve request
+    // and the time it receives it: some editors do allow changing the buffer between that, leading to ranges being different.
+    //
+    // Documentation hashing is skipped too, as it's a large blob to process,
+    // while not really making completion properties more unique as they are already.
+    hasher.update(item.kind.tag());
+    hasher.update(&item.lookup);
+    if let Some(detail) = &item.detail {
+        hasher.update(detail);
+    }
+    hash_completion_relevance(&mut hasher, &item.relevance);
+    if let Some((mutability, text_size)) = &item.ref_match {
+        hasher.update(mutability.as_keyword_for_ref());
+        hasher.update(u32::from(*text_size).to_le_bytes());
+    }
+    for (import_path, import_name) in &item.import_to_add {
+        hasher.update(import_path);
+        hasher.update(import_name);
+    }
+    hasher.finalize()
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
index 1db616898e8..b1136dbbdac 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
@@ -1,4 +1,5 @@
 //! Advertises the capabilities of the LSP Server.
+use ide::{CompletionFieldsToResolve, InlayFieldsToResolve};
 use ide_db::{line_index::WideEncoding, FxHashSet};
 use lsp_types::{
     CallHierarchyServerCapability, CodeActionKind, CodeActionOptions, CodeActionProviderCapability,
@@ -40,7 +41,11 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         })),
         hover_provider: Some(HoverProviderCapability::Simple(true)),
         completion_provider: Some(CompletionOptions {
-            resolve_provider: config.caps().completions_resolve_provider(),
+            resolve_provider: if config.client_is_neovim() {
+                config.completion_item_edit_resolve().then_some(true)
+            } else {
+                Some(config.caps().completions_resolve_provider())
+            },
             trigger_characters: Some(vec![
                 ":".to_owned(),
                 ".".to_owned(),
@@ -71,9 +76,12 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
             RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)),
             _ => Some(OneOf::Left(false)),
         },
-        document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
-            first_trigger_character: "=".to_owned(),
-            more_trigger_character: Some(more_trigger_character(config)),
+        document_on_type_formatting_provider: Some({
+            let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.chars();
+            DocumentOnTypeFormattingOptions {
+                first_trigger_character: chars.next().unwrap().to_string(),
+                more_trigger_character: Some(chars.map(|c| c.to_string()).collect()),
+            }
         }),
         selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
         folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
@@ -136,7 +144,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options(
             InlayHintOptions {
                 work_done_progress_options: Default::default(),
-                resolve_provider: Some(true),
+                resolve_provider: Some(config.caps().inlay_hints_resolve_provider()),
             },
         ))),
         inline_value_provider: None,
@@ -176,8 +184,18 @@ impl ClientCapabilities {
         Self(caps)
     }
 
-    fn completions_resolve_provider(&self) -> Option<bool> {
-        self.completion_item_edit_resolve().then_some(true)
+    fn completions_resolve_provider(&self) -> bool {
+        let client_capabilities = self.completion_resolve_support_properties();
+        let fields_to_resolve =
+            CompletionFieldsToResolve::from_client_capabilities(&client_capabilities);
+        fields_to_resolve != CompletionFieldsToResolve::empty()
+    }
+
+    fn inlay_hints_resolve_provider(&self) -> bool {
+        let client_capabilities = self.inlay_hint_resolve_support_properties();
+        let fields_to_resolve =
+            InlayFieldsToResolve::from_client_capabilities(&client_capabilities);
+        fields_to_resolve != InlayFieldsToResolve::empty()
     }
 
     fn experimental_bool(&self, index: &'static str) -> bool {
@@ -517,11 +535,3 @@ impl ClientCapabilities {
         .unwrap_or_default()
     }
 }
-
-fn more_trigger_character(config: &Config) -> Vec<String> {
-    let mut res = vec![".".to_owned(), ">".to_owned(), "{".to_owned(), "(".to_owned()];
-    if config.snippet_cap().is_some() {
-        res.push("<".to_owned());
-    }
-    res
-}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 6ddfe118d5e..df06270a8b1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -826,7 +826,8 @@ pub struct CompletionResolveData {
     pub imports: Vec<CompletionImport>,
     pub version: Option<i32>,
     pub trigger_character: Option<char>,
-    pub completion_item_index: usize,
+    pub for_ref: bool,
+    pub hash: String,
 }
 
 #[derive(Debug, Serialize, Deserialize)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index d444f90a131..612cb547b41 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -5,6 +5,7 @@ use std::{
     sync::atomic::{AtomicU32, Ordering},
 };
 
+use base64::{prelude::BASE64_STANDARD, Engine};
 use ide::{
     Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
     CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
@@ -21,6 +22,7 @@ use serde_json::to_value;
 use vfs::AbsPath;
 
 use crate::{
+    completion_item_hash,
     config::{CallInfoConfig, Config},
     global_state::GlobalStateSnapshot,
     line_index::{LineEndings, LineIndex, PositionEncoding},
@@ -295,7 +297,7 @@ fn completion_item(
         // non-trivial mapping here.
         let mut text_edit = None;
         let source_range = item.source_range;
-        for indel in item.text_edit {
+        for indel in &item.text_edit {
             if indel.delete.contains_range(source_range) {
                 // Extract this indel as the main edit
                 text_edit = Some(if indel.delete == source_range {
@@ -347,7 +349,7 @@ fn completion_item(
         something_to_resolve |= item.documentation.is_some();
         None
     } else {
-        item.documentation.map(documentation)
+        item.documentation.clone().map(documentation)
     };
 
     let mut lsp_item = lsp_types::CompletionItem {
@@ -371,10 +373,10 @@ fn completion_item(
         } else {
             lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails {
                 detail: item.label_detail.as_ref().map(ToString::to_string),
-                description: item.detail,
+                description: item.detail.clone(),
             });
         }
-    } else if let Some(label_detail) = item.label_detail {
+    } else if let Some(label_detail) = &item.label_detail {
         lsp_item.label.push_str(label_detail.as_str());
     }
 
@@ -383,6 +385,7 @@ fn completion_item(
     let imports =
         if config.completion(None).enable_imports_on_the_fly && !item.import_to_add.is_empty() {
             item.import_to_add
+                .clone()
                 .into_iter()
                 .map(|(import_path, import_name)| lsp_ext::CompletionImport {
                     full_import_path: import_path,
@@ -393,16 +396,15 @@ fn completion_item(
             Vec::new()
         };
     let (ref_resolve_data, resolve_data) = if something_to_resolve || !imports.is_empty() {
-        let mut item_index = acc.len();
         let ref_resolve_data = if ref_match.is_some() {
             let ref_resolve_data = lsp_ext::CompletionResolveData {
                 position: tdpp.clone(),
                 imports: Vec::new(),
                 version,
                 trigger_character: completion_trigger_character,
-                completion_item_index: item_index,
+                for_ref: true,
+                hash: BASE64_STANDARD.encode(completion_item_hash(&item, true)),
             };
-            item_index += 1;
             Some(to_value(ref_resolve_data).unwrap())
         } else {
             None
@@ -412,7 +414,8 @@ fn completion_item(
             imports,
             version,
             trigger_character: completion_trigger_character,
-            completion_item_index: item_index,
+            for_ref: false,
+            hash: BASE64_STANDARD.encode(completion_item_hash(&item, false)),
         };
         (ref_resolve_data, Some(to_value(resolve_data).unwrap()))
     } else {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 73fce42437f..a34f0a3c929 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -809,7 +809,7 @@ impl GlobalState {
                 }
             }
             vfs::loader::Message::Progress { n_total, n_done, dir, config_version } => {
-                let _p = span!(Level::INFO, "GlobalState::handle_vfs_mgs/progress").entered();
+                let _p = span!(Level::INFO, "GlobalState::handle_vfs_msg/progress").entered();
                 always!(config_version <= self.vfs_config_version);
 
                 let (n_done, state) = match n_done {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index bc85afa0e49..4549735fef8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -590,7 +590,7 @@ impl GlobalState {
             }
 
             watchers.extend(
-                iter::once(Config::user_config_path())
+                iter::once(Config::user_config_dir_path().as_deref())
                     .chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref)))
                     .flatten()
                     .map(|glob_pattern| lsp_types::FileSystemWatcher {
@@ -613,7 +613,11 @@ impl GlobalState {
         }
 
         let files_config = self.config.files();
-        let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
+        let project_folders = ProjectFolders::new(
+            &self.workspaces,
+            &files_config.exclude,
+            Config::user_config_dir_path().as_deref(),
+        );
 
         if (self.proc_macro_clients.is_empty() || !same_workspaces)
             && self.config.expand_proc_macros()
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index a857e0c2967..5dfaf0d3650 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
@@ -46,7 +46,7 @@ impl RatomlTest {
             project = project.with_config(client_config);
         }
 
-        let server = project.server().wait_until_workspace_is_loaded();
+        let server = project.server_with_lock(true).wait_until_workspace_is_loaded();
 
         let mut case = Self { urls: vec![], server, tmp_path };
         let urls = fixtures.iter().map(|fixture| case.fixture_path(fixture)).collect::<Vec<_>>();
@@ -72,7 +72,7 @@ impl RatomlTest {
         let mut spl = spl.into_iter();
         if let Some(first) = spl.next() {
             if first == "$$CONFIG_DIR$$" {
-                path = Config::user_config_path().unwrap().to_path_buf().into();
+                path = Config::user_config_dir_path().unwrap().into();
             } else {
                 path = path.join(first);
             }
@@ -285,7 +285,6 @@ enum Value {
 //     }
 
 #[test]
-#[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_user_config_detected() {
     if skip_slow_tests() {
         return;
@@ -294,7 +293,7 @@ fn ratoml_user_config_detected() {
     let server = RatomlTest::new(
         vec![
             r#"
-//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml
+//- /$$CONFIG_DIR$$/rust-analyzer.toml
 assist.emitMustUse = true
 "#,
             r#"
@@ -322,7 +321,6 @@ enum Value {
 }
 
 #[test]
-#[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_create_user_config() {
     if skip_slow_tests() {
         return;
@@ -353,10 +351,7 @@ enum Value {
         1,
         InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
     );
-    server.create(
-        "//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml",
-        RatomlTest::EMIT_MUST_USE.to_owned(),
-    );
+    server.create("//- /$$CONFIG_DIR$$/rust-analyzer.toml", RatomlTest::EMIT_MUST_USE.to_owned());
     server.query(
         InternalTestingFetchConfigOption::AssistEmitMustUse,
         1,
@@ -365,7 +360,6 @@ enum Value {
 }
 
 #[test]
-#[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_modify_user_config() {
     if skip_slow_tests() {
         return;
@@ -386,7 +380,7 @@ enum Value {
     Text(String),
 }"#,
             r#"
-//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml
+//- /$$CONFIG_DIR$$/rust-analyzer.toml
 assist.emitMustUse = true"#,
         ],
         vec!["p1"],
@@ -407,7 +401,6 @@ assist.emitMustUse = true"#,
 }
 
 #[test]
-#[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_delete_user_config() {
     if skip_slow_tests() {
         return;
@@ -428,7 +421,7 @@ enum Value {
     Text(String),
 }"#,
             r#"
-//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml
+//- /$$CONFIG_DIR$$/rust-analyzer.toml
 assist.emitMustUse = true"#,
         ],
         vec!["p1"],
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 78572e37a9b..5a88a5515c7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -1,7 +1,7 @@
 use std::{
     cell::{Cell, RefCell},
-    fs,
-    sync::Once,
+    env, fs,
+    sync::{Once, OnceLock},
     time::Duration,
 };
 
@@ -127,7 +127,53 @@ impl Project<'_> {
     }
 
     pub(crate) fn server(self) -> Server {
-        static CONFIG_DIR_LOCK: Mutex<()> = Mutex::new(());
+        Project::server_with_lock(self, false)
+    }
+
+    /// `prelock` : Forcefully acquire a lock that will maintain the path to the config dir throughout the whole test.
+    ///
+    /// When testing we set the user config dir by setting an envvar `__TEST_RA_USER_CONFIG_DIR`.
+    /// This value must be maintained until the end of a test case. When tests run in parallel
+    /// this value may change thus making the tests flaky. As such, we use a `MutexGuard` that locks
+    /// the process until `Server` is dropped. To optimize parallelization we use a lock only when it is
+    /// needed, that is when a test uses config directory to do stuff. Our naive approach is to use a lock
+    /// if there is a path to config dir in the test fixture. However, in certain cases we create a
+    /// file in the config dir after server is run, something where our naive approach comes short.
+    /// Using a `prelock` allows us to force a lock when we know we need it.
+    pub(crate) fn server_with_lock(self, config_lock: bool) -> Server {
+        static CONFIG_DIR_LOCK: OnceLock<(Utf8PathBuf, Mutex<()>)> = OnceLock::new();
+
+        let config_dir_guard = if config_lock {
+            Some({
+                let (path, mutex) = CONFIG_DIR_LOCK.get_or_init(|| {
+                    let value = TestDir::new().keep().path().to_owned();
+                    env::set_var("__TEST_RA_USER_CONFIG_DIR", &value);
+                    (value, Mutex::new(()))
+                });
+                #[allow(dyn_drop)]
+                (mutex.lock(), {
+                    Box::new({
+                        struct Dropper(Utf8PathBuf);
+                        impl Drop for Dropper {
+                            fn drop(&mut self) {
+                                for entry in fs::read_dir(&self.0).unwrap() {
+                                    let path = entry.unwrap().path();
+                                    if path.is_file() {
+                                        fs::remove_file(path).unwrap();
+                                    } else if path.is_dir() {
+                                        fs::remove_dir_all(path).unwrap();
+                                    }
+                                }
+                            }
+                        }
+                        Dropper(path.clone())
+                    }) as Box<dyn Drop>
+                })
+            })
+        } else {
+            None
+        };
+
         let tmp_dir = self.tmp_dir.unwrap_or_else(|| {
             if self.root_dir_contains_symlink {
                 TestDir::new_symlink()
@@ -160,13 +206,9 @@ impl Project<'_> {
         assert!(mini_core.is_none());
         assert!(toolchain.is_none());
 
-        let mut config_dir_guard = None;
         for entry in fixture {
             if let Some(pth) = entry.path.strip_prefix("/$$CONFIG_DIR$$") {
-                if config_dir_guard.is_none() {
-                    config_dir_guard = Some(CONFIG_DIR_LOCK.lock());
-                }
-                let path = Config::user_config_path().unwrap().join(&pth['/'.len_utf8()..]);
+                let path = Config::user_config_dir_path().unwrap().join(&pth['/'.len_utf8()..]);
                 fs::create_dir_all(path.parent().unwrap()).unwrap();
                 fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
             } else {
@@ -269,12 +311,14 @@ pub(crate) struct Server {
     client: Connection,
     /// XXX: remove the tempdir last
     dir: TestDir,
-    _config_dir_guard: Option<MutexGuard<'static, ()>>,
+    #[allow(dyn_drop)]
+    _config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>,
 }
 
 impl Server {
+    #[allow(dyn_drop)]
     fn new(
-        config_dir_guard: Option<MutexGuard<'static, ()>>,
+        config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>,
         dir: TestDir,
         config: Config,
     ) -> Server {
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 02c59646a99..30428329dd9 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -37,7 +37,7 @@ Path =
 PathSegment =
   '::'? NameRef
 | NameRef GenericArgList?
-| NameRef ParamList RetType?
+| NameRef ParenthesizedArgList RetType?
 | NameRef ReturnTypeSyntax
 | '<' Type ('as' PathType)? '>'
 
@@ -49,6 +49,9 @@ ReturnTypeSyntax =
 //        Generics         //
 //*************************//
 
+ParenthesizedArgList =
+  '::'? '(' (TypeArg (',' TypeArg)* ','?)? ')'
+
 GenericArgList =
   '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>'
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
index f1286e7aa21..ffe9f16cfd5 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
@@ -909,30 +909,6 @@ fn get_or_insert_comma_after(syntax: &SyntaxNode) -> SyntaxToken {
     }
 }
 
-impl ast::VariantList {
-    pub fn add_variant(&self, variant: ast::Variant) {
-        let (indent, position) = match self.variants().last() {
-            Some(last_item) => (
-                IndentLevel::from_node(last_item.syntax()),
-                Position::after(get_or_insert_comma_after(last_item.syntax())),
-            ),
-            None => match self.l_curly_token() {
-                Some(l_curly) => {
-                    normalize_ws_between_braces(self.syntax());
-                    (IndentLevel::from_token(&l_curly) + 1, Position::after(&l_curly))
-                }
-                None => (IndentLevel::single(), Position::last_child_of(self.syntax())),
-            },
-        };
-        let elements: Vec<SyntaxElement> = vec![
-            make::tokens::whitespace(&format!("{}{indent}", "\n")).into(),
-            variant.syntax().clone().into(),
-            ast::make::token(T![,]).into(),
-        ];
-        ted::insert_all(position, elements);
-    }
-}
-
 fn normalize_ws_between_braces(node: &SyntaxNode) -> Option<()> {
     let l = node
         .children_with_tokens()
@@ -1055,8 +1031,6 @@ mod tests {
     use std::fmt;
 
     use parser::Edition;
-    use stdx::trim_indent;
-    use test_utils::assert_eq_text;
 
     use crate::SourceFile;
 
@@ -1170,102 +1144,4 @@ mod tests {
         check("let a: u8 = 3;", "let a = 3;", None);
         check("let a: = 3;", "let a = 3;", None);
     }
-
-    #[test]
-    fn add_variant_to_empty_enum() {
-        let variant = make::variant(make::name("Bar"), None).clone_for_update();
-
-        check_add_variant(
-            r#"
-enum Foo {}
-"#,
-            r#"
-enum Foo {
-    Bar,
-}
-"#,
-            variant,
-        );
-    }
-
-    #[test]
-    fn add_variant_to_non_empty_enum() {
-        let variant = make::variant(make::name("Baz"), None).clone_for_update();
-
-        check_add_variant(
-            r#"
-enum Foo {
-    Bar,
-}
-"#,
-            r#"
-enum Foo {
-    Bar,
-    Baz,
-}
-"#,
-            variant,
-        );
-    }
-
-    #[test]
-    fn add_variant_with_tuple_field_list() {
-        let variant = make::variant(
-            make::name("Baz"),
-            Some(ast::FieldList::TupleFieldList(make::tuple_field_list(std::iter::once(
-                make::tuple_field(None, make::ty("bool")),
-            )))),
-        )
-        .clone_for_update();
-
-        check_add_variant(
-            r#"
-enum Foo {
-    Bar,
-}
-"#,
-            r#"
-enum Foo {
-    Bar,
-    Baz(bool),
-}
-"#,
-            variant,
-        );
-    }
-
-    #[test]
-    fn add_variant_with_record_field_list() {
-        let variant = make::variant(
-            make::name("Baz"),
-            Some(ast::FieldList::RecordFieldList(make::record_field_list(std::iter::once(
-                make::record_field(None, make::name("x"), make::ty("bool")),
-            )))),
-        )
-        .clone_for_update();
-
-        check_add_variant(
-            r#"
-enum Foo {
-    Bar,
-}
-"#,
-            r#"
-enum Foo {
-    Bar,
-    Baz { x: bool },
-}
-"#,
-            variant,
-        );
-    }
-
-    fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) {
-        let enum_ = ast_mut_from_text::<ast::Enum>(before);
-        if let Some(it) = enum_.variant_list() {
-            it.add_variant(variant)
-        }
-        let after = enum_.to_string();
-        assert_eq_text!(&trim_indent(expected.trim()), &trim_indent(after.trim()));
-    }
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 23d2b355a94..01dcb646b37 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -1363,6 +1363,21 @@ impl ParenType {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParenthesizedArgList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ParenthesizedArgList {
+    #[inline]
+    pub fn type_args(&self) -> AstChildren<TypeArg> { support::children(&self.syntax) }
+    #[inline]
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    #[inline]
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    #[inline]
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Path {
     pub(crate) syntax: SyntaxNode,
 }
@@ -1403,7 +1418,9 @@ impl PathSegment {
     #[inline]
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     #[inline]
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn parenthesized_arg_list(&self) -> Option<ParenthesizedArgList> {
+        support::child(&self.syntax)
+    }
     #[inline]
     pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
     #[inline]
@@ -3760,6 +3777,20 @@ impl AstNode for ParenType {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl AstNode for ParenthesizedArgList {
+    #[inline]
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARENTHESIZED_ARG_LIST }
+    #[inline]
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    #[inline]
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
 impl AstNode for Path {
     #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
@@ -7097,6 +7128,11 @@ impl std::fmt::Display for ParenType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for ParenthesizedArgList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for Path {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index 2ec83d23b27..05c2a8354da 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -402,7 +402,7 @@ pub fn join_paths(paths: impl IntoIterator<Item = ast::Path>) -> ast::Path {
 
 // FIXME: should not be pub
 pub fn path_from_text(text: &str) -> ast::Path {
-    ast_from_text(&format!("fn main() {{ let test = {text}; }}"))
+    ast_from_text(&format!("fn main() {{ let test: {text}; }}"))
 }
 
 pub fn use_tree_glob() -> ast::UseTree {
@@ -1053,7 +1053,17 @@ pub fn variant_list(variants: impl IntoIterator<Item = ast::Variant>) -> ast::Va
     ast_from_text(&format!("enum f {{ {variants} }}"))
 }
 
-pub fn variant(name: ast::Name, field_list: Option<ast::FieldList>) -> ast::Variant {
+pub fn variant(
+    visibility: Option<ast::Visibility>,
+    name: ast::Name,
+    field_list: Option<ast::FieldList>,
+    discriminant: Option<ast::Expr>,
+) -> ast::Variant {
+    let visibility = match visibility {
+        None => String::new(),
+        Some(it) => format!("{it} "),
+    };
+
     let field_list = match field_list {
         None => String::new(),
         Some(it) => match it {
@@ -1061,7 +1071,12 @@ pub fn variant(name: ast::Name, field_list: Option<ast::FieldList>) -> ast::Vari
             ast::FieldList::TupleFieldList(tuple) => format!("{tuple}"),
         },
     };
-    ast_from_text(&format!("enum f {{ {name}{field_list} }}"))
+
+    let discriminant = match discriminant {
+        Some(it) => format!(" = {it}"),
+        None => String::new(),
+    };
+    ast_from_text(&format!("enum f {{ {visibility}{name}{field_list}{discriminant} }}"))
 }
 
 pub fn fn_(
@@ -1122,6 +1137,8 @@ pub fn struct_(
 pub fn enum_(
     visibility: Option<ast::Visibility>,
     enum_name: ast::Name,
+    generic_param_list: Option<ast::GenericParamList>,
+    where_clause: Option<ast::WhereClause>,
     variant_list: ast::VariantList,
 ) -> ast::Enum {
     let visibility = match visibility {
@@ -1129,7 +1146,12 @@ pub fn enum_(
         Some(it) => format!("{it} "),
     };
 
-    ast_from_text(&format!("{visibility}enum {enum_name} {variant_list}"))
+    let generic_params = generic_param_list.map(|it| it.to_string()).unwrap_or_default();
+    let where_clause = where_clause.map(|it| format!(" {it}")).unwrap_or_default();
+
+    ast_from_text(&format!(
+        "{visibility}enum {enum_name}{generic_params}{where_clause} {variant_list}"
+    ))
 }
 
 pub fn attr_outer(meta: ast::Meta) -> ast::Attr {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
index 9f88add0f78..e86c291f76c 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -2,9 +2,9 @@
 use itertools::Itertools;
 
 use crate::{
-    ast::{self, make, HasName},
+    ast::{self, make, HasGenericParams, HasName, HasTypeBounds, HasVisibility},
     syntax_editor::SyntaxMappingBuilder,
-    AstNode,
+    AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
 };
 
 use super::SyntaxFactory;
@@ -14,6 +14,40 @@ impl SyntaxFactory {
         make::name(name).clone_for_update()
     }
 
+    pub fn ty(&self, text: &str) -> ast::Type {
+        make::ty(text).clone_for_update()
+    }
+
+    pub fn ty_infer(&self) -> ast::InferType {
+        let ast::Type::InferType(ast) = make::ty_placeholder().clone_for_update() else {
+            unreachable!()
+        };
+
+        ast
+    }
+
+    pub fn type_param(
+        &self,
+        name: ast::Name,
+        bounds: Option<ast::TypeBoundList>,
+    ) -> ast::TypeParam {
+        let ast = make::type_param(name.clone(), bounds.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
+            if let Some(input) = bounds {
+                builder.map_node(
+                    input.syntax().clone(),
+                    ast.type_bound_list().unwrap().syntax().clone(),
+                );
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn ident_pat(&self, ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat {
         let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update();
 
@@ -32,22 +66,52 @@ impl SyntaxFactory {
         tail_expr: Option<ast::Expr>,
     ) -> ast::BlockExpr {
         let stmts = stmts.into_iter().collect_vec();
-        let input = stmts.iter().map(|it| it.syntax().clone()).collect_vec();
+        let mut input = stmts.iter().map(|it| it.syntax().clone()).collect_vec();
 
         let ast = make::block_expr(stmts, tail_expr.clone()).clone_for_update();
 
-        if let Some((mut mapping, stmt_list)) = self.mappings().zip(ast.stmt_list()) {
+        if let Some(mut mapping) = self.mappings() {
+            let stmt_list = ast.stmt_list().unwrap();
             let mut builder = SyntaxMappingBuilder::new(stmt_list.syntax().clone());
 
+            if let Some(input) = tail_expr {
+                builder.map_node(
+                    input.syntax().clone(),
+                    stmt_list.tail_expr().unwrap().syntax().clone(),
+                );
+            } else if let Some(ast_tail) = stmt_list.tail_expr() {
+                // The parser interpreted the last statement (probably a statement with a block) as an Expr
+                let last_stmt = input.pop().unwrap();
+
+                builder.map_node(last_stmt, ast_tail.syntax().clone());
+            }
+
             builder.map_children(
                 input.into_iter(),
                 stmt_list.statements().map(|it| it.syntax().clone()),
             );
 
-            if let Some((input, output)) = tail_expr.zip(stmt_list.tail_expr()) {
-                builder.map_node(input.syntax().clone(), output.syntax().clone());
-            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn expr_empty_block(&self) -> ast::BlockExpr {
+        ast::BlockExpr { syntax: make::expr_empty_block().syntax().clone_for_update() }
+    }
 
+    pub fn expr_bin(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::BinExpr {
+        let ast::Expr::BinExpr(ast) =
+            make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(lhs.syntax().clone(), ast.lhs().unwrap().syntax().clone());
+            builder.map_node(rhs.syntax().clone(), ast.rhs().unwrap().syntax().clone());
             builder.finish(&mut mapping);
         }
 
@@ -83,6 +147,22 @@ impl SyntaxFactory {
         ast.into()
     }
 
+    pub fn expr_return(&self, expr: Option<ast::Expr>) -> ast::ReturnExpr {
+        let ast::Expr::ReturnExpr(ast) = make::expr_return(expr.clone()).clone_for_update() else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(input) = expr {
+                builder.map_node(input.syntax().clone(), ast.expr().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn let_stmt(
         &self,
         pattern: ast::Pat,
@@ -107,4 +187,261 @@ impl SyntaxFactory {
 
         ast
     }
+
+    pub fn turbofish_generic_arg_list(
+        &self,
+        args: impl IntoIterator<Item = ast::GenericArg> + Clone,
+    ) -> ast::GenericArgList {
+        let ast = make::turbofish_generic_arg_list(args.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(
+                args.into_iter().map(|arg| arg.syntax().clone()),
+                ast.generic_args().map(|arg| arg.syntax().clone()),
+            );
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn record_field_list(
+        &self,
+        fields: impl IntoIterator<Item = ast::RecordField>,
+    ) -> ast::RecordFieldList {
+        let fields: Vec<ast::RecordField> = fields.into_iter().collect();
+        let input: Vec<_> = fields.iter().map(|it| it.syntax().clone()).collect();
+        let ast = make::record_field_list(fields).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+
+            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn record_field(
+        &self,
+        visibility: Option<ast::Visibility>,
+        name: ast::Name,
+        ty: ast::Type,
+    ) -> ast::RecordField {
+        let ast =
+            make::record_field(visibility.clone(), name.clone(), ty.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+
+            builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
+            builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn tuple_field_list(
+        &self,
+        fields: impl IntoIterator<Item = ast::TupleField>,
+    ) -> ast::TupleFieldList {
+        let fields: Vec<ast::TupleField> = fields.into_iter().collect();
+        let input: Vec<_> = fields.iter().map(|it| it.syntax().clone()).collect();
+        let ast = make::tuple_field_list(fields).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+
+            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn tuple_field(
+        &self,
+        visibility: Option<ast::Visibility>,
+        ty: ast::Type,
+    ) -> ast::TupleField {
+        let ast = make::tuple_field(visibility.clone(), ty.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+
+            builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn item_enum(
+        &self,
+        visibility: Option<ast::Visibility>,
+        name: ast::Name,
+        generic_param_list: Option<ast::GenericParamList>,
+        where_clause: Option<ast::WhereClause>,
+        variant_list: ast::VariantList,
+    ) -> ast::Enum {
+        let ast = make::enum_(
+            visibility.clone(),
+            name.clone(),
+            generic_param_list.clone(),
+            where_clause.clone(),
+            variant_list.clone(),
+        )
+        .clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+
+            builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
+
+            if let Some(generic_param_list) = generic_param_list {
+                builder.map_node(
+                    generic_param_list.syntax().clone(),
+                    ast.generic_param_list().unwrap().syntax().clone(),
+                );
+            }
+
+            if let Some(where_clause) = where_clause {
+                builder.map_node(
+                    where_clause.syntax().clone(),
+                    ast.where_clause().unwrap().syntax().clone(),
+                );
+            }
+
+            builder.map_node(
+                variant_list.syntax().clone(),
+                ast.variant_list().unwrap().syntax().clone(),
+            );
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn variant_list(
+        &self,
+        variants: impl IntoIterator<Item = ast::Variant>,
+    ) -> ast::VariantList {
+        let variants: Vec<ast::Variant> = variants.into_iter().collect();
+        let input: Vec<_> = variants.iter().map(|it| it.syntax().clone()).collect();
+        let ast = make::variant_list(variants).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+
+            builder.map_children(input.into_iter(), ast.variants().map(|it| it.syntax().clone()));
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn variant(
+        &self,
+        visibility: Option<ast::Visibility>,
+        name: ast::Name,
+        field_list: Option<ast::FieldList>,
+        discriminant: Option<ast::Expr>,
+    ) -> ast::Variant {
+        let ast = make::variant(
+            visibility.clone(),
+            name.clone(),
+            field_list.clone(),
+            discriminant.clone(),
+        )
+        .clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+
+            builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
+
+            if let Some(field_list) = field_list {
+                builder.map_node(
+                    field_list.syntax().clone(),
+                    ast.field_list().unwrap().syntax().clone(),
+                );
+            }
+
+            if let Some(discriminant) = discriminant {
+                builder
+                    .map_node(discriminant.syntax().clone(), ast.expr().unwrap().syntax().clone());
+            }
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn token_tree(
+        &self,
+        delimiter: SyntaxKind,
+        tt: Vec<NodeOrToken<ast::TokenTree, SyntaxToken>>,
+    ) -> ast::TokenTree {
+        let tt: Vec<_> = tt.into_iter().collect();
+        let input: Vec<_> = tt.iter().cloned().filter_map(only_nodes).collect();
+
+        let ast = make::token_tree(delimiter, tt).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(
+                input.into_iter(),
+                ast.token_trees_and_tokens().filter_map(only_nodes),
+            );
+            builder.finish(&mut mapping);
+        }
+
+        return ast;
+
+        fn only_nodes(element: NodeOrToken<ast::TokenTree, SyntaxToken>) -> Option<SyntaxNode> {
+            element.as_node().map(|it| it.syntax().clone())
+        }
+    }
+
+    pub fn token(&self, kind: SyntaxKind) -> SyntaxToken {
+        make::token(kind)
+    }
+
+    pub fn whitespace(&self, text: &str) -> ast::SyntaxToken {
+        make::tokens::whitespace(text)
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
index 714f5a99111..992a847663a 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
@@ -16,6 +16,7 @@ use rustc_hash::FxHashMap;
 use crate::{SyntaxElement, SyntaxNode, SyntaxToken};
 
 mod edit_algo;
+mod edits;
 mod mapping;
 
 pub use mapping::{SyntaxMapping, SyntaxMappingBuilder};
@@ -326,7 +327,7 @@ mod tests {
 
     use crate::{
         ast::{self, make, syntax_factory::SyntaxFactory},
-        AstNode,
+        AstNode, SyntaxKind,
     };
 
     use super::*;
@@ -539,4 +540,50 @@ mod tests {
             }"#]];
         expect.assert_eq(&edit.new_root.to_string());
     }
+
+    #[test]
+    fn test_replace_token_in_parent() {
+        let parent_fn = make::fn_(
+            None,
+            make::name("it"),
+            None,
+            None,
+            make::param_list(None, []),
+            make::block_expr([], Some(make::expr_unit())),
+            Some(make::ret_type(make::ty_unit())),
+            false,
+            false,
+            false,
+            false,
+        );
+
+        let mut editor = SyntaxEditor::new(parent_fn.syntax().clone());
+
+        if let Some(ret_ty) = parent_fn.ret_type() {
+            editor.delete(ret_ty.syntax().clone());
+
+            if let Some(SyntaxElement::Token(token)) = ret_ty.syntax().next_sibling_or_token() {
+                if token.kind().is_trivia() {
+                    editor.delete(token);
+                }
+            }
+        }
+
+        if let Some(tail) = parent_fn.body().unwrap().tail_expr() {
+            // FIXME: We do this because `xtask tidy` will not allow us to have trailing whitespace in the expect string.
+            if let Some(SyntaxElement::Token(token)) = tail.syntax().prev_sibling_or_token() {
+                if let SyntaxKind::WHITESPACE = token.kind() {
+                    editor.delete(token);
+                }
+            }
+            editor.delete(tail.syntax().clone());
+        }
+
+        let edit = editor.finish();
+
+        let expect = expect![[r#"
+fn it() {
+}"#]];
+        expect.assert_eq(&edit.new_root.to_string());
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
index b769c941105..57ecbe57019 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
@@ -73,7 +73,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
         })
         .all(|(l, r)| {
             get_node_depth(l.target_parent()) != get_node_depth(r.target_parent())
-                || l.target_range().intersect(r.target_range()).is_none()
+                || (l.target_range().end() <= r.target_range().start())
         });
 
     if stdx::never!(
@@ -128,13 +128,14 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
 
         // Add to changed ancestors, if applicable
         match change {
-            Change::Insert(_, _) | Change::InsertAll(_, _) => {}
-            Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
+            Change::Replace(SyntaxElement::Node(target), _)
+            | Change::ReplaceWithMany(SyntaxElement::Node(target), _) => {
                 changed_ancestors.push_back(ChangedAncestor::single(target, change_index))
             }
             Change::ReplaceAll(range, _) => {
                 changed_ancestors.push_back(ChangedAncestor::multiple(range, change_index))
             }
+            _ => (),
         }
     }
 
@@ -154,6 +155,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
                     }
                 };
             }
+            Change::Replace(SyntaxElement::Node(target), Some(SyntaxElement::Node(new_target))) => {
+                *target = tree_mutator.make_syntax_mut(target);
+                if new_target.ancestors().any(|node| node == tree_mutator.immutable) {
+                    *new_target = new_target.clone_for_update();
+                }
+            }
             Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
                 *target = tree_mutator.make_element_mut(target);
             }
@@ -304,13 +311,8 @@ enum ChangedAncestorKind {
 }
 
 impl ChangedAncestor {
-    fn single(element: &SyntaxElement, change_index: usize) -> Self {
-        let kind = match element {
-            SyntaxElement::Node(node) => ChangedAncestorKind::Single { node: node.clone() },
-            SyntaxElement::Token(token) => {
-                ChangedAncestorKind::Single { node: token.parent().unwrap() }
-            }
-        };
+    fn single(node: &SyntaxNode, change_index: usize) -> Self {
+        let kind = ChangedAncestorKind::Single { node: node.clone() };
 
         Self { kind, change_index }
     }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
new file mode 100644
index 00000000000..8069fdd06f7
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
@@ -0,0 +1,274 @@
+//! Structural editing for ast using `SyntaxEditor`
+
+use crate::{
+    ast::{
+        self, edit::IndentLevel, make, syntax_factory::SyntaxFactory, AstNode, Fn, GenericParam,
+        HasGenericParams, HasName,
+    },
+    syntax_editor::{Position, SyntaxEditor},
+    Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
+};
+
+impl SyntaxEditor {
+    /// Adds a new generic param to the function using `SyntaxEditor`
+    pub fn add_generic_param(&mut self, function: &Fn, new_param: GenericParam) {
+        match function.generic_param_list() {
+            Some(generic_param_list) => match generic_param_list.generic_params().last() {
+                Some(last_param) => {
+                    // There exists a generic param list and it's not empty
+                    let position = generic_param_list.r_angle_token().map_or_else(
+                        || Position::last_child_of(function.syntax()),
+                        Position::before,
+                    );
+
+                    if last_param
+                        .syntax()
+                        .next_sibling_or_token()
+                        .map_or(false, |it| it.kind() == SyntaxKind::COMMA)
+                    {
+                        self.insert(
+                            Position::after(last_param.syntax()),
+                            new_param.syntax().clone(),
+                        );
+                        self.insert(
+                            Position::after(last_param.syntax()),
+                            make::token(SyntaxKind::WHITESPACE),
+                        );
+                        self.insert(
+                            Position::after(last_param.syntax()),
+                            make::token(SyntaxKind::COMMA),
+                        );
+                    } else {
+                        let elements = vec![
+                            make::token(SyntaxKind::COMMA).into(),
+                            make::token(SyntaxKind::WHITESPACE).into(),
+                            new_param.syntax().clone().into(),
+                        ];
+                        self.insert_all(position, elements);
+                    }
+                }
+                None => {
+                    // There exists a generic param list but it's empty
+                    let position = Position::after(generic_param_list.l_angle_token().unwrap());
+                    self.insert(position, new_param.syntax());
+                }
+            },
+            None => {
+                // There was no generic param list
+                let position = if let Some(name) = function.name() {
+                    Position::after(name.syntax)
+                } else if let Some(fn_token) = function.fn_token() {
+                    Position::after(fn_token)
+                } else if let Some(param_list) = function.param_list() {
+                    Position::before(param_list.syntax)
+                } else {
+                    Position::last_child_of(function.syntax())
+                };
+                let elements = vec![
+                    make::token(SyntaxKind::L_ANGLE).into(),
+                    new_param.syntax().clone().into(),
+                    make::token(SyntaxKind::R_ANGLE).into(),
+                ];
+                self.insert_all(position, elements);
+            }
+        }
+    }
+}
+
+fn get_or_insert_comma_after(editor: &mut SyntaxEditor, syntax: &SyntaxNode) -> SyntaxToken {
+    let make = SyntaxFactory::without_mappings();
+    match syntax
+        .siblings_with_tokens(Direction::Next)
+        .filter_map(|it| it.into_token())
+        .find(|it| it.kind() == T![,])
+    {
+        Some(it) => it,
+        None => {
+            let comma = make.token(T![,]);
+            editor.insert(Position::after(syntax), &comma);
+            comma
+        }
+    }
+}
+
+impl ast::VariantList {
+    pub fn add_variant(&self, editor: &mut SyntaxEditor, variant: &ast::Variant) {
+        let make = SyntaxFactory::without_mappings();
+        let (indent, position) = match self.variants().last() {
+            Some(last_item) => (
+                IndentLevel::from_node(last_item.syntax()),
+                Position::after(get_or_insert_comma_after(editor, last_item.syntax())),
+            ),
+            None => match self.l_curly_token() {
+                Some(l_curly) => {
+                    normalize_ws_between_braces(editor, self.syntax());
+                    (IndentLevel::from_token(&l_curly) + 1, Position::after(&l_curly))
+                }
+                None => (IndentLevel::single(), Position::last_child_of(self.syntax())),
+            },
+        };
+        let elements: Vec<SyntaxElement> = vec![
+            make.whitespace(&format!("{}{indent}", "\n")).into(),
+            variant.syntax().clone().into(),
+            make.token(T![,]).into(),
+        ];
+        editor.insert_all(position, elements);
+    }
+}
+
+fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) -> Option<()> {
+    let make = SyntaxFactory::without_mappings();
+    let l = node
+        .children_with_tokens()
+        .filter_map(|it| it.into_token())
+        .find(|it| it.kind() == T!['{'])?;
+    let r = node
+        .children_with_tokens()
+        .filter_map(|it| it.into_token())
+        .find(|it| it.kind() == T!['}'])?;
+
+    let indent = IndentLevel::from_node(node);
+
+    match l.next_sibling_or_token() {
+        Some(ws) if ws.kind() == SyntaxKind::WHITESPACE => {
+            if ws.next_sibling_or_token()?.into_token()? == r {
+                editor.replace(ws, make.whitespace(&format!("\n{indent}")));
+            }
+        }
+        Some(ws) if ws.kind() == T!['}'] => {
+            editor.insert(Position::after(l), make.whitespace(&format!("\n{indent}")));
+        }
+        _ => (),
+    }
+    Some(())
+}
+
+#[cfg(test)]
+mod tests {
+    use parser::Edition;
+    use stdx::trim_indent;
+    use test_utils::assert_eq_text;
+
+    use crate::SourceFile;
+
+    use super::*;
+
+    fn ast_from_text<N: AstNode>(text: &str) -> N {
+        let parse = SourceFile::parse(text, Edition::CURRENT);
+        let node = match parse.tree().syntax().descendants().find_map(N::cast) {
+            Some(it) => it,
+            None => {
+                let node = std::any::type_name::<N>();
+                panic!("Failed to make ast node `{node}` from text {text}")
+            }
+        };
+        let node = node.clone_subtree();
+        assert_eq!(node.syntax().text_range().start(), 0.into());
+        node
+    }
+
+    #[test]
+    fn add_variant_to_empty_enum() {
+        let make = SyntaxFactory::without_mappings();
+        let variant = make.variant(None, make.name("Bar"), None, None);
+
+        check_add_variant(
+            r#"
+enum Foo {}
+"#,
+            r#"
+enum Foo {
+    Bar,
+}
+"#,
+            variant,
+        );
+    }
+
+    #[test]
+    fn add_variant_to_non_empty_enum() {
+        let make = SyntaxFactory::without_mappings();
+        let variant = make.variant(None, make.name("Baz"), None, None);
+
+        check_add_variant(
+            r#"
+enum Foo {
+    Bar,
+}
+"#,
+            r#"
+enum Foo {
+    Bar,
+    Baz,
+}
+"#,
+            variant,
+        );
+    }
+
+    #[test]
+    fn add_variant_with_tuple_field_list() {
+        let make = SyntaxFactory::without_mappings();
+        let variant = make.variant(
+            None,
+            make.name("Baz"),
+            Some(make.tuple_field_list([make.tuple_field(None, make.ty("bool"))]).into()),
+            None,
+        );
+
+        check_add_variant(
+            r#"
+enum Foo {
+    Bar,
+}
+"#,
+            r#"
+enum Foo {
+    Bar,
+    Baz(bool),
+}
+"#,
+            variant,
+        );
+    }
+
+    #[test]
+    fn add_variant_with_record_field_list() {
+        let make = SyntaxFactory::without_mappings();
+        let variant = make.variant(
+            None,
+            make.name("Baz"),
+            Some(
+                make.record_field_list([make.record_field(None, make.name("x"), make.ty("bool"))])
+                    .into(),
+            ),
+            None,
+        );
+
+        check_add_variant(
+            r#"
+enum Foo {
+    Bar,
+}
+"#,
+            r#"
+enum Foo {
+    Bar,
+    Baz { x: bool },
+}
+"#,
+            variant,
+        );
+    }
+
+    fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) {
+        let enum_ = ast_from_text::<ast::Enum>(before);
+        let mut editor = SyntaxEditor::new(enum_.syntax().clone());
+        if let Some(it) = enum_.variant_list() {
+            it.add_variant(&mut editor, &variant)
+        }
+        let edit = editor.finish();
+        let after = edit.new_root.to_string();
+        assert_eq_text!(&trim_indent(expected.trim()), &trim_indent(after.trim()));
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index 593e31c2fbb..889a7d10ada 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -236,7 +236,7 @@ impl ChangeFixture {
             crate_graph.add_crate_root(
                 crate_root,
                 Edition::CURRENT,
-                Some(CrateName::new("test").unwrap().into()),
+                Some(CrateName::new("ra_test_fixture").unwrap().into()),
                 None,
                 From::from(default_cfg.clone()),
                 Some(From::from(default_cfg)),
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 07767d5ae9f..99dfabe174e 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -12,6 +12,7 @@
 //!     asm:
 //!     assert:
 //!     as_ref: sized
+//!     async_fn: fn, tuple, future, copy
 //!     bool_impl: option, fn
 //!     builtin_impls:
 //!     cell: copy, drop
@@ -29,7 +30,7 @@
 //!     eq: sized
 //!     error: fmt
 //!     fmt: option, result, transmute, coerce_unsized, copy, clone, derive
-//!     fn:
+//!     fn: tuple
 //!     from: sized
 //!     future: pin
 //!     coroutine: pin
@@ -60,6 +61,7 @@
 //!     sync: sized
 //!     transmute:
 //!     try: infallible
+//!     tuple:
 //!     unpin: sized
 //!     unsize: sized
 //!     todo: panic
@@ -138,10 +140,10 @@ pub mod marker {
     }
     // endregion:copy
 
-    // region:fn
+    // region:tuple
     #[lang = "tuple_trait"]
     pub trait Tuple {}
-    // endregion:fn
+    // endregion:tuple
 
     // region:phantom_data
     #[lang = "phantom_data"]
@@ -682,6 +684,112 @@ pub mod ops {
     }
     pub use self::function::{Fn, FnMut, FnOnce};
     // endregion:fn
+
+    // region:async_fn
+    mod async_function {
+        use crate::{future::Future, marker::Tuple};
+
+        #[lang = "async_fn"]
+        #[fundamental]
+        pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
+            extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_>;
+        }
+
+        #[lang = "async_fn_mut"]
+        #[fundamental]
+        pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
+            #[lang = "call_ref_future"]
+            type CallRefFuture<'a>: Future<Output = Self::Output>
+            where
+                Self: 'a;
+            extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_>;
+        }
+
+        #[lang = "async_fn_once"]
+        #[fundamental]
+        pub trait AsyncFnOnce<Args: Tuple> {
+            #[lang = "async_fn_once_output"]
+            type Output;
+            #[lang = "call_once_future"]
+            type CallOnceFuture: Future<Output = Self::Output>;
+            extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture;
+        }
+
+        mod impls {
+            use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
+            use crate::marker::Tuple;
+
+            impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F
+            where
+                F: AsyncFn<A>,
+            {
+                extern "rust-call" fn async_call(&self, args: A) -> Self::CallRefFuture<'_> {
+                    F::async_call(*self, args)
+                }
+            }
+
+            impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F
+            where
+                F: AsyncFn<A>,
+            {
+                type CallRefFuture<'a>
+                    = F::CallRefFuture<'a>
+                where
+                    Self: 'a;
+
+                extern "rust-call" fn async_call_mut(
+                    &mut self,
+                    args: A,
+                ) -> Self::CallRefFuture<'_> {
+                    F::async_call(*self, args)
+                }
+            }
+
+            impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F
+            where
+                F: AsyncFn<A>,
+            {
+                type Output = F::Output;
+                type CallOnceFuture = F::CallRefFuture<'a>;
+
+                extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
+                    F::async_call(self, args)
+                }
+            }
+
+            impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F
+            where
+                F: AsyncFnMut<A>,
+            {
+                type CallRefFuture<'a>
+                    = F::CallRefFuture<'a>
+                where
+                    Self: 'a;
+
+                extern "rust-call" fn async_call_mut(
+                    &mut self,
+                    args: A,
+                ) -> Self::CallRefFuture<'_> {
+                    F::async_call_mut(*self, args)
+                }
+            }
+
+            impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F
+            where
+                F: AsyncFnMut<A>,
+            {
+                type Output = F::Output;
+                type CallOnceFuture = F::CallRefFuture<'a>;
+
+                extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture {
+                    F::async_call_mut(self, args)
+                }
+            }
+        }
+    }
+    pub use self::async_function::{AsyncFn, AsyncFnMut, AsyncFnOnce};
+    // endregion:async_fn
+
     // region:try
     mod try_ {
         use crate::convert::Infallible;
@@ -1684,6 +1792,7 @@ pub mod prelude {
             marker::Sync,                            // :sync
             mem::drop,                               // :drop
             ops::Drop,                               // :drop
+            ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}, // :async_fn
             ops::{Fn, FnMut, FnOnce},                // :fn
             option::Option::{self, None, Some},      // :option
             panic,                                   // :panic
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index b7c536e0279..2aad2cfa361 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 96f88b7a5d0080c6
+lsp/ext.rs hash: 14b7fb1309f5bb00
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 052d0a2a41d..1195a85cf70 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -992,10 +992,10 @@ Show full signature of the callable. Only shows parameters if disabled.
 --
 Show documentation.
 --
-[[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`)::
+[[rust-analyzer.typing.excludeChars]]rust-analyzer.typing.excludeChars (default: `"|<"`)::
 +
 --
-Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.
+Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.
 --
 [[rust-analyzer.workspace.discoverConfig]]rust-analyzer.workspace.discoverConfig (default: `null`)::
 +
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 82c43b76fdd..469c1b458d5 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -425,6 +425,41 @@
                         ],
                         "default": "openLogs",
                         "markdownDescription": "Action to run when clicking the extension status bar item."
+                    },
+                    "rust-analyzer.statusBar.documentSelector": {
+                        "type": [
+                            "array",
+                            "null"
+                        ],
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "language": {
+                                    "type": [
+                                        "string",
+                                        "null"
+                                    ]
+                                },
+                                "pattern": {
+                                    "type": [
+                                        "string",
+                                        "null"
+                                    ]
+                                }
+                            }
+                        },
+                        "default": [
+                            {
+                                "language": "rust"
+                            },
+                            {
+                                "pattern": "**/Cargo.toml"
+                            },
+                            {
+                                "pattern": "**/Cargo.lock"
+                            }
+                        ],
+                        "markdownDescription": "Determines when to show the extension status bar item based on the currently open file. Use `{ \"pattern\": \"**\" }` to always show. Use `null` to never show."
                     }
                 }
             },
@@ -2570,10 +2605,13 @@
             {
                 "title": "typing",
                 "properties": {
-                    "rust-analyzer.typing.autoClosingAngleBrackets.enable": {
-                        "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.",
-                        "default": false,
-                        "type": "boolean"
+                    "rust-analyzer.typing.excludeChars": {
+                        "markdownDescription": "Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.",
+                        "default": "|<",
+                        "type": [
+                            "null",
+                            "string"
+                        ]
                     }
                 }
             },
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index eac7b849fdb..4ce19f5c665 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -324,7 +324,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
     }
     fillClientCapabilities(capabilities: lc.ClientCapabilities): void {
         capabilities.experimental = {
-            snippetTextEdit: true,
+            snippetTextEdit: false,
             codeActionGroup: true,
             hoverActions: true,
             serverStatusNotification: true,
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 67bc72f1e12..f7ef80df2ba 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -261,9 +261,9 @@ export class Config {
         return this.get<boolean | undefined>("testExplorer");
     }
 
-    get runnablesExtraEnv() {
+    runnablesExtraEnv(label: string): Record<string, string> | undefined {
         const item = this.get<any>("runnables.extraEnv") ?? this.get<any>("runnableEnv");
-        if (!item) return item;
+        if (!item) return undefined;
         const fixRecord = (r: Record<string, any>) => {
             for (const key in r) {
                 if (typeof r[key] !== "string") {
@@ -271,11 +271,28 @@ export class Config {
                 }
             }
         };
+
+        const platform = process.platform;
+        const checkPlatform = (it: RunnableEnvCfgItem) => {
+            if (it.platform) {
+                const platforms = Array.isArray(it.platform) ? it.platform : [it.platform];
+                return platforms.indexOf(platform) >= 0;
+            }
+            return true;
+        };
+
         if (item instanceof Array) {
-            item.forEach((x) => fixRecord(x.env));
-        } else {
-            fixRecord(item);
+            const env = {};
+            for (const it of item) {
+                const masked = !it.mask || new RegExp(it.mask).test(label);
+                if (masked && checkPlatform(it)) {
+                    Object.assign(env, it.env);
+                }
+            }
+            fixRecord(env);
+            return env;
         }
+        fixRecord(item);
         return item;
     }
 
@@ -331,6 +348,10 @@ export class Config {
         return this.get<string>("statusBar.clickAction");
     }
 
+    get statusBarDocumentSelector() {
+        return this.get<vscode.DocumentSelector>("statusBar.documentSelector");
+    }
+
     get initializeStopped() {
         return this.get<boolean>("initializeStopped");
     }
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 234fe6ab024..4a3f66b00d0 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -88,6 +88,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
     private _treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined;
     private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" };
     private _serverVersion: string;
+    private statusBarActiveEditorListener: Disposable;
 
     get serverPath(): string | undefined {
         return this._serverPath;
@@ -119,6 +120,10 @@ export class Ctx implements RustAnalyzerExtensionApi {
         this._serverVersion = "<not running>";
         this.config = new Config(extCtx.subscriptions);
         this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
+        this.updateStatusBarVisibility(vscode.window.activeTextEditor);
+        this.statusBarActiveEditorListener = vscode.window.onDidChangeActiveTextEditor((editor) =>
+            this.updateStatusBarVisibility(editor),
+        );
         if (this.config.testExplorer) {
             this.testController = vscode.tests.createTestController(
                 "rustAnalyzerTestController",
@@ -141,6 +146,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
     dispose() {
         this.config.dispose();
         this.statusBar.dispose();
+        this.statusBarActiveEditorListener.dispose();
         this.testController?.dispose();
         void this.disposeClient();
         this.commandDisposables.forEach((disposable) => disposable.dispose());
@@ -404,7 +410,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
         let icon = "";
         const status = this.lastStatus;
         const statusBar = this.statusBar;
-        statusBar.show();
         statusBar.tooltip = new vscode.MarkdownString("", true);
         statusBar.tooltip.isTrusted = true;
         switch (status.health) {
@@ -472,6 +477,17 @@ export class Ctx implements RustAnalyzerExtensionApi {
         statusBar.text = `${icon}rust-analyzer`;
     }
 
+    private updateStatusBarVisibility(editor: vscode.TextEditor | undefined) {
+        const documentSelector = this.config.statusBarDocumentSelector;
+        if (documentSelector != null) {
+            if (editor != null && vscode.languages.match(documentSelector, editor.document) > 0) {
+                this.statusBar.show();
+                return;
+            }
+        }
+        this.statusBar.hide();
+    }
+
     pushExtCleanup(d: Disposable) {
         this.extCtx.subscriptions.push(d);
     }
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index 9e2e3d2185b..f21ca2e8f96 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -148,8 +148,16 @@ async function getDebugConfiguration(
         return path.normalize(p).replace(wsFolder, `\${workspaceFolder${workspaceQualifier}}`);
     }
 
-    const env = prepareEnv(inheritEnv, runnable.label, runnableArgs, config.runnablesExtraEnv);
-    const executable = await getDebugExecutable(runnableArgs, env);
+    const executable = await getDebugExecutable(
+        runnableArgs,
+        prepareEnv(true, {}, config.runnablesExtraEnv(runnable.label)),
+    );
+
+    const env = prepareEnv(
+        inheritEnv,
+        runnableArgs.environment,
+        config.runnablesExtraEnv(runnable.label),
+    );
     let sourceFileMap = debugOptions.sourceFileMap;
 
     if (sourceFileMap === "auto") {
diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts
index 8a82a5a58cf..f71ab7ffbd8 100644
--- a/src/tools/rust-analyzer/editors/code/src/run.ts
+++ b/src/tools/rust-analyzer/editors/code/src/run.ts
@@ -5,7 +5,7 @@ import * as tasks from "./tasks";
 
 import type { CtxInit } from "./ctx";
 import { makeDebugConfig } from "./debug";
-import type { Config, RunnableEnvCfg, RunnableEnvCfgItem } from "./config";
+import type { Config } from "./config";
 import type { LanguageClient } from "vscode-languageclient/node";
 import { unwrapUndefinable, type RustEditor } from "./util";
 
@@ -81,32 +81,13 @@ export function prepareBaseEnv(
 
 export function prepareEnv(
     inheritEnv: boolean,
-    label: string,
-    runnableArgs: ra.CargoRunnableArgs,
-    runnableEnvCfg?: RunnableEnvCfg,
+    runnableEnv?: Record<string, string>,
+    runnableEnvCfg?: Record<string, string>,
 ): Record<string, string> {
-    const env = prepareBaseEnv(inheritEnv, runnableArgs.environment);
-    const platform = process.platform;
-
-    const checkPlatform = (it: RunnableEnvCfgItem) => {
-        if (it.platform) {
-            const platforms = Array.isArray(it.platform) ? it.platform : [it.platform];
-            return platforms.indexOf(platform) >= 0;
-        }
-        return true;
-    };
+    const env = prepareBaseEnv(inheritEnv, runnableEnv);
 
     if (runnableEnvCfg) {
-        if (Array.isArray(runnableEnvCfg)) {
-            for (const it of runnableEnvCfg) {
-                const masked = !it.mask || new RegExp(it.mask).test(label);
-                if (masked && checkPlatform(it)) {
-                    Object.assign(env, it.env);
-                }
-            }
-        } else {
-            Object.assign(env, runnableEnvCfg);
-        }
+        Object.assign(env, runnableEnvCfg);
     }
 
     return env;
@@ -140,7 +121,11 @@ export async function createTaskFromRunnable(
         };
         options = {
             cwd: runnableArgs.workspaceRoot || ".",
-            env: prepareEnv(true, runnable.label, runnableArgs, config.runnablesExtraEnv),
+            env: prepareEnv(
+                true,
+                runnableArgs.environment,
+                config.runnablesExtraEnv(runnable.label),
+            ),
         };
     } else {
         const runnableArgs = runnable.args;
diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts b/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts
deleted file mode 100644
index f0a62a3cce2..00000000000
--- a/src/tools/rust-analyzer/editors/code/tests/unit/runnable_env.test.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import * as assert from "assert";
-import { prepareEnv } from "../../src/run";
-import type { RunnableEnvCfg } from "../../src/config";
-import type { Context } from ".";
-import type * as ra from "../../src/lsp_ext";
-
-function makeRunnable(label: string): ra.Runnable {
-    return {
-        label,
-        kind: "cargo",
-        args: {
-            cargoArgs: [],
-            cwd: ".",
-            executableArgs: [],
-        },
-    };
-}
-
-function fakePrepareEnv(runnableName: string, config?: RunnableEnvCfg): Record<string, string> {
-    const runnable = makeRunnable(runnableName);
-    const runnableArgs = runnable.args as ra.CargoRunnableArgs;
-    return prepareEnv(false, runnable.label, runnableArgs, config);
-}
-
-export async function getTests(ctx: Context) {
-    await ctx.suite("Runnable env", (suite) => {
-        suite.addTest("Global config works", async () => {
-            const binEnv = fakePrepareEnv("run project_name", { GLOBAL: "g" });
-            assert.strictEqual(binEnv["GLOBAL"], "g");
-
-            const testEnv = fakePrepareEnv("test some::mod::test_name", { GLOBAL: "g" });
-            assert.strictEqual(testEnv["GLOBAL"], "g");
-        });
-
-        suite.addTest("null mask works", async () => {
-            const config = [
-                {
-                    env: { DATA: "data" },
-                },
-            ];
-            const binEnv = fakePrepareEnv("run project_name", config);
-            assert.strictEqual(binEnv["DATA"], "data");
-
-            const testEnv = fakePrepareEnv("test some::mod::test_name", config);
-            assert.strictEqual(testEnv["DATA"], "data");
-        });
-
-        suite.addTest("order works", async () => {
-            const config = [
-                {
-                    env: { DATA: "data" },
-                },
-                {
-                    env: { DATA: "newdata" },
-                },
-            ];
-            const binEnv = fakePrepareEnv("run project_name", config);
-            assert.strictEqual(binEnv["DATA"], "newdata");
-
-            const testEnv = fakePrepareEnv("test some::mod::test_name", config);
-            assert.strictEqual(testEnv["DATA"], "newdata");
-        });
-
-        suite.addTest("mask works", async () => {
-            const config = [
-                {
-                    env: { DATA: "data" },
-                },
-                {
-                    mask: "^run",
-                    env: { DATA: "rundata" },
-                },
-                {
-                    mask: "special_test$",
-                    env: { DATA: "special_test" },
-                },
-            ];
-            const binEnv = fakePrepareEnv("run project_name", config);
-            assert.strictEqual(binEnv["DATA"], "rundata");
-
-            const testEnv = fakePrepareEnv("test some::mod::test_name", config);
-            assert.strictEqual(testEnv["DATA"], "data");
-
-            const specialTestEnv = fakePrepareEnv("test some::mod::special_test", config);
-            assert.strictEqual(specialTestEnv["DATA"], "special_test");
-        });
-
-        suite.addTest("exact test name works", async () => {
-            const config = [
-                {
-                    env: { DATA: "data" },
-                },
-                {
-                    mask: "some::mod::test_name",
-                    env: { DATA: "test special" },
-                },
-            ];
-            const testEnv = fakePrepareEnv("test some::mod::test_name", config);
-            assert.strictEqual(testEnv["DATA"], "test special");
-
-            const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
-            assert.strictEqual(specialTestEnv["DATA"], "data");
-        });
-
-        suite.addTest("test mod name works", async () => {
-            const config = [
-                {
-                    env: { DATA: "data" },
-                },
-                {
-                    mask: "some::mod",
-                    env: { DATA: "mod special" },
-                },
-            ];
-            const testEnv = fakePrepareEnv("test some::mod::test_name", config);
-            assert.strictEqual(testEnv["DATA"], "mod special");
-
-            const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
-            assert.strictEqual(specialTestEnv["DATA"], "mod special");
-        });
-    });
-}
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 8f41ed9e14f..7d60fa6cb76 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-f005c7437def424a1c43cbc380352a58d8ac920b
+5a6036a1802262f8cf02192b02026688d396f1d7
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 18932587f1f..c3debc2f4f0 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -3597,7 +3597,7 @@ pub(crate) fn rewrite_extern_crate(
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     !matches!(
         item.kind,
-        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _))
+        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
     )
 }
 
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 493b04f16c6..a40ee7f66a9 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -316,12 +316,11 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
             self.directory = directory;
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
-            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
+            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => {
                 self.visit_mod_from_ast(items)
             }
-            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
-                self.visit_mod_outside_ast(items)
-            }
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _)
+            | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items),
             (_, _) => Ok(()),
         }
     }
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9b116b620b7..805e13b7803 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -927,7 +927,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
         self.push_str(&ident_str);
 
-        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind {
+        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind {
             let ast::ModSpans {
                 inner_span,
                 inject_use_span: _,
diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs
index 644df169a36..2d67e02eb9c 100644
--- a/tests/codegen/async-closure-debug.rs
+++ b/tests/codegen/async-closure-debug.rs
@@ -7,8 +7,6 @@
 // CHECK-DAG:  [[CLOSURE:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[GEN_FN]]
 // CHECK-DAG:  [[UPVAR:!.*]] = !DIDerivedType(tag: DW_TAG_member, name: "upvar", scope: [[CLOSURE]]
 
-#![feature(async_closure)]
-
 fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ {
     async move || {
         let hello = String::from("hello");
diff --git a/tests/codegen/instrument-coverage/testprog.rs b/tests/codegen/instrument-coverage/testprog.rs
index 655fe779fca..9e918499d57 100644
--- a/tests/codegen/instrument-coverage/testprog.rs
+++ b/tests/codegen/instrument-coverage/testprog.rs
@@ -73,11 +73,9 @@ fn main() {
 
 // WIN:          $__llvm_profile_runtime_user = comdat any
 
-// CHECK:        @__llvm_coverage_mapping = private constant
-// CHECK-SAME:   section "[[INSTR_PROF_COVMAP]]", align 8
+// CHECK-DAG:    @__llvm_coverage_mapping = private constant {{.*}}, section "[[INSTR_PROF_COVMAP]]", align 8
 
-// CHECK:        @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
-// CHECK-SAME:   section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+// CHECK-DAG:    @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant {{.*}}, section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
 
 // WIN:          @__llvm_profile_runtime = external{{.*}}global i32
 
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index e62adfa0ba6..0b2229ba7d1 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -25,9 +25,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 // CHECK-NOT: call void @llvm.memcpy
 
 // For a large type, we expect exactly three `memcpy`s
-// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8])
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}(ptr
+// CHECK-SAME: sret([56 x i8]){{.+}}[[RESULT:%.+]], ptr{{.+}}%dest, ptr{{.+}}%src)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 [[RESULT]], ptr align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs
index bcaa60baeff..8efedab6ea5 100644
--- a/tests/codegen/naked-asan.rs
+++ b/tests/codegen/naked-asan.rs
@@ -8,14 +8,15 @@
 #![no_std]
 #![feature(abi_x86_interrupt, naked_functions)]
 
-// CHECK: define x86_intrcc void @page_fault_handler(ptr {{.*}}%0, i64 {{.*}}%1){{.*}}#[[ATTRS:[0-9]+]] {
-// CHECK-NOT: memcpy
+pub fn caller() {
+    page_fault_handler(1, 2);
+}
+
+// CHECK: declare x86_intrcc void @page_fault_handler(ptr {{.*}}, i64{{.*}}){{.*}}#[[ATTRS:[0-9]+]]
 #[naked]
 #[no_mangle]
 pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
-    unsafe {
-        core::arch::naked_asm!("ud2");
-    }
+    unsafe { core::arch::naked_asm!("ud2") };
 }
 
 // CHECK: #[[ATTRS]] =
diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs
index 3bbd67981e5..d9dcd7f6c3e 100644
--- a/tests/codegen/naked-fn/aligned.rs
+++ b/tests/codegen/naked-fn/aligned.rs
@@ -6,15 +6,12 @@
 #![feature(naked_functions, fn_align)]
 use std::arch::naked_asm;
 
-// CHECK: Function Attrs: naked
-// CHECK-NEXT: define{{.*}}void @naked_empty()
-// CHECK: align 16
+// CHECK: .balign 16
+// CHECK-LABEL: naked_empty:
 #[repr(align(16))]
 #[no_mangle]
 #[naked]
 pub unsafe extern "C" fn naked_empty() {
-    // CHECK-NEXT: start:
-    // CHECK-NEXT: call void asm
-    // CHECK-NEXT: unreachable
+    // CHECK: ret
     naked_asm!("ret");
 }
diff --git a/tests/codegen/naked-fn/generics.rs b/tests/codegen/naked-fn/generics.rs
new file mode 100644
index 00000000000..a33d213617a
--- /dev/null
+++ b/tests/codegen/naked-fn/generics.rs
@@ -0,0 +1,116 @@
+//@ compile-flags: -O
+//@ only-x86_64
+
+#![crate_type = "lib"]
+#![feature(naked_functions, asm_const)]
+
+use std::arch::naked_asm;
+
+#[no_mangle]
+fn test(x: u64) {
+    // just making sure these symbols get used
+    using_const_generics::<1>(x);
+    using_const_generics::<2>(x);
+
+    generic_function::<i64>(x as i64);
+
+    let foo = Foo(x);
+
+    foo.method();
+    foo.trait_method();
+}
+
+// CHECK: .balign 4
+// CHECK: add rax, 2
+// CHECK: add rax, 42
+
+// CHECK: .balign 4
+// CHECK: add rax, 1
+// CHECK: add rax, 42
+
+#[naked]
+pub extern "C" fn using_const_generics<const N: u64>(x: u64) -> u64 {
+    const M: u64 = 42;
+
+    unsafe {
+        naked_asm!(
+            "xor rax, rax",
+            "add rax, rdi",
+            "add rax, {}",
+            "add rax, {}",
+            "ret",
+            const N,
+            const M,
+        )
+    }
+}
+
+trait Invert {
+    fn invert(self) -> Self;
+}
+
+impl Invert for i64 {
+    fn invert(self) -> Self {
+        -1 * self
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: generic_function:
+// CHECK: call
+// CHECK: ret
+
+#[naked]
+#[no_mangle]
+pub extern "C" fn generic_function<T: Invert>(x: i64) -> i64 {
+    unsafe {
+        naked_asm!(
+            "call {}",
+            "ret",
+            sym <T as Invert>::invert,
+        )
+    }
+}
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+struct Foo(u64);
+
+// CHECK: .balign 4
+// CHECK-LABEL: method:
+// CHECK: mov rax, rdi
+
+impl Foo {
+    #[naked]
+    #[no_mangle]
+    extern "C" fn method(self) -> u64 {
+        unsafe { naked_asm!("mov rax, rdi", "ret") }
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: trait_method:
+// CHECK: mov rax, rdi
+
+trait Bar {
+    extern "C" fn trait_method(self) -> u64;
+}
+
+impl Bar for Foo {
+    #[naked]
+    #[no_mangle]
+    extern "C" fn trait_method(self) -> u64 {
+        unsafe { naked_asm!("mov rax, rdi", "ret") }
+    }
+}
+
+// CHECK: .balign 4
+// CHECK-LABEL: naked_with_args_and_return:
+// CHECK: lea rax, [rdi + rsi]
+
+// this previously ICE'd, see https://github.com/rust-lang/rust/issues/124375
+#[naked]
+#[no_mangle]
+pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
+    naked_asm!("lea rax, [rdi + rsi]", "ret");
+}
diff --git a/tests/codegen/naked-fn/instruction-set.rs b/tests/codegen/naked-fn/instruction-set.rs
new file mode 100644
index 00000000000..5b790b2034c
--- /dev/null
+++ b/tests/codegen/naked-fn/instruction-set.rs
@@ -0,0 +1,59 @@
+//@ revisions: arm-mode thumb-mode
+//@ [arm-mode] compile-flags: --target armv5te-none-eabi
+//@ [thumb-mode] compile-flags: --target thumbv5te-none-eabi
+//@ [arm-mode] needs-llvm-components: arm
+//@ [thumb-mode] needs-llvm-components: arm
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, rustc_attrs, naked_functions)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! naked_asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// arm-mode: .arm
+// thumb-mode: .thumb
+// CHECK-LABEL: test_unspecified:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn test_unspecified() {
+    naked_asm!("bx lr");
+}
+
+// CHECK: .thumb
+// CHECK: .thumb_func
+// CHECK-LABEL: test_thumb:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[naked]
+#[instruction_set(arm::t32)]
+unsafe extern "C" fn test_thumb() {
+    naked_asm!("bx lr");
+}
+
+// CHECK: .arm
+// CHECK-LABEL: test_arm:
+// CHECK: bx lr
+// CHECK: .popsection
+// arm-mode: .arm
+// thumb-mode: .thumb
+#[no_mangle]
+#[naked]
+#[instruction_set(arm::a32)]
+unsafe extern "C" fn test_arm() {
+    naked_asm!("bx lr");
+}
diff --git a/tests/codegen/naked-fn/naked-functions.rs b/tests/codegen/naked-fn/naked-functions.rs
index 3f7447af599..f505d27d48c 100644
--- a/tests/codegen/naked-fn/naked-functions.rs
+++ b/tests/codegen/naked-fn/naked-functions.rs
@@ -1,29 +1,147 @@
-//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
-//@ needs-asm-support
-//@ only-x86_64
+//@ revisions: linux win macos thumb
+//
+//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[linux] needs-llvm-components: x86
+//@[win] compile-flags: --target x86_64-pc-windows-gnu
+//@[win] needs-llvm-components: x86
+//@[macos] compile-flags: --target aarch64-apple-darwin
+//@[macos] needs-llvm-components: arm
+//@[thumb] compile-flags: --target thumbv7em-none-eabi
+//@[thumb] needs-llvm-components: arm
 
 #![crate_type = "lib"]
-#![feature(naked_functions)]
-use std::arch::naked_asm;
+#![feature(no_core, lang_items, rustc_attrs, naked_functions)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! naked_asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// linux,win: .intel_syntax
+//
+// linux:   .pushsection .text.naked_empty,\22ax\22, @progbits
+// macos:   .pushsection __TEXT,__text,regular,pure_instructions
+// win: .pushsection .text.naked_empty,\22xr\22
+// thumb:   .pushsection .text.naked_empty,\22ax\22, %progbits
+//
+// CHECK: .balign 4
+//
+// linux,win,thumb: .globl naked_empty
+// macos: .globl _naked_empty
+//
+// CHECK-NOT: .private_extern
+// CHECK-NOT: .hidden
+//
+// linux: .type naked_empty, @function
+//
+// win: .def naked_empty
+// win: .scl 2
+// win: .type 32
+// win: .endef naked_empty
+//
+// thumb: .type naked_empty, %function
+// thumb: .thumb
+// thumb: .thumb_func
+//
+// CHECK-LABEL: naked_empty:
+//
+// linux,macos,win: ret
+// thumb: bx lr
+//
+// CHECK: .popsection
+//
+// thumb: .thumb
+//
+// linux,win: .att_syntax
 
-// CHECK: Function Attrs: naked
-// CHECK-NEXT: define{{.*}}void @naked_empty()
 #[no_mangle]
 #[naked]
 pub unsafe extern "C" fn naked_empty() {
-    // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: call void asm
-    // CHECK-NEXT: unreachable
+    #[cfg(not(all(target_arch = "arm", target_feature = "thumb-mode")))]
     naked_asm!("ret");
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    naked_asm!("bx lr");
 }
 
-// CHECK: Function Attrs: naked
-// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i64 %0, i64 %1)
+// linux,win: .intel_syntax
+//
+// linux:   .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits
+// macos:   .pushsection __TEXT,__text,regular,pure_instructions
+// win: .pushsection .text.naked_with_args_and_return,\22xr\22
+// thumb:   .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits
+//
+// CHECK: .balign 4
+//
+// linux,win,thumb: .globl naked_with_args_and_return
+// macos: .globl _naked_with_args_and_return
+//
+// CHECK-NOT: .private_extern
+// CHECK-NOT: .hidden
+//
+// linux: .type naked_with_args_and_return, @function
+//
+// win: .def naked_with_args_and_return
+// win: .scl 2
+// win: .type 32
+// win: .endef naked_with_args_and_return
+//
+// thumb: .type naked_with_args_and_return, %function
+// thumb: .thumb
+// thumb: .thumb_func
+//
+// CHECK-LABEL: naked_with_args_and_return:
+//
+// linux, win: lea rax, [rdi + rsi]
+// macos: add x0, x0, x1
+// thumb: adds r0, r0, r1
+//
+// linux,macos,win: ret
+// thumb: bx lr
+//
+// CHECK: .popsection
+//
+// thumb: .thumb
+//
+// linux,win: .att_syntax
+
 #[no_mangle]
 #[naked]
 pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
-    // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: call void asm
-    // CHECK-NEXT: unreachable
-    naked_asm!("lea rax, [rdi + rsi]", "ret");
+    #[cfg(any(target_os = "windows", target_os = "linux"))]
+    {
+        naked_asm!("lea rax, [rdi + rsi]", "ret")
+    }
+
+    #[cfg(target_os = "macos")]
+    {
+        naked_asm!("add x0, x0, x1", "ret")
+    }
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    {
+        naked_asm!("adds r0, r0, r1", "bx lr")
+    }
+}
+
+// linux:   .pushsection .text.some_different_name,\22ax\22, @progbits
+// macos:   .pushsection .text.some_different_name,regular,pure_instructions
+// win: .pushsection .text.some_different_name,\22xr\22
+// thumb:   .pushsection .text.some_different_name,\22ax\22, %progbits
+// CHECK-LABEL: test_link_section:
+#[no_mangle]
+#[naked]
+#[link_section = ".text.some_different_name"]
+pub unsafe extern "C" fn test_link_section() {
+    #[cfg(not(all(target_arch = "arm", target_feature = "thumb-mode")))]
+    naked_asm!("ret");
+
+    #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
+    naked_asm!("bx lr");
 }
diff --git a/tests/codegen/naked-fn/naked-nocoverage.rs b/tests/codegen/naked-fn/naked-nocoverage.rs
deleted file mode 100644
index f63661bcd3a..00000000000
--- a/tests/codegen/naked-fn/naked-nocoverage.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Checks that naked functions are not instrumented by -Cinstrument-coverage.
-// Regression test for issue #105170.
-//
-//@ needs-asm-support
-//@ compile-flags: -Zno-profiler-runtime
-//@ compile-flags: -Cinstrument-coverage
-#![crate_type = "lib"]
-#![feature(naked_functions)]
-use std::arch::naked_asm;
-
-#[naked]
-#[no_mangle]
-pub unsafe extern "C" fn f() {
-    // CHECK:       define {{(dso_local )?}}void @f()
-    // CHECK-NEXT:  start:
-    // CHECK-NEXT:    call void asm
-    // CHECK-NEXT:    unreachable
-    naked_asm!("");
-}
diff --git a/tests/codegen/naked-fn/naked-noinline.rs b/tests/codegen/naked-fn/naked-noinline.rs
deleted file mode 100644
index 6ea36d96783..00000000000
--- a/tests/codegen/naked-fn/naked-noinline.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Checks that naked functions are never inlined.
-//@ compile-flags: -O -Zmir-opt-level=3
-//@ needs-asm-support
-//@ ignore-wasm32
-#![crate_type = "lib"]
-#![feature(naked_functions)]
-
-use std::arch::naked_asm;
-
-#[naked]
-#[no_mangle]
-pub unsafe extern "C" fn f() {
-    // Check that f has naked and noinline attributes.
-    //
-    // CHECK:       define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]]
-    // CHECK-NEXT:  start:
-    // CHECK-NEXT:    call void asm
-    naked_asm!("");
-}
-
-#[no_mangle]
-pub unsafe fn g() {
-    // Check that call to f is not inlined.
-    //
-    // CHECK-LABEL: define {{(dso_local )?}}void @g()
-    // CHECK-NEXT:  start:
-    // CHECK-NEXT:    call void @f()
-    f();
-}
-
-// CHECK: attributes [[ATTR]] = { naked{{.*}}noinline{{.*}} }
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 9ff29af8e8e..04c05ba098b 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -1,56 +1,56 @@
 Function name: async_closure::call_once::<async_closure::main::{closure#0}>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 01, 00, 2b]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 43)
 Highest counter ID seen: c0
 
 Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 06, 2b, 01, 0e, 05, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14)
+- Code(Counter(0)) at (prev + 6, 43) to (start + 1, 14)
 - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
 Highest counter ID seen: c1
 
 Function name: async_closure::main
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 01, 01, 16, 01, 02, 05, 02, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 01, 01, 16, 01, 02, 05, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 22)
+- Code(Counter(0)) at (prev + 10, 1) to (start + 1, 22)
 - Code(Counter(0)) at (prev + 2, 5) to (start + 2, 2)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 22, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 12, 34) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
index 75da1a01fc1..7fbea265812 100644
--- a/tests/coverage/async_closure.coverage
+++ b/tests/coverage/async_closure.coverage
@@ -1,4 +1,3 @@
-   LL|       |#![feature(async_closure)]
    LL|       |//@ edition: 2021
    LL|       |
    LL|       |//@ aux-build: executor.rs
diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs
index cbac592d957..85c5df1f1ab 100644
--- a/tests/coverage/async_closure.rs
+++ b/tests/coverage/async_closure.rs
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 //@ edition: 2021
 
 //@ aux-build: executor.rs
diff --git a/tests/crashes/116979.rs b/tests/crashes/116979.rs
new file mode 100644
index 00000000000..28bbc972ea3
--- /dev/null
+++ b/tests/crashes/116979.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #116979
+//@ compile-flags: -Csymbol-mangling-version=v0
+//@ needs-rustc-debug-assertions
+
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+
+pub fn require_dyn_star_display(_: dyn* Display) {}
+
+fn main() {
+    require_dyn_star_display(1usize);
+}
diff --git a/tests/crashes/117808.rs b/tests/crashes/117808.rs
new file mode 100644
index 00000000000..2c727986dd0
--- /dev/null
+++ b/tests/crashes/117808.rs
@@ -0,0 +1,27 @@
+//@ known-bug: #117808
+//@ edition:2021
+//@ needs-rustc-debug-assertions
+
+use std::future::Future;
+
+fn hrc<R, F: for<'a> AsyncClosure<'a, (), R>>(f: F) -> F {
+    f
+}
+
+fn main() {
+    hrc(|x| async {});
+}
+
+trait AsyncClosure<'a, I, R>
+where
+    I: 'a,
+{
+}
+
+impl<'a, I, R, Fut, F> AsyncClosure<'a, I, R> for F
+where
+    I: 'a,
+    F: Fn(&'a I) -> Fut,
+    Fut: Future<Output = R> + Send + 'a,
+{
+}
diff --git a/tests/crashes/117877.rs b/tests/crashes/117877.rs
new file mode 100644
index 00000000000..b1effc0cbcb
--- /dev/null
+++ b/tests/crashes/117877.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #117877
+//@ edition:2021
+//@ needs-rustc-debug-assertions
+//@ only-x86_64
+#![feature(asm_const)]
+
+use std::arch::asm;
+
+async unsafe fn foo<'a>() {
+    asm!("/* {0} */", const N);
+}
+
+fn main() {}
diff --git a/tests/crashes/118778.rs b/tests/crashes/118778.rs
new file mode 100644
index 00000000000..9914e76022d
--- /dev/null
+++ b/tests/crashes/118778.rs
@@ -0,0 +1,24 @@
+//@ known-bug: #118778
+//@ edition:2021
+//@ needs-rustc-debug-assertions
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Owner {
+    type T<const N: u16>;
+}
+
+impl Owner for () {
+    type T<const N: u32> = U32<{ N + 1 }>
+    where
+        U32<{ N + 1 }>:;
+}
+
+struct U32<const N: u32>;
+
+fn take1(_: impl Owner<T<1> = U32<1>>) {}
+
+fn main() {
+    take1(());
+}
diff --git a/tests/crashes/118784.rs b/tests/crashes/118784.rs
new file mode 100644
index 00000000000..7bf943c8177
--- /dev/null
+++ b/tests/crashes/118784.rs
@@ -0,0 +1,19 @@
+//@ known-bug: #118784
+//@ needs-rustc-debug-assertions
+
+use std::collections::HashMap;
+
+macro_rules! all_sync_send {
+    ($ctor:expr, $($iter:expr),+) => ({
+        $(
+            let mut x = $ctor;
+            is_sync(x.$iter());
+            let mut y = $ctor;
+            is_send(y.$iter());
+        )+
+    })
+}
+
+fn main() {
+    all_sync_send!(HashMap, HashMap);
+}
diff --git a/tests/crashes/120175.rs b/tests/crashes/120175.rs
new file mode 100644
index 00000000000..c6e7203ff98
--- /dev/null
+++ b/tests/crashes/120175.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #120175
+//@ needs-rustc-debug-assertions
+
+#![feature(extern_types)]
+
+#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
+extern "C" {
+    pub type CrossCrate;
+}
+
+fn main() {}
diff --git a/tests/crashes/121176.rs b/tests/crashes/121176.rs
new file mode 100644
index 00000000000..4d82e51de8f
--- /dev/null
+++ b/tests/crashes/121176.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #121176
+//@ needs-rustc-debug-assertions
+use std::fmt::Debug;
+
+static STATIC_1: dyn Debug + Sync = *();
+
+fn main() {
+    println!("{:?}", &STATIC_1);
+}
diff --git a/tests/crashes/123861.rs b/tests/crashes/123861.rs
new file mode 100644
index 00000000000..60245960af0
--- /dev/null
+++ b/tests/crashes/123861.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #123861
+//@ needs-rustc-debug-assertions
+
+struct _;
+fn mainIterator<_ = _> {}
diff --git a/tests/crashes/123862.rs b/tests/crashes/123862.rs
new file mode 100644
index 00000000000..075e0e6fc8f
--- /dev/null
+++ b/tests/crashes/123862.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #123862
+//@ needs-rustc-debug-assertions
+
+macro_rules! pos {
+    () => {
+        (file![$($pos,)* pos!()], line!())
+    };
+}
+
+fn outer() {
+    inner_inlined(main_pos, pos!());
+}
+
+fn inner_inlined() {}
diff --git a/tests/crashes/124375.rs b/tests/crashes/124375.rs
deleted file mode 100644
index 1d877caeb8b..00000000000
--- a/tests/crashes/124375.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #124375
-//@ compile-flags: -Zmir-opt-level=0
-//@ only-x86_64
-#![crate_type = "lib"]
-#![feature(naked_functions)]
-use std::arch::naked_asm;
-
-#[naked]
-pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
-    naked_asm!("lea rax, [rdi + rsi]", "ret");
-}
diff --git a/tests/crashes/130395.rs b/tests/crashes/130395.rs
new file mode 100644
index 00000000000..c1d189c79ba
--- /dev/null
+++ b/tests/crashes/130395.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #130395
+//@ needs-rustc-debug-assertions
+
+enum U {
+    B(isize, usize),
+}
+
+fn main() {
+    let x = T::A(U::C);
+}
diff --git a/tests/crashes/132765.rs b/tests/crashes/132765.rs
new file mode 100644
index 00000000000..01e8fdaacff
--- /dev/null
+++ b/tests/crashes/132765.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #132765
+
+trait LendingIterator {
+    type Item<'q>;
+    fn for_each(&self, _f: Box<fn(Self::Item<'_>)>) {}
+}
+
+fn f(_: ()) {}
+
+fn main() {
+    LendingIterator::for_each(&(), f);
+}
diff --git a/tests/crashes/132766.rs b/tests/crashes/132766.rs
new file mode 100644
index 00000000000..5f5117d77a5
--- /dev/null
+++ b/tests/crashes/132766.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #132766
+
+trait Trait {}
+impl<'a> Trait for () {
+    fn pass2<'a>() -> impl Trait2 {}
+}
+
+trait Trait2 {}
+impl Trait2 for () {}
diff --git a/tests/crashes/132882.rs b/tests/crashes/132882.rs
new file mode 100644
index 00000000000..6b5e4dba803
--- /dev/null
+++ b/tests/crashes/132882.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #132882
+
+use std::ops::Add;
+
+pub trait Numoid
+where
+    for<N: Numoid> &'a Self: Add<Self>,
+{
+}
+
+pub fn compute<N: Numoid>(a: N) -> N {
+    &a + a
+}
diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs
new file mode 100644
index 00000000000..8ff4fa36fd0
--- /dev/null
+++ b/tests/crashes/132981.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #132981
+//@compile-flags: -Clink-dead-code=true --crate-type lib
+//@ only-x86_64
+//@ ignore-windows
+
+#![feature(rust_cold_cc)]
+pub extern "rust-cold" fn foo(_: [usize; 3]) {}
diff --git a/tests/crashes/133063.rs b/tests/crashes/133063.rs
new file mode 100644
index 00000000000..132b5486170
--- /dev/null
+++ b/tests/crashes/133063.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #133063
+
+fn foo(x: !) {
+    match x {
+        (! | !) if false => {}
+        _ => {}
+    }
+}
diff --git a/tests/crashes/133066.rs b/tests/crashes/133066.rs
new file mode 100644
index 00000000000..732ebb7079f
--- /dev/null
+++ b/tests/crashes/133066.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #133066
+trait Owner {
+    const C<const N: u32>: u32;
+}
+
+impl Owner for () {;}
+
+fn take0<const N: u64>(_: impl Owner<C<N> = { N }>) {}
+
+fn main() {
+    take0::<f32, >(());
+}
diff --git a/tests/crashes/133199.rs b/tests/crashes/133199.rs
new file mode 100644
index 00000000000..76535fa83a6
--- /dev/null
+++ b/tests/crashes/133199.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #133199
+//@ aux-build: aux133199.rs
+
+extern crate aux133199;
+
+use aux133199::FixedBitSet;
+
+fn main() {
+    FixedBitSet::<7>::new();
+    //~^ ERROR
+}
diff --git a/tests/crashes/133275-1.rs b/tests/crashes/133275-1.rs
new file mode 100644
index 00000000000..73c04f5d6e4
--- /dev/null
+++ b/tests/crashes/133275-1.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #133275
+#![feature(const_trait_impl)]
+#![feature(associated_type_defaults)]
+
+#[const_trait]
+trait Foo3<T>
+where
+    Self::Baz: Clone,
+{
+    type Baz = T;
+}
+
+pub fn main() {}
diff --git a/tests/crashes/133275-2.rs b/tests/crashes/133275-2.rs
new file mode 100644
index 00000000000..a774b3cdb69
--- /dev/null
+++ b/tests/crashes/133275-2.rs
@@ -0,0 +1,15 @@
+//@ known-bug: #133275
+#![feature(const_trait_impl)]
+#[const_trait]
+pub trait Owo<X = <IntEnum as Uwu>::T> {}
+
+#[const_trait]
+trait Foo3<T>
+where
+    Self::Bar: Clone,
+    Self::Baz: Clone,
+{
+    type Bar = Vec<Self::Baz>;
+    type Baz = T;
+    //~^ ERROR the trait bound `T: Clone` is not satisfied
+}
diff --git a/tests/crashes/auxiliary/aux133199.rs b/tests/crashes/auxiliary/aux133199.rs
new file mode 100644
index 00000000000..40765d92fbf
--- /dev/null
+++ b/tests/crashes/auxiliary/aux133199.rs
@@ -0,0 +1,13 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+pub struct FixedBitSet<const N: usize>;
+
+impl<const N: usize> FixedBitSet<N>
+where
+    [u8; N.div_ceil(8)]: Sized,
+{
+    pub fn new() -> Self {
+        todo!()
+    }
+}
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
index 7da33b8a094..8a584853e00 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built
 
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
index a21e82ef5b6..a9e08d2e8f6 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
 
-fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
index c1566360995..a984845fd2c 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
@@ -1,10 +1,10 @@
 // MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
 
-fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:54:33: 54:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10};
+fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10};
 
     bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:54:53: 57:10 (#0)} { a: move _2, b: move (_1.0: i32) };
+        _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) };
         return;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
index a4a6a535a23..c6721085eb2 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built
 
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
index 69bba6f5194..4452ae7812e 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
 
-fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
index 134fe145bae..aab9f7b03b9 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
@@ -1,10 +1,10 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move
 
-fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
+fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
 
     bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
+        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
         return;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
index f267d93bd60..3fdc81791de 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
@@ -1,10 +1,10 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
 
-fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
+fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
 
     bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
+        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
         return;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index f28400e298f..cd2e83e939a 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -1,7 +1,6 @@
 //@ edition:2021
 // skip-filecheck
 
-#![feature(async_closure, async_fn_traits)]
 #![allow(unused)]
 
 use std::future::Future;
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 94017f028cc..56d4d50e967 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 858f9ace9b4..751916a00f1 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 2efbb6d9904..3f0d60b46f4 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 2efbb6d9904..3f0d60b46f4 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/strip_debuginfo.rs b/tests/mir-opt/strip_debuginfo.rs
new file mode 100644
index 00000000000..310609e1e9d
--- /dev/null
+++ b/tests/mir-opt/strip_debuginfo.rs
@@ -0,0 +1,39 @@
+//@ revisions: NONE TINY ALL
+//@[NONE] compile-flags: -Zmir_strip_debuginfo=none
+//@[TINY] compile-flags: -Zmir_strip_debuginfo=locals-in-tiny-functions
+//@[ALL] compile-flags: -Zmir_strip_debuginfo=all-locals
+
+// CHECK: fn tiny_function
+fn tiny_function(end: u32) -> u32 {
+    // CHECK: debug end => _1;
+    // NONE: debug a =>
+    // NONE: debug b =>
+    // TINY-NOT: debug a =>
+    // TINY-NOT: debug b =>
+    // ALL-NOT: debug a =>
+    // ALL-NOT: debug b =>
+    let a = !end;
+    let b = a ^ 1;
+    b
+}
+
+#[inline(never)]
+fn opaque(_: u32) {}
+
+// CHECK: fn looping_function
+fn looping_function(end: u32) {
+    // CHECK: debug end => _1;
+    // NONE: debug i =>
+    // NONE: debug x =>
+    // TINY: debug i =>
+    // TINY: debug x =>
+    // ALL-NOT: debug i =>
+    // ALL-NOT: debug x =>
+    let mut i = 0;
+    while i < end {
+        let x = i ^ 1;
+        opaque(x);
+    }
+}
+
+fn main() {}
diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
index 56708ec9310..6ab3cc6f6fe 100644
--- a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -1,5 +1,3 @@
-#![feature(async_closure)]
-
 use std::ops::AsyncFnMut;
 
 pub trait Main {
diff --git a/tests/ui/alias-uninit-value.rs b/tests/ui/alias-uninit-value.rs
deleted file mode 100644
index 0084a98e627..00000000000
--- a/tests/ui/alias-uninit-value.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//@ run-pass
-
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-
-
-
-// Regression test for issue #374
-
-
-enum sty { ty_nil, }
-
-struct RawT {struct_: sty, cname: Option<String>, hash: usize}
-
-fn mk_raw_ty(st: sty, cname: Option<String>) -> RawT {
-    return RawT {struct_: st, cname: cname, hash: 0};
-}
-
-pub fn main() { mk_raw_ty(sty::ty_nil, None::<String>); }
diff --git a/tests/ui/allow-non-lint-warnings.rs b/tests/ui/allow-non-lint-warnings.rs
deleted file mode 100644
index f8f5a78ebff..00000000000
--- a/tests/ui/allow-non-lint-warnings.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ compile-flags: -Awarnings
-//@ check-pass
-
-#[derive()]
-#[derive(Copy, Clone)]
-pub struct Foo;
-
-pub fn main() {}
diff --git a/tests/ui/artificial-block.rs b/tests/ui/artificial-block.rs
deleted file mode 100644
index 037163b4174..00000000000
--- a/tests/ui/artificial-block.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ run-pass
-
-fn f() -> isize { { return 3; } }
-
-pub fn main() { assert_eq!(f(), 3); }
diff --git a/tests/ui/as-precedence.rs b/tests/ui/as-precedence.rs
deleted file mode 100644
index 5021a3b677f..00000000000
--- a/tests/ui/as-precedence.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-pass
-
-#[allow(unused_parens)]
-fn main() {
-    assert_eq!(3 as usize * 3, 9);
-    assert_eq!(3 as (usize) * 3, 9);
-    assert_eq!(3 as (usize) / 3, 1);
-    assert_eq!(3 as usize + 3, 6);
-    assert_eq!(3 as (usize) + 3, 6);
-}
diff --git a/tests/ui/asm/aarch64/srcloc.new.stderr b/tests/ui/asm/aarch64/srcloc.new.stderr
new file mode 100644
index 00000000000..b92a07e5fb1
--- /dev/null
+++ b/tests/ui/asm/aarch64/srcloc.new.stderr
@@ -0,0 +1,320 @@
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:15:15
+   |
+LL |         asm!("invalid_instruction");
+   |               ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:19:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:13
+   |
+LL |             invalid_instruction
+   |             ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:24:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:13
+   |
+LL |             invalid_instruction
+   |             ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:30:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:37:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:42:14
+   |
+LL |         asm!(concat!("invalid", "_", "instruction"));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:46:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:52:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:59:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:66:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:73:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:80:14
+   |
+LL |             "invalid_instruction1",
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction1
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:81:14
+   |
+LL |             "invalid_instruction2",
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction2
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:87:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction1
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:87:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction2
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:96:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction1
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:96:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction2
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:100:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction3
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:100:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:1
+   |
+LL | invalid_instruction4
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:111:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     invalid_instruction1
+   |     ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:111:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction2
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:115:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:1
+   |
+LL | invalid_instruction3
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:115:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:5:1
+   |
+LL | invalid_instruction4
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:128:14
+   |
+LL |             "invalid_instruction"
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/asm/aarch64/srcloc.stderr b/tests/ui/asm/aarch64/srcloc.old.stderr
index 2e17b60b912..2a15e48f025 100644
--- a/tests/ui/asm/aarch64/srcloc.stderr
+++ b/tests/ui/asm/aarch64/srcloc.old.stderr
@@ -1,5 +1,5 @@
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:12:15
+  --> $DIR/srcloc.rs:15:15
    |
 LL |         asm!("invalid_instruction");
    |               ^
@@ -11,7 +11,7 @@ LL |     invalid_instruction
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:16:13
+  --> $DIR/srcloc.rs:19:13
    |
 LL |             invalid_instruction
    |             ^
@@ -23,7 +23,7 @@ LL |             invalid_instruction
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:21:13
+  --> $DIR/srcloc.rs:24:13
    |
 LL |             invalid_instruction
    |             ^
@@ -35,7 +35,7 @@ LL |             invalid_instruction
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:27:13
+  --> $DIR/srcloc.rs:30:13
    |
 LL |             invalid_instruction
    |             ^
@@ -47,7 +47,7 @@ LL |             invalid_instruction
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:34:13
+  --> $DIR/srcloc.rs:37:13
    |
 LL |             invalid_instruction
    |             ^
@@ -59,7 +59,7 @@ LL |             invalid_instruction
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:39:14
+  --> $DIR/srcloc.rs:42:14
    |
 LL |         asm!(concat!("invalid", "_", "instruction"));
    |              ^
@@ -71,7 +71,7 @@ LL |     invalid_instruction
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:43:14
+  --> $DIR/srcloc.rs:46:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -83,7 +83,7 @@ LL |     invalid_instruction
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:49:14
+  --> $DIR/srcloc.rs:52:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -95,7 +95,7 @@ LL | invalid_instruction
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:56:14
+  --> $DIR/srcloc.rs:59:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -107,7 +107,7 @@ LL | invalid_instruction
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:63:13
+  --> $DIR/srcloc.rs:66:13
    |
 LL |             concat!("invalid", "_", "instruction"),
    |             ^
@@ -119,7 +119,7 @@ LL | invalid_instruction
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:70:13
+  --> $DIR/srcloc.rs:73:13
    |
 LL |             concat!("invalid", "_", "instruction"),
    |             ^
@@ -131,7 +131,7 @@ LL | invalid_instruction
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:77:14
+  --> $DIR/srcloc.rs:80:14
    |
 LL |             "invalid_instruction1",
    |              ^
@@ -143,7 +143,7 @@ LL |     invalid_instruction1
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:78:14
+  --> $DIR/srcloc.rs:81:14
    |
 LL |             "invalid_instruction2",
    |              ^
@@ -155,7 +155,7 @@ LL | invalid_instruction2
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:84:13
+  --> $DIR/srcloc.rs:87:13
    |
 LL |             concat!(
    |             ^
@@ -167,7 +167,7 @@ LL |     invalid_instruction1
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:84:13
+  --> $DIR/srcloc.rs:87:13
    |
 LL |             concat!(
    |             ^
@@ -179,7 +179,7 @@ LL | invalid_instruction2
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:93:13
+  --> $DIR/srcloc.rs:96:13
    |
 LL |             concat!(
    |             ^
@@ -191,7 +191,7 @@ LL |     invalid_instruction1
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:93:13
+  --> $DIR/srcloc.rs:96:13
    |
 LL |             concat!(
    |             ^
@@ -203,7 +203,7 @@ LL | invalid_instruction2
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:97:13
+  --> $DIR/srcloc.rs:100:13
    |
 LL |             concat!(
    |             ^
@@ -215,7 +215,7 @@ LL | invalid_instruction3
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:97:13
+  --> $DIR/srcloc.rs:100:13
    |
 LL |             concat!(
    |             ^
@@ -227,7 +227,7 @@ LL | invalid_instruction4
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:108:13
+  --> $DIR/srcloc.rs:111:13
    |
 LL |             concat!(
    |             ^
@@ -239,7 +239,7 @@ LL |     invalid_instruction1
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:108:13
+  --> $DIR/srcloc.rs:111:13
    |
 LL |             concat!(
    |             ^
@@ -251,7 +251,7 @@ LL | invalid_instruction2
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:112:13
+  --> $DIR/srcloc.rs:115:13
    |
 LL |             concat!(
    |             ^
@@ -263,7 +263,7 @@ LL | invalid_instruction3
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:112:13
+  --> $DIR/srcloc.rs:115:13
    |
 LL |             concat!(
    |             ^
@@ -275,7 +275,7 @@ LL | invalid_instruction4
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:125:14
+  --> $DIR/srcloc.rs:128:14
    |
 LL |             "invalid_instruction"
    |              ^
diff --git a/tests/ui/asm/aarch64/srcloc.rs b/tests/ui/asm/aarch64/srcloc.rs
index c635fa6ba70..9b92dfef056 100644
--- a/tests/ui/asm/aarch64/srcloc.rs
+++ b/tests/ui/asm/aarch64/srcloc.rs
@@ -1,7 +1,10 @@
+//@ revisions: old new
 //@ only-aarch64
 //@ build-fail
 //@ needs-asm-support
 //@ compile-flags: -Ccodegen-units=1
+//@[old] ignore-llvm-version: 19 - 99
+//@[new] min-llvm-version: 19
 
 use std::arch::asm;
 
diff --git a/tests/ui/asm/generic_const_simd_vec_len.rs b/tests/ui/asm/generic_const_simd_vec_len.rs
new file mode 100644
index 00000000000..fb8c5274ddb
--- /dev/null
+++ b/tests/ui/asm/generic_const_simd_vec_len.rs
@@ -0,0 +1,21 @@
+//! This is a regression test to ensure that we emit a diagnostic pointing to the
+//! reason the type was rejected in inline assembly.
+
+//@ only-x86_64
+
+#![feature(repr_simd)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct Foo<const C: usize>([u8; C]);
+//~^ ERROR: cannot evaluate SIMD vector length
+
+pub unsafe fn foo<const C: usize>(a: Foo<C>) {
+    std::arch::asm!(
+        "movaps {src}, {src}",
+        src = in(xmm_reg) a,
+        //~^ NOTE: SIMD vector length needs to be known statically
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/asm/generic_const_simd_vec_len.stderr b/tests/ui/asm/generic_const_simd_vec_len.stderr
new file mode 100644
index 00000000000..486281b6062
--- /dev/null
+++ b/tests/ui/asm/generic_const_simd_vec_len.stderr
@@ -0,0 +1,14 @@
+error: cannot evaluate SIMD vector length `C`
+  --> $DIR/generic_const_simd_vec_len.rs:10:32
+   |
+LL | pub struct Foo<const C: usize>([u8; C]);
+   |                                ^^^^^^^
+   |
+note: SIMD vector length needs to be known statically for use in `asm!`
+  --> $DIR/generic_const_simd_vec_len.rs:16:27
+   |
+LL |         src = in(xmm_reg) a,
+   |                           ^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr
index 61e5078d6d9..e36ec125d13 100644
--- a/tests/ui/asm/inline-syntax.arm.stderr
+++ b/tests/ui/asm/inline-syntax.arm.stderr
@@ -15,10 +15,10 @@ LL | .intel_syntax noprefix
    | ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:29:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
-   |               ^
+   |               ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:2
@@ -27,10 +27,10 @@ LL |     .intel_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:32:15
+  --> $DIR/inline-syntax.rs:39:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
-   |               ^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:2
@@ -39,10 +39,10 @@ LL |     .intel_syntax aaa noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:43:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
-   |               ^
+   |               ^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:2
@@ -51,10 +51,10 @@ LL |     .att_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:38:15
+  --> $DIR/inline-syntax.rs:47:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
-   |               ^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:2
@@ -63,10 +63,10 @@ LL |     .att_syntax bbb noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:41:15
+  --> $DIR/inline-syntax.rs:51:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
-   |               ^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:2
@@ -75,10 +75,10 @@ LL |     .intel_syntax noprefix; nop
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:47:13
+  --> $DIR/inline-syntax.rs:58:13
    |
 LL |             .intel_syntax noprefix
-   |             ^
+   |             ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:2:13
diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr
new file mode 100644
index 00000000000..ada3f4891d3
--- /dev/null
+++ b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr
@@ -0,0 +1,90 @@
+error: unknown directive
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:1
+   |
+LL | .intel_syntax noprefix
+   | ^
+
+error: unknown directive
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:1
+   |
+LL | .intel_syntax noprefix
+   | ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:35:15
+   |
+LL |         asm!(".intel_syntax noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:39:15
+   |
+LL |         asm!(".intel_syntax aaa noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax aaa noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:43:15
+   |
+LL |         asm!(".att_syntax noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:47:15
+   |
+LL |         asm!(".att_syntax bbb noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax bbb noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:51:15
+   |
+LL |         asm!(".intel_syntax noprefix; nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix; nop
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:58:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs
index b8486527e6f..fda79b2afa3 100644
--- a/tests/ui/asm/inline-syntax.rs
+++ b/tests/ui/asm/inline-syntax.rs
@@ -1,10 +1,16 @@
-//@ revisions: x86_64 arm
+//@ revisions: x86_64 arm_llvm_18 arm
 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
 //@[x86_64] check-pass
 //@[x86_64] needs-llvm-components: x86
+//@[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@[arm_llvm_18] build-fail
+//@[arm_llvm_18] needs-llvm-components: arm
+//@[arm_llvm_18] ignore-llvm-version: 19 - 99
+// LLVM 19+ has full support for 64-bit cookies.
 //@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
 //@[arm] build-fail
 //@[arm] needs-llvm-components: arm
+//@[arm] min-llvm-version: 19
 //@ needs-asm-support
 
 #![feature(no_core, lang_items, rustc_attrs)]
@@ -29,18 +35,23 @@ pub fn main() {
         asm!(".intel_syntax noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".intel_syntax aaa noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".att_syntax noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.att_syntax`
         //[arm]~^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".att_syntax bbb noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.att_syntax`
         //[arm]~^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".intel_syntax noprefix; nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^ ERROR unknown directive
 
         asm!(
             r"
@@ -49,9 +60,10 @@ pub fn main() {
         );
         //[x86_64]~^^^ WARN avoid using `.intel_syntax`
         //[arm]~^^^^ ERROR unknown directive
+        //[arm_llvm_18]~^^^^^ ERROR unknown directive
     }
 }
 
 global_asm!(".intel_syntax noprefix", "nop");
 //[x86_64]~^ WARN avoid using `.intel_syntax`
-// Assembler errors don't have line numbers, so no error on ARM
+// Global assembly errors don't have line numbers, so no error on ARM.
diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr
index 59c95194322..66dc37f3089 100644
--- a/tests/ui/asm/inline-syntax.x86_64.stderr
+++ b/tests/ui/asm/inline-syntax.x86_64.stderr
@@ -1,5 +1,5 @@
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:55:14
+  --> $DIR/inline-syntax.rs:67:14
    |
 LL | global_asm!(".intel_syntax noprefix", "nop");
    |              ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop");
    = note: `#[warn(bad_asm_style)]` on by default
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:29:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:32:15
+  --> $DIR/inline-syntax.rs:39:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:43:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:38:15
+  --> $DIR/inline-syntax.rs:47:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:41:15
+  --> $DIR/inline-syntax.rs:51:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:47:13
+  --> $DIR/inline-syntax.rs:58:13
    |
 LL |             .intel_syntax noprefix
    |             ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/naked-functions-instruction-set.rs b/tests/ui/asm/naked-functions-instruction-set.rs
index 37c7b52c191..3a6e7a46ce5 100644
--- a/tests/ui/asm/naked-functions-instruction-set.rs
+++ b/tests/ui/asm/naked-functions-instruction-set.rs
@@ -24,7 +24,7 @@ unsafe extern "C" fn test_thumb() {
 
 #[no_mangle]
 #[naked]
-#[instruction_set(arm::t32)]
+#[instruction_set(arm::a32)]
 unsafe extern "C" fn test_arm() {
     naked_asm!("bx lr");
 }
diff --git a/tests/ui/asm/named_const_simd_vec_len.rs b/tests/ui/asm/named_const_simd_vec_len.rs
new file mode 100644
index 00000000000..7df4d922d5c
--- /dev/null
+++ b/tests/ui/asm/named_const_simd_vec_len.rs
@@ -0,0 +1,22 @@
+//! This is a regression test to ensure that we evaluate
+//! SIMD vector length constants instead of assuming they are literals.
+
+//@ only-x86_64
+//@ check-pass
+
+#![feature(repr_simd)]
+
+const C: usize = 16;
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct Foo([u8; C]);
+
+pub unsafe fn foo(a: Foo) {
+    std::arch::asm!(
+        "movaps {src}, {src}",
+        src = in(xmm_reg) a,
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr
index e7a86805b26..ac1373f0e2d 100644
--- a/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr
@@ -1,8 +1,8 @@
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:46:11
+  --> $DIR/riscv32e-registers.rs:58:11
    |
 LL |     asm!("li x16, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -11,10 +11,10 @@ LL |     li x16, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:49:11
+  --> $DIR/riscv32e-registers.rs:61:11
    |
 LL |     asm!("li x17, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -23,10 +23,10 @@ LL |     li x17, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:52:11
+  --> $DIR/riscv32e-registers.rs:64:11
    |
 LL |     asm!("li x18, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -35,10 +35,10 @@ LL |     li x18, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:55:11
+  --> $DIR/riscv32e-registers.rs:67:11
    |
 LL |     asm!("li x19, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -47,10 +47,10 @@ LL |     li x19, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:58:11
+  --> $DIR/riscv32e-registers.rs:70:11
    |
 LL |     asm!("li x20, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -59,10 +59,10 @@ LL |     li x20, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:61:11
+  --> $DIR/riscv32e-registers.rs:73:11
    |
 LL |     asm!("li x21, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -71,10 +71,10 @@ LL |     li x21, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:64:11
+  --> $DIR/riscv32e-registers.rs:76:11
    |
 LL |     asm!("li x22, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -83,10 +83,10 @@ LL |     li x22, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:67:11
+  --> $DIR/riscv32e-registers.rs:79:11
    |
 LL |     asm!("li x23, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -95,10 +95,10 @@ LL |     li x23, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:70:11
+  --> $DIR/riscv32e-registers.rs:82:11
    |
 LL |     asm!("li x24, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -107,10 +107,10 @@ LL |     li x24, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:73:11
+  --> $DIR/riscv32e-registers.rs:85:11
    |
 LL |     asm!("li x25, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -119,10 +119,10 @@ LL |     li x25, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:76:11
+  --> $DIR/riscv32e-registers.rs:88:11
    |
 LL |     asm!("li x26, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -131,10 +131,10 @@ LL |     li x26, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:79:11
+  --> $DIR/riscv32e-registers.rs:91:11
    |
 LL |     asm!("li x27, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -143,10 +143,10 @@ LL |     li x27, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:82:11
+  --> $DIR/riscv32e-registers.rs:94:11
    |
 LL |     asm!("li x28, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -155,10 +155,10 @@ LL |     li x28, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:85:11
+  --> $DIR/riscv32e-registers.rs:97:11
    |
 LL |     asm!("li x29, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -167,10 +167,10 @@ LL |     li x29, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:88:11
+  --> $DIR/riscv32e-registers.rs:100:11
    |
 LL |     asm!("li x30, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -179,10 +179,10 @@ LL |     li x30, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:91:11
+  --> $DIR/riscv32e-registers.rs:103:11
    |
 LL |     asm!("li x31, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr
new file mode 100644
index 00000000000..f140f54adc5
--- /dev/null
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32e_llvm_18.stderr
@@ -0,0 +1,194 @@
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:58:11
+   |
+LL |     asm!("li x16, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x16, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:61:11
+   |
+LL |     asm!("li x17, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x17, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:64:11
+   |
+LL |     asm!("li x18, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x18, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:67:11
+   |
+LL |     asm!("li x19, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x19, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:70:11
+   |
+LL |     asm!("li x20, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x20, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:73:11
+   |
+LL |     asm!("li x21, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x21, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:76:11
+   |
+LL |     asm!("li x22, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x22, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:79:11
+   |
+LL |     asm!("li x23, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x23, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:82:11
+   |
+LL |     asm!("li x24, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x24, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:85:11
+   |
+LL |     asm!("li x25, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x25, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:88:11
+   |
+LL |     asm!("li x26, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x26, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:91:11
+   |
+LL |     asm!("li x27, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x27, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:94:11
+   |
+LL |     asm!("li x28, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x28, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:97:11
+   |
+LL |     asm!("li x29, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x29, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:100:11
+   |
+LL |     asm!("li x30, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x30, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:103:11
+   |
+LL |     asm!("li x31, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x31, 0
+   |        ^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr
index e7a86805b26..ac1373f0e2d 100644
--- a/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr
@@ -1,8 +1,8 @@
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:46:11
+  --> $DIR/riscv32e-registers.rs:58:11
    |
 LL |     asm!("li x16, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -11,10 +11,10 @@ LL |     li x16, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:49:11
+  --> $DIR/riscv32e-registers.rs:61:11
    |
 LL |     asm!("li x17, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -23,10 +23,10 @@ LL |     li x17, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:52:11
+  --> $DIR/riscv32e-registers.rs:64:11
    |
 LL |     asm!("li x18, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -35,10 +35,10 @@ LL |     li x18, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:55:11
+  --> $DIR/riscv32e-registers.rs:67:11
    |
 LL |     asm!("li x19, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -47,10 +47,10 @@ LL |     li x19, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:58:11
+  --> $DIR/riscv32e-registers.rs:70:11
    |
 LL |     asm!("li x20, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -59,10 +59,10 @@ LL |     li x20, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:61:11
+  --> $DIR/riscv32e-registers.rs:73:11
    |
 LL |     asm!("li x21, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -71,10 +71,10 @@ LL |     li x21, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:64:11
+  --> $DIR/riscv32e-registers.rs:76:11
    |
 LL |     asm!("li x22, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -83,10 +83,10 @@ LL |     li x22, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:67:11
+  --> $DIR/riscv32e-registers.rs:79:11
    |
 LL |     asm!("li x23, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -95,10 +95,10 @@ LL |     li x23, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:70:11
+  --> $DIR/riscv32e-registers.rs:82:11
    |
 LL |     asm!("li x24, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -107,10 +107,10 @@ LL |     li x24, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:73:11
+  --> $DIR/riscv32e-registers.rs:85:11
    |
 LL |     asm!("li x25, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -119,10 +119,10 @@ LL |     li x25, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:76:11
+  --> $DIR/riscv32e-registers.rs:88:11
    |
 LL |     asm!("li x26, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -131,10 +131,10 @@ LL |     li x26, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:79:11
+  --> $DIR/riscv32e-registers.rs:91:11
    |
 LL |     asm!("li x27, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -143,10 +143,10 @@ LL |     li x27, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:82:11
+  --> $DIR/riscv32e-registers.rs:94:11
    |
 LL |     asm!("li x28, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -155,10 +155,10 @@ LL |     li x28, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:85:11
+  --> $DIR/riscv32e-registers.rs:97:11
    |
 LL |     asm!("li x29, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -167,10 +167,10 @@ LL |     li x29, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:88:11
+  --> $DIR/riscv32e-registers.rs:100:11
    |
 LL |     asm!("li x30, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -179,10 +179,10 @@ LL |     li x30, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:91:11
+  --> $DIR/riscv32e-registers.rs:103:11
    |
 LL |     asm!("li x31, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr
new file mode 100644
index 00000000000..f140f54adc5
--- /dev/null
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32em_llvm_18.stderr
@@ -0,0 +1,194 @@
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:58:11
+   |
+LL |     asm!("li x16, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x16, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:61:11
+   |
+LL |     asm!("li x17, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x17, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:64:11
+   |
+LL |     asm!("li x18, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x18, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:67:11
+   |
+LL |     asm!("li x19, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x19, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:70:11
+   |
+LL |     asm!("li x20, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x20, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:73:11
+   |
+LL |     asm!("li x21, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x21, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:76:11
+   |
+LL |     asm!("li x22, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x22, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:79:11
+   |
+LL |     asm!("li x23, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x23, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:82:11
+   |
+LL |     asm!("li x24, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x24, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:85:11
+   |
+LL |     asm!("li x25, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x25, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:88:11
+   |
+LL |     asm!("li x26, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x26, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:91:11
+   |
+LL |     asm!("li x27, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x27, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:94:11
+   |
+LL |     asm!("li x28, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x28, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:97:11
+   |
+LL |     asm!("li x29, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x29, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:100:11
+   |
+LL |     asm!("li x30, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x30, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:103:11
+   |
+LL |     asm!("li x31, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x31, 0
+   |        ^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr
index e7a86805b26..ac1373f0e2d 100644
--- a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr
@@ -1,8 +1,8 @@
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:46:11
+  --> $DIR/riscv32e-registers.rs:58:11
    |
 LL |     asm!("li x16, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -11,10 +11,10 @@ LL |     li x16, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:49:11
+  --> $DIR/riscv32e-registers.rs:61:11
    |
 LL |     asm!("li x17, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -23,10 +23,10 @@ LL |     li x17, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:52:11
+  --> $DIR/riscv32e-registers.rs:64:11
    |
 LL |     asm!("li x18, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -35,10 +35,10 @@ LL |     li x18, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:55:11
+  --> $DIR/riscv32e-registers.rs:67:11
    |
 LL |     asm!("li x19, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -47,10 +47,10 @@ LL |     li x19, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:58:11
+  --> $DIR/riscv32e-registers.rs:70:11
    |
 LL |     asm!("li x20, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -59,10 +59,10 @@ LL |     li x20, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:61:11
+  --> $DIR/riscv32e-registers.rs:73:11
    |
 LL |     asm!("li x21, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -71,10 +71,10 @@ LL |     li x21, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:64:11
+  --> $DIR/riscv32e-registers.rs:76:11
    |
 LL |     asm!("li x22, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -83,10 +83,10 @@ LL |     li x22, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:67:11
+  --> $DIR/riscv32e-registers.rs:79:11
    |
 LL |     asm!("li x23, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -95,10 +95,10 @@ LL |     li x23, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:70:11
+  --> $DIR/riscv32e-registers.rs:82:11
    |
 LL |     asm!("li x24, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -107,10 +107,10 @@ LL |     li x24, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:73:11
+  --> $DIR/riscv32e-registers.rs:85:11
    |
 LL |     asm!("li x25, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -119,10 +119,10 @@ LL |     li x25, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:76:11
+  --> $DIR/riscv32e-registers.rs:88:11
    |
 LL |     asm!("li x26, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -131,10 +131,10 @@ LL |     li x26, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:79:11
+  --> $DIR/riscv32e-registers.rs:91:11
    |
 LL |     asm!("li x27, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -143,10 +143,10 @@ LL |     li x27, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:82:11
+  --> $DIR/riscv32e-registers.rs:94:11
    |
 LL |     asm!("li x28, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -155,10 +155,10 @@ LL |     li x28, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:85:11
+  --> $DIR/riscv32e-registers.rs:97:11
    |
 LL |     asm!("li x29, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -167,10 +167,10 @@ LL |     li x29, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:88:11
+  --> $DIR/riscv32e-registers.rs:100:11
    |
 LL |     asm!("li x30, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
@@ -179,10 +179,10 @@ LL |     li x30, 0
    |        ^
 
 error: invalid operand for instruction
-  --> $DIR/riscv32e-registers.rs:91:11
+  --> $DIR/riscv32e-registers.rs:103:11
    |
 LL |     asm!("li x31, 0");
-   |           ^
+   |           ^^^^^^^^^
    |
 note: instantiated into assembly here
   --> <inline asm>:1:5
diff --git a/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr
new file mode 100644
index 00000000000..f140f54adc5
--- /dev/null
+++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc_llvm_18.stderr
@@ -0,0 +1,194 @@
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:58:11
+   |
+LL |     asm!("li x16, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x16, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:61:11
+   |
+LL |     asm!("li x17, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x17, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:64:11
+   |
+LL |     asm!("li x18, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x18, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:67:11
+   |
+LL |     asm!("li x19, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x19, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:70:11
+   |
+LL |     asm!("li x20, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x20, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:73:11
+   |
+LL |     asm!("li x21, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x21, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:76:11
+   |
+LL |     asm!("li x22, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x22, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:79:11
+   |
+LL |     asm!("li x23, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x23, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:82:11
+   |
+LL |     asm!("li x24, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x24, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:85:11
+   |
+LL |     asm!("li x25, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x25, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:88:11
+   |
+LL |     asm!("li x26, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x26, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:91:11
+   |
+LL |     asm!("li x27, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x27, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:94:11
+   |
+LL |     asm!("li x28, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x28, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:97:11
+   |
+LL |     asm!("li x29, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x29, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:100:11
+   |
+LL |     asm!("li x30, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x30, 0
+   |        ^
+
+error: invalid operand for instruction
+  --> $DIR/riscv32e-registers.rs:103:11
+   |
+LL |     asm!("li x31, 0");
+   |           ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:5
+   |
+LL |     li x31, 0
+   |        ^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/asm/riscv/riscv32e-registers.rs b/tests/ui/asm/riscv/riscv32e-registers.rs
index 57b1e169a04..c3fe19991b0 100644
--- a/tests/ui/asm/riscv/riscv32e-registers.rs
+++ b/tests/ui/asm/riscv/riscv32e-registers.rs
@@ -1,15 +1,27 @@
 // Test that loads into registers x16..=x31 are never generated for riscv32{e,em,emc} targets
 //
 //@ build-fail
-//@ revisions: riscv32e riscv32em riscv32emc
+//@ revisions: riscv32e riscv32em riscv32emc riscv32e_llvm_18 riscv32em_llvm_18 riscv32emc_llvm_18
 //
 //@ compile-flags: --crate-type=rlib
 //@ [riscv32e] needs-llvm-components: riscv
 //@ [riscv32e] compile-flags: --target=riscv32e-unknown-none-elf
+//@ [riscv32e] min-llvm-version: 19
 //@ [riscv32em] needs-llvm-components: riscv
 //@ [riscv32em] compile-flags: --target=riscv32em-unknown-none-elf
+//@ [riscv32em] min-llvm-version: 19
 //@ [riscv32emc] needs-llvm-components: riscv
 //@ [riscv32emc] compile-flags: --target=riscv32emc-unknown-none-elf
+//@ [riscv32emc] min-llvm-version: 19
+//@ [riscv32e_llvm_18] needs-llvm-components: riscv
+//@ [riscv32e_llvm_18] compile-flags: --target=riscv32e-unknown-none-elf
+//@ [riscv32e_llvm_18] ignore-llvm-version: 19 - 99
+//@ [riscv32em_llvm_18] needs-llvm-components: riscv
+//@ [riscv32em_llvm_18] compile-flags: --target=riscv32em-unknown-none-elf
+//@ [riscv32em_llvm_18] ignore-llvm-version: 19 - 99
+//@ [riscv32emc_llvm_18] needs-llvm-components: riscv
+//@ [riscv32emc_llvm_18] compile-flags: --target=riscv32emc-unknown-none-elf
+//@ [riscv32emc_llvm_18] ignore-llvm-version: 19 - 99
 
 // Unlike bad-reg.rs, this tests if the assembler can reject invalid registers
 // usage in assembly code.
diff --git a/tests/ui/asm/x86_64/srcloc.new.stderr b/tests/ui/asm/x86_64/srcloc.new.stderr
new file mode 100644
index 00000000000..7211f1ab69d
--- /dev/null
+++ b/tests/ui/asm/x86_64/srcloc.new.stderr
@@ -0,0 +1,332 @@
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:14:15
+   |
+LL |         asm!("invalid_instruction");
+   |               ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:18:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:23:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:29:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:36:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:41:14
+   |
+LL |         asm!(concat!("invalid", "_", "instruction"));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction
+   |     ^^^^^^^^^^^^^^^^^^^
+
+warning: scale factor without index register is ignored
+  --> $DIR/srcloc.rs:44:15
+   |
+LL |         asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+   |               ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:23
+   |
+LL |     movaps %xmm3, (%esi, 2)
+   |                          ^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:48:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:54:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:61:14
+   |
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:68:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:75:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+  --> $DIR/srcloc.rs:82:14
+   |
+LL |             "invalid_instruction1",
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction1
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+  --> $DIR/srcloc.rs:83:14
+   |
+LL |             "invalid_instruction2",
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction2
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+  --> $DIR/srcloc.rs:89:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction1
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+  --> $DIR/srcloc.rs:89:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction2
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+  --> $DIR/srcloc.rs:98:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction1
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+  --> $DIR/srcloc.rs:98:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction2
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+  --> $DIR/srcloc.rs:102:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:1
+   |
+LL | invalid_instruction3
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+  --> $DIR/srcloc.rs:102:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:5:1
+   |
+LL | invalid_instruction4
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+  --> $DIR/srcloc.rs:113:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction1
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+  --> $DIR/srcloc.rs:113:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction1", "\n",
+LL | |                 "invalid", "_", "instruction2", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction2
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+  --> $DIR/srcloc.rs:117:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:5:1
+   |
+LL | invalid_instruction3
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+  --> $DIR/srcloc.rs:117:13
+   |
+LL | /             concat!(
+LL | |                 "invalid", "_", "instruction3", "\n",
+LL | |                 "invalid", "_", "instruction4", "\n",
+LL | |             ),
+   | |_____________^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:6:1
+   |
+LL | invalid_instruction4
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:130:14
+   |
+LL |             "invalid_instruction"
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:5:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors; 1 warning emitted
+
diff --git a/tests/ui/asm/x86_64/srcloc.stderr b/tests/ui/asm/x86_64/srcloc.old.stderr
index 8899c1b916b..edb9ee46812 100644
--- a/tests/ui/asm/x86_64/srcloc.stderr
+++ b/tests/ui/asm/x86_64/srcloc.old.stderr
@@ -1,5 +1,5 @@
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:11:15
+  --> $DIR/srcloc.rs:14:15
    |
 LL |         asm!("invalid_instruction");
    |               ^
@@ -11,7 +11,7 @@ LL |     invalid_instruction
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:15:13
+  --> $DIR/srcloc.rs:18:13
    |
 LL |             invalid_instruction
    |             ^
@@ -23,7 +23,7 @@ LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:20:13
+  --> $DIR/srcloc.rs:23:13
    |
 LL |             invalid_instruction
    |             ^
@@ -35,7 +35,7 @@ LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:26:13
+  --> $DIR/srcloc.rs:29:13
    |
 LL |             invalid_instruction
    |             ^
@@ -47,7 +47,7 @@ LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:33:13
+  --> $DIR/srcloc.rs:36:13
    |
 LL |             invalid_instruction
    |             ^
@@ -59,7 +59,7 @@ LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:38:14
+  --> $DIR/srcloc.rs:41:14
    |
 LL |         asm!(concat!("invalid", "_", "instruction"));
    |              ^
@@ -71,7 +71,7 @@ LL |     invalid_instruction
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: scale factor without index register is ignored
-  --> $DIR/srcloc.rs:41:15
+  --> $DIR/srcloc.rs:44:15
    |
 LL |         asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
    |               ^
@@ -83,7 +83,7 @@ LL |     movaps %xmm3, (%esi, 2)
    |                          ^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:45:14
+  --> $DIR/srcloc.rs:48:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -95,7 +95,7 @@ LL |     invalid_instruction
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:51:14
+  --> $DIR/srcloc.rs:54:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -107,7 +107,7 @@ LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:58:14
+  --> $DIR/srcloc.rs:61:14
    |
 LL |             "invalid_instruction",
    |              ^
@@ -119,7 +119,7 @@ LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:65:13
+  --> $DIR/srcloc.rs:68:13
    |
 LL |             concat!("invalid", "_", "instruction"),
    |             ^
@@ -131,7 +131,7 @@ LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:72:13
+  --> $DIR/srcloc.rs:75:13
    |
 LL |             concat!("invalid", "_", "instruction"),
    |             ^
@@ -143,7 +143,7 @@ LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:79:14
+  --> $DIR/srcloc.rs:82:14
    |
 LL |             "invalid_instruction1",
    |              ^
@@ -155,7 +155,7 @@ LL |     invalid_instruction1
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:80:14
+  --> $DIR/srcloc.rs:83:14
    |
 LL |             "invalid_instruction2",
    |              ^
@@ -167,7 +167,7 @@ LL | invalid_instruction2
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:86:13
+  --> $DIR/srcloc.rs:89:13
    |
 LL |             concat!(
    |             ^
@@ -179,7 +179,7 @@ LL |     invalid_instruction1
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:86:13
+  --> $DIR/srcloc.rs:89:13
    |
 LL |             concat!(
    |             ^
@@ -191,7 +191,7 @@ LL | invalid_instruction2
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:95:13
+  --> $DIR/srcloc.rs:98:13
    |
 LL |             concat!(
    |             ^
@@ -203,7 +203,7 @@ LL |     invalid_instruction1
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:95:13
+  --> $DIR/srcloc.rs:98:13
    |
 LL |             concat!(
    |             ^
@@ -215,7 +215,7 @@ LL | invalid_instruction2
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction3'
-  --> $DIR/srcloc.rs:99:13
+  --> $DIR/srcloc.rs:102:13
    |
 LL |             concat!(
    |             ^
@@ -227,7 +227,7 @@ LL | invalid_instruction3
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction4'
-  --> $DIR/srcloc.rs:99:13
+  --> $DIR/srcloc.rs:102:13
    |
 LL |             concat!(
    |             ^
@@ -239,7 +239,7 @@ LL | invalid_instruction4
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:110:13
+  --> $DIR/srcloc.rs:113:13
    |
 LL |             concat!(
    |             ^
@@ -251,7 +251,7 @@ LL |     invalid_instruction1
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:110:13
+  --> $DIR/srcloc.rs:113:13
    |
 LL |             concat!(
    |             ^
@@ -263,7 +263,7 @@ LL | invalid_instruction2
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction3'
-  --> $DIR/srcloc.rs:114:13
+  --> $DIR/srcloc.rs:117:13
    |
 LL |             concat!(
    |             ^
@@ -275,7 +275,7 @@ LL | invalid_instruction3
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction4'
-  --> $DIR/srcloc.rs:114:13
+  --> $DIR/srcloc.rs:117:13
    |
 LL |             concat!(
    |             ^
@@ -287,7 +287,7 @@ LL | invalid_instruction4
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:127:14
+  --> $DIR/srcloc.rs:130:14
    |
 LL |             "invalid_instruction"
    |              ^
diff --git a/tests/ui/asm/x86_64/srcloc.rs b/tests/ui/asm/x86_64/srcloc.rs
index 2938bafe5e7..40fc66cbc92 100644
--- a/tests/ui/asm/x86_64/srcloc.rs
+++ b/tests/ui/asm/x86_64/srcloc.rs
@@ -1,6 +1,9 @@
+//@ revisions: old new
 //@ only-x86_64
 //@ build-fail
 //@ compile-flags: -Ccodegen-units=1
+//@[old] ignore-llvm-version: 19 - 99
+//@[new] min-llvm-version: 19
 
 use std::arch::asm;
 
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
index ffb97ca04ac..4489f344e6f 100644
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
@@ -1,6 +1,5 @@
 //@ edition:2018
 
-#![feature(async_closure)]
 fn foo() -> Box<dyn std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new((async || x)())
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
index 4b1ce300b56..967b3bf5a77 100644
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `x`
-  --> $DIR/async-borrowck-escaping-closure-error.rs:6:5
+  --> $DIR/async-borrowck-escaping-closure-error.rs:5:5
    |
 LL |     Box::new((async || x)())
    |     ^^^^^^^^^------------^^^
diff --git a/tests/ui/async-await/async-closure-matches-expr.rs b/tests/ui/async-await/async-closure-matches-expr.rs
index 75ce14a4947..3f1c70e691c 100644
--- a/tests/ui/async-await/async-closure-matches-expr.rs
+++ b/tests/ui/async-await/async-closure-matches-expr.rs
@@ -1,8 +1,6 @@
 //@ build-pass
 //@ edition:2018
 
-#![feature(async_closure)]
-
 macro_rules! match_expr {
     ($x:expr) => {}
 }
diff --git a/tests/ui/async-await/async-closure.rs b/tests/ui/async-await/async-closure.rs
index 77c00bbdc9f..3dd88fbf739 100644
--- a/tests/ui/async-await/async-closure.rs
+++ b/tests/ui/async-await/async-closure.rs
@@ -6,8 +6,6 @@
 //@ edition:2018
 //@ aux-build:arc_wake.rs
 
-#![feature(async_closure)]
-
 extern crate arc_wake;
 
 use std::pin::Pin;
diff --git a/tests/ui/async-await/async-closures/ambiguous-arg.rs b/tests/ui/async-await/async-closures/ambiguous-arg.rs
index d76a1cf953e..e8e6ff6d97c 100644
--- a/tests/ui/async-await/async-closures/ambiguous-arg.rs
+++ b/tests/ui/async-await/async-closures/ambiguous-arg.rs
@@ -3,8 +3,6 @@
 // Regression test for #123901. We previously ICE'd as we silently
 // swallowed an in the `ExprUseVisitor`.
 
-#![feature(async_closure)]
-
 pub fn test(test: &u64, temp: &u64) {
     async |check, a, b| {
         //~^ ERROR type annotations needed
diff --git a/tests/ui/async-await/async-closures/ambiguous-arg.stderr b/tests/ui/async-await/async-closures/ambiguous-arg.stderr
index 01f72e94ecc..adb71d676dc 100644
--- a/tests/ui/async-await/async-closures/ambiguous-arg.stderr
+++ b/tests/ui/async-await/async-closures/ambiguous-arg.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/ambiguous-arg.rs:9:25
+  --> $DIR/ambiguous-arg.rs:7:25
    |
 LL |       async |check, a, b| {
    |  _________________________^
diff --git a/tests/ui/async-await/async-closures/arg-mismatch.rs b/tests/ui/async-await/async-closures/arg-mismatch.rs
index c8dddee6275..f69c8122d1d 100644
--- a/tests/ui/async-await/async-closures/arg-mismatch.rs
+++ b/tests/ui/async-await/async-closures/arg-mismatch.rs
@@ -1,8 +1,6 @@
 //@ aux-build:block-on.rs
 //@ edition:2021
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/arg-mismatch.stderr b/tests/ui/async-await/async-closures/arg-mismatch.stderr
index 70853ae2815..5c8e6650293 100644
--- a/tests/ui/async-await/async-closures/arg-mismatch.stderr
+++ b/tests/ui/async-await/async-closures/arg-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/arg-mismatch.rs:12:11
+  --> $DIR/arg-mismatch.rs:10:11
    |
 LL |         c(2usize).await;
    |         - ^^^^^^ expected `i32`, found `usize`
@@ -7,7 +7,7 @@ LL |         c(2usize).await;
    |         arguments to this function are incorrect
    |
 note: closure parameter defined here
-  --> $DIR/arg-mismatch.rs:10:24
+  --> $DIR/arg-mismatch.rs:8:24
    |
 LL |         let c = async |x| {};
    |                        ^
diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
index 8309cfbd58f..e739230fd46 100644
--- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
+++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ run-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
index e7644e3dfe0..078348eb4e6 100644
--- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
+++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ run-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs
index 8b50c5571c1..4ec45ddf333 100644
--- a/tests/ui/async-await/async-closures/auxiliary/block-on.rs
+++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::pin::pin;
 use std::task::*;
diff --git a/tests/ui/async-await/async-closures/auxiliary/foreign.rs b/tests/ui/async-await/async-closures/auxiliary/foreign.rs
index 33548a1b30d..935b029a7c5 100644
--- a/tests/ui/async-await/async-closures/auxiliary/foreign.rs
+++ b/tests/ui/async-await/async-closures/auxiliary/foreign.rs
@@ -1,7 +1,5 @@
 //@ edition:2021
 
-#![feature(async_closure)]
-
 pub fn closure() -> impl AsyncFn() {
     async || { /* Don't really need to do anything here. */ }
 }
diff --git a/tests/ui/async-await/async-closures/await-inference-guidance.rs b/tests/ui/async-await/async-closures/await-inference-guidance.rs
index 1ddc1f8d1c5..f4f91e2e073 100644
--- a/tests/ui/async-await/async-closures/await-inference-guidance.rs
+++ b/tests/ui/async-await/async-closures/await-inference-guidance.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ run-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
index a72ff8e5dce..0560d3b0867 100644
--- a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
+++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 // Make sure that we don't call `coroutine_by_move_body_def_id` query
diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
index 5ec1c5ee50e..10f7636720c 100644
--- a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
+++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ run-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 pub trait Trait {
diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs
index db1f5d271c6..3b13506cf00 100644
--- a/tests/ui/async-await/async-closures/brand.rs
+++ b/tests/ui/async-await/async-closures/brand.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 use std::future::Future;
diff --git a/tests/ui/async-await/async-closures/call-once-deduction.rs b/tests/ui/async-await/async-closures/call-once-deduction.rs
index 41d92bc3d78..ed2830a5e82 100644
--- a/tests/ui/async-await/async-closures/call-once-deduction.rs
+++ b/tests/ui/async-await/async-closures/call-once-deduction.rs
@@ -1,7 +1,7 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure, async_fn_traits, unboxed_closures)]
+#![feature(async_fn_traits, unboxed_closures)]
 
 fn bar<F, O>(_: F)
 where
diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs
index 2bd4b685997..296fca6cb86 100644
--- a/tests/ui/async-await/async-closures/captures.rs
+++ b/tests/ui/async-await/async-closures/captures.rs
@@ -5,8 +5,6 @@
 
 // Same as miri's `tests/pass/async-closure-captures.rs`, keep in sync
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/clone-closure.rs b/tests/ui/async-await/async-closures/clone-closure.rs
index a9e1d6bccc7..b637ab45b9a 100644
--- a/tests/ui/async-await/async-closures/clone-closure.rs
+++ b/tests/ui/async-await/async-closures/clone-closure.rs
@@ -3,8 +3,6 @@
 //@ run-pass
 //@ check-run-results
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 async fn for_each(f: impl AsyncFnOnce(&str) + Clone) {
diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
index 4cbbefb0f52..069744a3282 100644
--- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
+++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
@@ -1,7 +1,5 @@
 //@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3
 
-#![feature(async_closure)]
-
 fn main() {}
 
 fn needs_fn_mut<T>(mut x: impl FnMut() -> T) {
diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
index bab26c19482..52697bac509 100644
--- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
+++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `x` which is behind a mutable reference
-  --> $DIR/closure-shim-borrowck-error.rs:12:18
+  --> $DIR/closure-shim-borrowck-error.rs:10:18
    |
 LL |     needs_fn_mut(async || {
    |                  ^^^^^^^^ `x` is moved here
@@ -11,7 +11,7 @@ LL |         x.hello();
    |         move occurs because `x` has type `Ty`, which does not implement the `Copy` trait
    |
 note: if `Ty` implemented `Clone`, you could clone the value
-  --> $DIR/closure-shim-borrowck-error.rs:18:1
+  --> $DIR/closure-shim-borrowck-error.rs:16:1
    |
 LL |         x.hello();
    |         - you could clone this value
diff --git a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
index 1acbf0311b3..993f8378439 100644
--- a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
+++ b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
@@ -4,8 +4,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(async_closure)]
-
 fn constrain<T: AsyncFnOnce()>(t: T) -> T {
     t
 }
diff --git a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
index f71cc1ef537..a1d6ce259e2 100644
--- a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
+++ b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
@@ -3,8 +3,6 @@
 //@ build-pass
 //@ compile-flags: -Cdebuginfo=2
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 async fn call_once(f: impl AsyncFnOnce()) {
diff --git a/tests/ui/async-await/async-closures/def-path.rs b/tests/ui/async-await/async-closures/def-path.rs
index 70450697816..838556966e8 100644
--- a/tests/ui/async-await/async-closures/def-path.rs
+++ b/tests/ui/async-await/async-closures/def-path.rs
@@ -1,8 +1,6 @@
 //@ compile-flags: -Zverbose-internals
 //@ edition:2021
 
-#![feature(async_closure)]
-
 fn main() {
     let x = async || {};
     //~^ NOTE the expected `async` closure body
diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr
index 0a1e30c1253..cf25b2d2d23 100644
--- a/tests/ui/async-await/async-closures/def-path.stderr
+++ b/tests/ui/async-await/async-closures/def-path.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/def-path.rs:9:9
+  --> $DIR/def-path.rs:7:9
    |
 LL |     let x = async || {};
    |                      -- the expected `async` closure body
diff --git a/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs b/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs
index 2313db506be..d40c9548a3a 100644
--- a/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs
+++ b/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs
@@ -2,8 +2,6 @@
 //@ edition: 2021
 // issue: rust-lang/rust#123697
 
-#![feature(async_closure)]
-
 struct S { t: i32 }
 
 fn test(s: &S, t: &i32) {
diff --git a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
index 8fc9924a12f..f90d10ebe85 100644
--- a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
+++ b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 struct DropMe;
 
 trait Impossible {}
diff --git a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr
index b4dc3e268bd..c93c1732a22 100644
--- a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr
+++ b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `(): Impossible` is not satisfied
-  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:19:23
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:17:23
    |
 LL |         trait_error::<()>();
    |                       ^^ the trait `Impossible` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:7:1
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:5:1
    |
 LL | trait Impossible {}
    | ^^^^^^^^^^^^^^^^
 note: required by a bound in `trait_error`
-  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:8:19
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:6:19
    |
 LL | fn trait_error<T: Impossible>() {}
    |                   ^^^^^^^^^^ required by this bound in `trait_error`
diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs
index 9c99550e3b7..24c182d2c2d 100644
--- a/tests/ui/async-await/async-closures/drop.rs
+++ b/tests/ui/async-await/async-closures/drop.rs
@@ -3,7 +3,6 @@
 //@ run-pass
 //@ check-run-results
 
-#![feature(async_closure)]
 #![allow(unused)]
 
 extern crate block_on;
diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
index eb554650b7c..82fc776fd2c 100644
--- a/tests/ui/async-await/async-closures/fn-exception-target-features.rs
+++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
@@ -1,7 +1,7 @@
 //@ edition: 2021
 //@ only-x86_64
 
-#![feature(async_closure, target_feature_11)]
+#![feature(target_feature_11)]
 // `target_feature_11` just to test safe functions w/ target features.
 
 use std::pin::Pin;
diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs
index 36cb955cd5c..8ff63983e79 100644
--- a/tests/ui/async-await/async-closures/fn-exception.rs
+++ b/tests/ui/async-await/async-closures/fn-exception.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 use std::pin::Pin;
 use std::future::Future;
 
diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr
index b3118664c15..aa74ed234df 100644
--- a/tests/ui/async-await/async-closures/fn-exception.stderr
+++ b/tests/ui/async-await/async-closures/fn-exception.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn()` is not satisfied
-  --> $DIR/fn-exception.rs:19:10
+  --> $DIR/fn-exception.rs:17:10
    |
 LL |     test(unsafety);
    |     ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
@@ -7,13 +7,13 @@ LL |     test(unsafety);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `test`
-  --> $DIR/fn-exception.rs:16:17
+  --> $DIR/fn-exception.rs:14:17
    |
 LL | fn test(f: impl AsyncFn()) {}
    |                 ^^^^^^^^^ required by this bound in `test`
 
 error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
-  --> $DIR/fn-exception.rs:20:10
+  --> $DIR/fn-exception.rs:18:10
    |
 LL |     test(abi);
    |     ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
@@ -21,7 +21,7 @@ LL |     test(abi);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `test`
-  --> $DIR/fn-exception.rs:16:17
+  --> $DIR/fn-exception.rs:14:17
    |
 LL | fn test(f: impl AsyncFn()) {}
    |                 ^^^^^^^^^ required by this bound in `test`
diff --git a/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs
index 7244a29673b..1347a4b259b 100644
--- a/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs
+++ b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn consume(_: String) {}
diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
index c20e3664d8b..c963d282c4e 100644
--- a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
+++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn force_fnonce<T: AsyncFnOnce()>(t: T) -> T { t }
diff --git a/tests/ui/async-await/async-closures/foreign.rs b/tests/ui/async-await/async-closures/foreign.rs
index a244eef4102..b0580a8f09d 100644
--- a/tests/ui/async-await/async-closures/foreign.rs
+++ b/tests/ui/async-await/async-closures/foreign.rs
@@ -3,8 +3,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 use std::future::Future;
 
 extern crate block_on;
diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.rs b/tests/ui/async-await/async-closures/higher-ranked-return.rs
index d6bea5dd103..328c733d42d 100644
--- a/tests/ui/async-await/async-closures/higher-ranked-return.rs
+++ b/tests/ui/async-await/async-closures/higher-ranked-return.rs
@@ -4,8 +4,6 @@
 //@ known-bug: unknown
 // Borrow checking doesn't like that higher-ranked output...
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.stderr b/tests/ui/async-await/async-closures/higher-ranked-return.stderr
index 268631f67cd..23ce3df6616 100644
--- a/tests/ui/async-await/async-closures/higher-ranked-return.stderr
+++ b/tests/ui/async-await/async-closures/higher-ranked-return.stderr
@@ -1,10 +1,10 @@
 error: lifetime may not live long enough
-  --> $DIR/higher-ranked-return.rs:13:46
+  --> $DIR/higher-ranked-return.rs:11:46
    |
 LL |           let x = async move |x: &str| -> &str {
    |  ________________________________-________----_^
    | |                                |        |
-   | |                                |        return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:13:46: 15:10}` contains a lifetime `'2`
+   | |                                |        return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:11:46: 13:10}` contains a lifetime `'2`
    | |                                let's call the lifetime of this reference `'1`
 LL | |             x
 LL | |         };
diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs
index 5b34bfce961..28f9df60130 100644
--- a/tests/ui/async-await/async-closures/higher-ranked.rs
+++ b/tests/ui/async-await/async-closures/higher-ranked.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs
index f49d1423c40..a2e31bb9870 100644
--- a/tests/ui/async-await/async-closures/implements-fnmut.rs
+++ b/tests/ui/async-await/async-closures/implements-fnmut.rs
@@ -7,8 +7,6 @@
 // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we
 // must borrow from the closure env.
 
-#![feature(async_closure)]
-
 fn main() {
     hello(&Ty);
 }
diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs
index b7d7102c287..3f1b9c26601 100644
--- a/tests/ui/async-await/async-closures/inline-body.rs
+++ b/tests/ui/async-await/async-closures/inline-body.rs
@@ -6,8 +6,6 @@
 // `mir_inliner_callees` for the synthetic by-move coroutine body since
 // its def-id wasn't previously being considered.
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::pin::pin;
 use std::task::*;
diff --git a/tests/ui/async-await/async-closures/is-fn.rs b/tests/ui/async-await/async-closures/is-fn.rs
index 89c3a96bbbe..45c2b6ae342 100644
--- a/tests/ui/async-await/async-closures/is-fn.rs
+++ b/tests/ui/async-await/async-closures/is-fn.rs
@@ -5,8 +5,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(async_closure)]
-
 use std::future::Future;
 
 extern crate block_on;
diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs
index f877513043d..4acaa5d9809 100644
--- a/tests/ui/async-await/async-closures/is-not-fn.rs
+++ b/tests/ui/async-await/async-closures/is-not-fn.rs
@@ -1,9 +1,7 @@
 //@ edition:2021
 
-#![feature(async_closure)]
-
 fn main() {
     fn needs_fn(x: impl FnOnce()) {}
     needs_fn(async || {});
-    //~^ ERROR expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()`
+    //~^ ERROR expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()`
 }
diff --git a/tests/ui/async-await/async-closures/is-not-fn.stderr b/tests/ui/async-await/async-closures/is-not-fn.stderr
index 130746ece67..bc1d5e6e9d1 100644
--- a/tests/ui/async-await/async-closures/is-not-fn.stderr
+++ b/tests/ui/async-await/async-closures/is-not-fn.stderr
@@ -1,5 +1,5 @@
-error[E0271]: expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}`
-  --> $DIR/is-not-fn.rs:7:14
+error[E0271]: expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}`
+  --> $DIR/is-not-fn.rs:5:14
    |
 LL |     needs_fn(async || {});
    |     -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
@@ -7,9 +7,9 @@ LL |     needs_fn(async || {});
    |     required by a bound introduced by this call
    |
    = note:         expected unit type `()`
-           found `async` closure body `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}`
+           found `async` closure body `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}`
 note: required by a bound in `needs_fn`
-  --> $DIR/is-not-fn.rs:6:25
+  --> $DIR/is-not-fn.rs:4:25
    |
 LL |     fn needs_fn(x: impl FnOnce()) {}
    |                         ^^^^^^^^ required by this bound in `needs_fn`
diff --git a/tests/ui/async-await/async-closures/lint-closure-returning-async-block.rs b/tests/ui/async-await/async-closures/lint-closure-returning-async-block.rs
index 3e2ab8321a8..f05d918aef2 100644
--- a/tests/ui/async-await/async-closures/lint-closure-returning-async-block.rs
+++ b/tests/ui/async-await/async-closures/lint-closure-returning-async-block.rs
@@ -1,6 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
 #![deny(closure_returning_async_block)]
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/lint-closure-returning-async-block.stderr b/tests/ui/async-await/async-closures/lint-closure-returning-async-block.stderr
index 4c0c4d797d8..287dc52c593 100644
--- a/tests/ui/async-await/async-closures/lint-closure-returning-async-block.stderr
+++ b/tests/ui/async-await/async-closures/lint-closure-returning-async-block.stderr
@@ -1,11 +1,11 @@
 error: closure returning async block can be made into an async closure
-  --> $DIR/lint-closure-returning-async-block.rs:7:13
+  --> $DIR/lint-closure-returning-async-block.rs:6:13
    |
 LL |     let x = || async {};
    |             ^^ ----- this async block can be removed, and the closure can be turned into an async closure
    |
 note: the lint level is defined here
-  --> $DIR/lint-closure-returning-async-block.rs:4:9
+  --> $DIR/lint-closure-returning-async-block.rs:3:9
    |
 LL | #![deny(closure_returning_async_block)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL +     let x = async || {};
    |
 
 error: closure returning async block can be made into an async closure
-  --> $DIR/lint-closure-returning-async-block.rs:10:13
+  --> $DIR/lint-closure-returning-async-block.rs:9:13
    |
 LL |     let x = || async move {};
    |             ^^ ---------- this async block can be removed, and the closure can be turned into an async closure
@@ -28,7 +28,7 @@ LL +     let x = async || {};
    |
 
 error: closure returning async block can be made into an async closure
-  --> $DIR/lint-closure-returning-async-block.rs:13:13
+  --> $DIR/lint-closure-returning-async-block.rs:12:13
    |
 LL |     let x = move || async move {};
    |             ^^^^^^^ ---------- this async block can be removed, and the closure can be turned into an async closure
@@ -40,7 +40,7 @@ LL +     let x = async move || {};
    |
 
 error: closure returning async block can be made into an async closure
-  --> $DIR/lint-closure-returning-async-block.rs:16:13
+  --> $DIR/lint-closure-returning-async-block.rs:15:13
    |
 LL |     let x = move || async {};
    |             ^^^^^^^ ----- this async block can be removed, and the closure can be turned into an async closure
@@ -52,7 +52,7 @@ LL +     let x = async move || {};
    |
 
 error: closure returning async block can be made into an async closure
-  --> $DIR/lint-closure-returning-async-block.rs:19:13
+  --> $DIR/lint-closure-returning-async-block.rs:18:13
    |
 LL |     let x = || {{ async {} }};
    |             ^^    ----- this async block can be removed, and the closure can be turned into an async closure
diff --git a/tests/ui/async-await/async-closures/mac-body.rs b/tests/ui/async-await/async-closures/mac-body.rs
index a416227c390..51c077ba03f 100644
--- a/tests/ui/async-await/async-closures/mac-body.rs
+++ b/tests/ui/async-await/async-closures/mac-body.rs
@@ -1,8 +1,6 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure)]
-
 // Make sure we don't ICE if an async closure has a macro body.
 // This happened because we were calling walk instead of visit
 // in the def collector, oops!
diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs
index 1790f369c57..c8e5e52e1b2 100644
--- a/tests/ui/async-await/async-closures/mangle.rs
+++ b/tests/ui/async-await/async-closures/mangle.rs
@@ -5,8 +5,6 @@
 //@[v0] compile-flags: -Csymbol-mangling-version=v0
 //@[legacy] compile-flags: -Csymbol-mangling-version=legacy -Zunstable-options
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 use std::future::Future;
diff --git a/tests/ui/async-await/async-closures/moro-example.rs b/tests/ui/async-await/async-closures/moro-example.rs
index c331b8e5b5e..502b3e1bbf8 100644
--- a/tests/ui/async-await/async-closures/moro-example.rs
+++ b/tests/ui/async-await/async-closures/moro-example.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::pin::Pin;
 use std::{marker::PhantomData, sync::Mutex};
diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.rs b/tests/ui/async-await/async-closures/move-consuming-capture.rs
index 17925fc89ba..c833bc7e895 100644
--- a/tests/ui/async-await/async-closures/move-consuming-capture.rs
+++ b/tests/ui/async-await/async-closures/move-consuming-capture.rs
@@ -1,8 +1,6 @@
 //@ aux-build:block-on.rs
 //@ edition:2021
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 struct NoCopy;
diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.stderr b/tests/ui/async-await/async-closures/move-consuming-capture.stderr
index 4ce71ec49d6..e28716ca213 100644
--- a/tests/ui/async-await/async-closures/move-consuming-capture.stderr
+++ b/tests/ui/async-await/async-closures/move-consuming-capture.stderr
@@ -1,8 +1,8 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/move-consuming-capture.rs:17:9
+  --> $DIR/move-consuming-capture.rs:15:9
    |
 LL |         let x = async move || {
-   |             - move occurs because `x` has type `{async closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait
+   |             - move occurs because `x` has type `{async closure@$DIR/move-consuming-capture.rs:11:17: 11:30}`, which does not implement the `Copy` trait
 ...
 LL |         x().await;
    |         --- `x` moved due to this method call
diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs
index d0e2bc24b52..2cbad0faffc 100644
--- a/tests/ui/async-await/async-closures/move-is-async-fn.rs
+++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs
@@ -2,7 +2,7 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure, async_fn_traits)]
+#![feature(async_fn_traits)]
 
 extern crate block_on;
 
diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.rs b/tests/ui/async-await/async-closures/move-out-of-ref.rs
index a05447232f6..34389d2d00a 100644
--- a/tests/ui/async-await/async-closures/move-out-of-ref.rs
+++ b/tests/ui/async-await/async-closures/move-out-of-ref.rs
@@ -1,8 +1,6 @@
 //@ compile-flags: -Zvalidate-mir
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 // NOT copy.
 struct Ty;
 
diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr
index 294905a481d..8a63515a8a9 100644
--- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr
+++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr
@@ -1,11 +1,11 @@
 error[E0507]: cannot move out of `*x` which is behind a shared reference
-  --> $DIR/move-out-of-ref.rs:11:9
+  --> $DIR/move-out-of-ref.rs:9:9
    |
 LL |         *x;
    |         ^^ move occurs because `*x` has type `Ty`, which does not implement the `Copy` trait
    |
 note: if `Ty` implemented `Clone`, you could clone the value
-  --> $DIR/move-out-of-ref.rs:7:1
+  --> $DIR/move-out-of-ref.rs:5:1
    |
 LL | struct Ty;
    | ^^^^^^^^^ consider implementing `Clone` for this type
diff --git a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
index c37048398e9..a1a90a1c9ad 100644
--- a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
+++ b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
@@ -5,8 +5,6 @@
 //@[e2018] edition:2018
 //@[e2021] edition:2021
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 async fn call_once(f: impl AsyncFnOnce()) { f().await; }
diff --git a/tests/ui/async-await/async-closures/mutate.rs b/tests/ui/async-await/async-closures/mutate.rs
index 562a7271c66..7c1d8389eac 100644
--- a/tests/ui/async-await/async-closures/mutate.rs
+++ b/tests/ui/async-await/async-closures/mutate.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ run-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/no-borrow-from-env.rs b/tests/ui/async-await/async-closures/no-borrow-from-env.rs
index 36b10c06dca..ce180631389 100644
--- a/tests/ui/async-await/async-closures/no-borrow-from-env.rs
+++ b/tests/ui/async-await/async-closures/no-borrow-from-env.rs
@@ -1,8 +1,6 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure)]
-
 fn outlives<'a>(_: impl Sized + 'a) {}
 
 async fn call_once(f: impl AsyncFnOnce()) {
diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
index cfb50dd5574..0c22ac97265 100644
--- a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
+++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) {
diff --git a/tests/ui/async-await/async-closures/not-clone-closure.rs b/tests/ui/async-await/async-closures/not-clone-closure.rs
index 2776ce4690f..c96c50e85d8 100644
--- a/tests/ui/async-await/async-closures/not-clone-closure.rs
+++ b/tests/ui/async-await/async-closures/not-clone-closure.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 struct NotClonableArg;
 #[derive(Default)]
 struct NotClonableReturnType;
diff --git a/tests/ui/async-await/async-closures/not-clone-closure.stderr b/tests/ui/async-await/async-closures/not-clone-closure.stderr
index c2f963f9b92..a08ee45f970 100644
--- a/tests/ui/async-await/async-closures/not-clone-closure.stderr
+++ b/tests/ui/async-await/async-closures/not-clone-closure.stderr
@@ -1,12 +1,12 @@
-error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`
-  --> $DIR/not-clone-closure.rs:32:15
+error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{async closure@$DIR/not-clone-closure.rs:27:21: 27:34}`
+  --> $DIR/not-clone-closure.rs:30:15
    |
 LL |     not_clone.clone();
    |               ^^^^^ unsatisfied trait bound
    |
-   = help: within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`
+   = help: within `{async closure@$DIR/not-clone-closure.rs:27:21: 27:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`
 note: required because it's used within this closure
-  --> $DIR/not-clone-closure.rs:29:21
+  --> $DIR/not-clone-closure.rs:27:21
    |
 LL |     let not_clone = async move || {
    |                     ^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/async-closures/not-fn.rs b/tests/ui/async-await/async-closures/not-fn.rs
index 5f2d047c3e9..34dd2a22bbb 100644
--- a/tests/ui/async-await/async-closures/not-fn.rs
+++ b/tests/ui/async-await/async-closures/not-fn.rs
@@ -2,8 +2,6 @@
 
 // FIXME(async_closures): This needs a better error message!
 
-#![feature(async_closure)]
-
 fn main() {
     fn needs_fn<T>(_: impl FnMut() -> T) {}
 
diff --git a/tests/ui/async-await/async-closures/not-fn.stderr b/tests/ui/async-await/async-closures/not-fn.stderr
index 9c40613599a..4b9d2db9a25 100644
--- a/tests/ui/async-await/async-closures/not-fn.stderr
+++ b/tests/ui/async-await/async-closures/not-fn.stderr
@@ -1,5 +1,5 @@
 error: async closure does not implement `FnMut` because it captures state from its environment
-  --> $DIR/not-fn.rs:11:14
+  --> $DIR/not-fn.rs:9:14
    |
 LL |     needs_fn(async || {
    |     -------- ^^^^^^^^
@@ -7,7 +7,7 @@ LL |     needs_fn(async || {
    |     required by a bound introduced by this call
    |
 note: required by a bound in `needs_fn`
-  --> $DIR/not-fn.rs:8:28
+  --> $DIR/not-fn.rs:6:28
    |
 LL |     fn needs_fn<T>(_: impl FnMut() -> T) {}
    |                            ^^^^^^^^^^^^ required by this bound in `needs_fn`
diff --git a/tests/ui/async-await/async-closures/not-lending.rs b/tests/ui/async-await/async-closures/not-lending.rs
index 2e5542207cf..7bf2d3ead52 100644
--- a/tests/ui/async-await/async-closures/not-lending.rs
+++ b/tests/ui/async-await/async-closures/not-lending.rs
@@ -1,8 +1,6 @@
 //@ aux-build:block-on.rs
 //@ edition:2021
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 // Make sure that we can't make an async closure that evaluates to a self-borrow.
diff --git a/tests/ui/async-await/async-closures/not-lending.stderr b/tests/ui/async-await/async-closures/not-lending.stderr
index 1713e49b551..f0028129caa 100644
--- a/tests/ui/async-await/async-closures/not-lending.stderr
+++ b/tests/ui/async-await/async-closures/not-lending.stderr
@@ -1,21 +1,21 @@
 error: lifetime may not live long enough
-  --> $DIR/not-lending.rs:14:42
+  --> $DIR/not-lending.rs:12:42
    |
 LL |         let x = async move || -> &String { &s };
    |                 ------------------------ ^^^^^^ returning this value requires that `'1` must outlive `'2`
    |                 |                |
-   |                 |                return type of async closure `{async closure body@$DIR/not-lending.rs:14:42: 14:48}` contains a lifetime `'2`
+   |                 |                return type of async closure `{async closure body@$DIR/not-lending.rs:12:42: 12:48}` contains a lifetime `'2`
    |                 lifetime `'1` represents this closure's body
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure
 
 error: lifetime may not live long enough
-  --> $DIR/not-lending.rs:18:31
+  --> $DIR/not-lending.rs:16:31
    |
 LL |         let x = async move || { &s };
    |                 ------------- ^^^^^^ returning this value requires that `'1` must outlive `'2`
    |                 |           |
-   |                 |           return type of async closure `{async closure body@$DIR/not-lending.rs:18:31: 18:37}` contains a lifetime `'2`
+   |                 |           return type of async closure `{async closure body@$DIR/not-lending.rs:16:31: 16:37}` contains a lifetime `'2`
    |                 lifetime `'1` represents this closure's body
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure
diff --git a/tests/ui/async-await/async-closures/once.rs b/tests/ui/async-await/async-closures/once.rs
index 7009e0d132f..3cf70e16a12 100644
--- a/tests/ui/async-await/async-closures/once.rs
+++ b/tests/ui/async-await/async-closures/once.rs
@@ -5,8 +5,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(async_closure)]
-
 use std::future::Future;
 
 extern crate block_on;
diff --git a/tests/ui/async-await/async-closures/overlapping-projs.rs b/tests/ui/async-await/async-closures/overlapping-projs.rs
index f778534cfe2..c37f24b4ff2 100644
--- a/tests/ui/async-await/async-closures/overlapping-projs.rs
+++ b/tests/ui/async-await/async-closures/overlapping-projs.rs
@@ -3,8 +3,6 @@
 //@ run-pass
 //@ check-run-results
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 async fn call_once(f: impl AsyncFnOnce()) {
diff --git a/tests/ui/async-await/async-closures/precise-captures.rs b/tests/ui/async-await/async-closures/precise-captures.rs
index 7dcbf2595f0..638fb67c3a4 100644
--- a/tests/ui/async-await/async-closures/precise-captures.rs
+++ b/tests/ui/async-await/async-closures/precise-captures.rs
@@ -9,7 +9,6 @@
 // force_once - Force the closure mode to `FnOnce`, so exercising what was fixed
 //   in <https://github.com/rust-lang/rust/pull/123350>.
 
-#![feature(async_closure)]
 #![allow(unused_mut)]
 
 extern crate block_on;
diff --git a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs
index 2e7cf1b09fd..deae1c9376a 100644
--- a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs
+++ b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.rs
@@ -1,9 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
-use std::ops::AsyncFnMut;
-
 fn produce() -> impl AsyncFnMut() -> &'static str {
     async || ""
 }
diff --git a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr
index 863e61eb35a..8bbd9fbec3e 100644
--- a/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr
+++ b/tests/ui/async-await/async-closures/pretty-async-fn-opaque.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pretty-async-fn-opaque.rs:12:18
+  --> $DIR/pretty-async-fn-opaque.rs:8:18
    |
 LL | fn produce() -> impl AsyncFnMut() -> &'static str {
    |                 --------------------------------- the found opaque type
diff --git a/tests/ui/async-await/async-closures/refd.rs b/tests/ui/async-await/async-closures/refd.rs
index 8c16ecb1531..ae8a10a530a 100644
--- a/tests/ui/async-await/async-closures/refd.rs
+++ b/tests/ui/async-await/async-closures/refd.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 struct NoCopy;
diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.rs b/tests/ui/async-await/async-closures/return-type-mismatch.rs
index 992f033180e..d3b4cb61cdf 100644
--- a/tests/ui/async-await/async-closures/return-type-mismatch.rs
+++ b/tests/ui/async-await/async-closures/return-type-mismatch.rs
@@ -1,8 +1,6 @@
 //@ aux-build:block-on.rs
 //@ edition:2021
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.stderr b/tests/ui/async-await/async-closures/return-type-mismatch.stderr
index 53841f62777..d7675aab953 100644
--- a/tests/ui/async-await/async-closures/return-type-mismatch.stderr
+++ b/tests/ui/async-await/async-closures/return-type-mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/return-type-mismatch.rs:11:24
+  --> $DIR/return-type-mismatch.rs:9:24
    |
 LL |         let y: usize = x().await;
    |                        ^^^^^^^^^ expected `usize`, found `i32`
diff --git a/tests/ui/async-await/async-closures/sig-from-bare-fn.rs b/tests/ui/async-await/async-closures/sig-from-bare-fn.rs
index a679471a3b3..72aac140256 100644
--- a/tests/ui/async-await/async-closures/sig-from-bare-fn.rs
+++ b/tests/ui/async-await/async-closures/sig-from-bare-fn.rs
@@ -5,8 +5,6 @@
 // a function that requires the async closure implement `Fn*` but does *not* have
 // a `Future` bound on the return type.
 
-#![feature(async_closure)]
-
 use std::future::Future;
 
 trait TryStream {
diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs
index 4e9a6747f1f..27ec54ba4f9 100644
--- a/tests/ui/async-await/async-closures/signature-deduction.rs
+++ b/tests/ui/async-await/async-closures/signature-deduction.rs
@@ -1,8 +1,6 @@
 //@ build-pass
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 async fn foo(x: impl AsyncFn(&str) -> &str) {}
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs b/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs
index 0e2d1ef1208..f66787bd6fc 100644
--- a/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs
+++ b/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs
@@ -4,8 +4,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::any::Any;
 
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.rs b/tests/ui/async-await/async-closures/tainted-body-2.rs
index 73c6bdc30a0..8314f7e7f96 100644
--- a/tests/ui/async-await/async-closures/tainted-body-2.rs
+++ b/tests/ui/async-await/async-closures/tainted-body-2.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 // Ensure that building a by-ref async closure body doesn't ICE when the parent
 // body is tainted.
 
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.stderr b/tests/ui/async-await/async-closures/tainted-body-2.stderr
index 798d47064d9..cffd67b6361 100644
--- a/tests/ui/async-await/async-closures/tainted-body-2.stderr
+++ b/tests/ui/async-await/async-closures/tainted-body-2.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `missing` in this scope
-  --> $DIR/tainted-body-2.rs:9:5
+  --> $DIR/tainted-body-2.rs:7:5
    |
 LL |     missing;
    |     ^^^^^^^ not found in this scope
diff --git a/tests/ui/async-await/async-closures/tainted-body.rs b/tests/ui/async-await/async-closures/tainted-body.rs
index e42d9d6e36a..118c0887469 100644
--- a/tests/ui/async-await/async-closures/tainted-body.rs
+++ b/tests/ui/async-await/async-closures/tainted-body.rs
@@ -1,7 +1,5 @@
 //@ edition:2021
 
-#![feature(async_closure)]
-
 // Don't ICE in ByMove shim builder when MIR body is tainted by writeback errors
 
 fn main() {
diff --git a/tests/ui/async-await/async-closures/tainted-body.stderr b/tests/ui/async-await/async-closures/tainted-body.stderr
index b06a896b81f..617d87e9df2 100644
--- a/tests/ui/async-await/async-closures/tainted-body.stderr
+++ b/tests/ui/async-await/async-closures/tainted-body.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find function `used_fn` in this scope
-  --> $DIR/tainted-body.rs:9:9
+  --> $DIR/tainted-body.rs:7:9
    |
 LL |         used_fn();
    |         ^^^^^^^ not found in this scope
diff --git a/tests/ui/async-await/async-closures/truncated-fields-when-imm.rs b/tests/ui/async-await/async-closures/truncated-fields-when-imm.rs
index 5c718638d80..7d08cdb91e5 100644
--- a/tests/ui/async-await/async-closures/truncated-fields-when-imm.rs
+++ b/tests/ui/async-await/async-closures/truncated-fields-when-imm.rs
@@ -1,8 +1,6 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure)]
-
 pub struct Struct {
     pub path: String,
 }
diff --git a/tests/ui/async-await/async-closures/validate-synthetic-body.rs b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
index 67e683ac08a..3fd7382f7f9 100644
--- a/tests/ui/async-await/async-closures/validate-synthetic-body.rs
+++ b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 // Make sure that we don't hit a query cycle when validating
 // the by-move coroutine body for an async closure.
 
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
index 19f366cc903..19a31d1889b 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
@@ -4,8 +4,6 @@
 // sure that we don't ICE or anything, even if precise closure captures means
 // that we can't actually borrowck successfully.
 
-#![feature(async_closure)]
-
 fn outlives<'a>(_: impl Sized + 'a) {}
 
 async fn call_once(f: impl AsyncFnOnce()) {
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
index a70aece2dea..be39dbf313b 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `x` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:16:13
+  --> $DIR/without-precise-captures-we-are-powerless.rs:14:13
    |
 LL | fn simple<'a>(x: &'a i32) {
    |           -- lifetime `'a` defined here
@@ -13,7 +13,7 @@ LL | }
    |  - `x` dropped here while still borrowed
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:21:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:19:20
    |
 LL | fn simple<'a>(x: &'a i32) {
    |           -- lifetime `'a` defined here
@@ -30,7 +30,7 @@ LL | }
    | - `c` dropped here while still borrowed
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:28:13
+  --> $DIR/without-precise-captures-we-are-powerless.rs:26:13
    |
 LL | fn through_field<'a>(x: S<'a>) {
    |                  -- lifetime `'a` defined here
@@ -44,7 +44,7 @@ LL | }
    |  - `x` dropped here while still borrowed
 
 error[E0505]: cannot move out of `x` because it is borrowed
-  --> $DIR/without-precise-captures-we-are-powerless.rs:32:13
+  --> $DIR/without-precise-captures-we-are-powerless.rs:30:13
    |
 LL | fn through_field<'a>(x: S<'a>) {
    |                  -- lifetime `'a` defined here
@@ -58,7 +58,7 @@ LL |     let c = async move || { println!("{}", *x.0); };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:33:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:31:20
    |
 LL | fn through_field<'a>(x: S<'a>) {
    |                  -- lifetime `'a` defined here
@@ -75,7 +75,7 @@ LL | }
    | - `c` dropped here while still borrowed
 
 error[E0505]: cannot move out of `c` because it is borrowed
-  --> $DIR/without-precise-captures-we-are-powerless.rs:34:30
+  --> $DIR/without-precise-captures-we-are-powerless.rs:32:30
    |
 LL | fn through_field<'a>(x: S<'a>) {
    |                  -- lifetime `'a` defined here
@@ -91,7 +91,7 @@ LL |     outlives::<'a>(call_once(c));
    |                              ^ move out of `c` occurs here
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:38:13
+  --> $DIR/without-precise-captures-we-are-powerless.rs:36:13
    |
 LL | fn through_field_and_ref<'a>(x: &S<'a>) {
    |                          -- lifetime `'a` defined here
@@ -104,7 +104,7 @@ LL | }
    |  - `x` dropped here while still borrowed
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/without-precise-captures-we-are-powerless.rs:40:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:38:20
    |
 LL | fn through_field_and_ref<'a>(x: &S<'a>) {
    |                                 ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
@@ -113,7 +113,7 @@ LL |     outlives::<'a>(call_once(c));
    |                    ^^^^^^^^^^^^ lifetime `'a` required
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/without-precise-captures-we-are-powerless.rs:45:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:43:20
    |
 LL | fn through_field_and_ref_move<'a>(x: &S<'a>) {
    |                               -- lifetime `'a` defined here
@@ -129,7 +129,7 @@ LL | }
    | - `c` dropped here while still borrowed
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/without-precise-captures-we-are-powerless.rs:46:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:44:20
    |
 LL | fn through_field_and_ref_move<'a>(x: &S<'a>) {
    |                                      ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
index a566b8aa663..2aed6dc6d80 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
@@ -1,7 +1,5 @@
 //@ edition:2021
 
-#![feature(async_closure)]
-
 fn needs_async_fn(_: impl AsyncFn()) {}
 
 fn a() {
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
index d03b10ca2cc..95f314214cc 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
@@ -1,5 +1,5 @@
 error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
-  --> $DIR/wrong-fn-kind.rs:17:20
+  --> $DIR/wrong-fn-kind.rs:15:20
    |
 LL |       needs_async_fn(move || async move {
    |       -------------- -^^^^^^
@@ -14,13 +14,13 @@ LL | |     });
    | |_____- the requirement to implement `AsyncFn` derives from here
    |
 note: required by a bound in `needs_async_fn`
-  --> $DIR/wrong-fn-kind.rs:5:27
+  --> $DIR/wrong-fn-kind.rs:3:27
    |
 LL | fn needs_async_fn(_: impl AsyncFn()) {}
    |                           ^^^^^^^^^ required by this bound in `needs_async_fn`
 
 error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
-  --> $DIR/wrong-fn-kind.rs:9:20
+  --> $DIR/wrong-fn-kind.rs:7:20
    |
 LL | fn needs_async_fn(_: impl AsyncFn()) {}
    |                      -------------- change this to accept `FnMut` instead of `Fn`
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs
index d3884680e51..b1af81423ce 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop.rs
@@ -5,7 +5,7 @@
 // please consider modifying miri's async drop test at
 // `src/tools/miri/tests/pass/async-drop.rs`.
 
-#![feature(async_drop, impl_trait_in_assoc_type, async_closure)]
+#![feature(async_drop, impl_trait_in_assoc_type)]
 #![allow(incomplete_features, dead_code)]
 
 //@ edition: 2021
diff --git a/tests/ui/async-await/async-fn/auxiliary/block-on.rs b/tests/ui/async-await/async-fn/auxiliary/block-on.rs
index 8b50c5571c1..4ec45ddf333 100644
--- a/tests/ui/async-await/async-fn/auxiliary/block-on.rs
+++ b/tests/ui/async-await/async-fn/auxiliary/block-on.rs
@@ -1,7 +1,5 @@
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::pin::pin;
 use std::task::*;
diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs
index 129ea282936..d71af1bd53e 100644
--- a/tests/ui/async-await/async-fn/dyn-pos.rs
+++ b/tests/ui/async-await/async-fn/dyn-pos.rs
@@ -1,7 +1,5 @@
 //@ edition:2018
 
-#![feature(async_closure)]
-
 fn foo(x: &dyn AsyncFn()) {}
 //~^ ERROR the trait `AsyncFnMut` cannot be made into an object
 
diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr
index aaa8eb2634d..0c901846671 100644
--- a/tests/ui/async-await/async-fn/dyn-pos.stderr
+++ b/tests/ui/async-await/async-fn/dyn-pos.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait `AsyncFnMut` cannot be made into an object
-  --> $DIR/dyn-pos.rs:5:16
+  --> $DIR/dyn-pos.rs:3:16
    |
 LL | fn foo(x: &dyn AsyncFn()) {}
    |                ^^^^^^^^^ `AsyncFnMut` cannot be made into an object
diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs
index 7fc62a8dd93..341b9b10e67 100644
--- a/tests/ui/async-await/async-fn/edition-2015.rs
+++ b/tests/ui/async-await/async-fn/edition-2015.rs
@@ -3,7 +3,5 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x }
 //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
 //~| ERROR `async` trait bounds are unstable
 //~| ERROR `async` trait bounds are unstable
-//~| ERROR use of unstable library feature `async_closure`
-//~| ERROR use of unstable library feature `async_closure`
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr
index 96fb4c9e979..ca9e64cd1bb 100644
--- a/tests/ui/async-await/async-fn/edition-2015.stderr
+++ b/tests/ui/async-await/async-fn/edition-2015.stderr
@@ -38,26 +38,6 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: use the desugared name of the async trait, such as `AsyncFn`
 
-error[E0658]: use of unstable library feature `async_closure`
-  --> $DIR/edition-2015.rs:1:42
-   |
-LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
-   |                                          ^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature `async_closure`
-  --> $DIR/edition-2015.rs:1:22
-   |
-LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
-   |                      ^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
index 5d675921028..ac8e0d7c63e 100644
--- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
+++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
@@ -5,8 +5,6 @@
 //@[next] compile-flags: -Znext-solver
 //@ build-pass (since it ICEs during mono)
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 use std::future::Future;
diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs
index 11faf9ac983..f284de8981a 100644
--- a/tests/ui/async-await/async-fn/impl-trait.rs
+++ b/tests/ui/async-await/async-fn/impl-trait.rs
@@ -1,7 +1,7 @@
 //@ edition:2018
 //@ check-pass
 
-#![feature(async_closure, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
 type Tait = impl AsyncFn();
 fn tait() -> Tait {
diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs
index b6068a916ae..8ee50724e4c 100644
--- a/tests/ui/async-await/async-fn/project.rs
+++ b/tests/ui/async-await/async-fn/project.rs
@@ -4,7 +4,7 @@
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
-#![feature(async_closure, unboxed_closures, async_fn_traits)]
+#![feature(unboxed_closures, async_fn_traits)]
 
 use std::ops::AsyncFn;
 
diff --git a/tests/ui/async-await/async-fn/simple.rs b/tests/ui/async-await/async-fn/simple.rs
index 3f15b08560a..89b68e12435 100644
--- a/tests/ui/async-await/async-fn/simple.rs
+++ b/tests/ui/async-await/async-fn/simple.rs
@@ -2,8 +2,6 @@
 //@ edition: 2021
 //@ build-pass
 
-#![feature(async_closure)]
-
 extern crate block_on;
 
 use std::ops::AsyncFn;
diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs
index 0225b666ac5..d00965ee647 100644
--- a/tests/ui/async-await/async-fn/sugar.rs
+++ b/tests/ui/async-await/async-fn/sugar.rs
@@ -1,7 +1,7 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure, async_trait_bounds)]
+#![feature(async_trait_bounds)]
 
 async fn foo() {}
 
diff --git a/tests/ui/async-await/coroutine-desc.rs b/tests/ui/async-await/coroutine-desc.rs
index 9a61c9719db..9a581049107 100644
--- a/tests/ui/async-await/coroutine-desc.rs
+++ b/tests/ui/async-await/coroutine-desc.rs
@@ -1,5 +1,4 @@
 //@ edition:2018
-#![feature(async_closure)]
 use std::future::Future;
 
 async fn one() {}
diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr
index 5434ff3d958..01482a9cb1f 100644
--- a/tests/ui/async-await/coroutine-desc.stderr
+++ b/tests/ui/async-await/coroutine-desc.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/coroutine-desc.rs:10:19
+  --> $DIR/coroutine-desc.rs:9:19
    |
 LL |     fun(async {}, async {});
    |     --- --------  ^^^^^^^^ expected `async` block, found a different `async` block
@@ -8,12 +8,12 @@ LL |     fun(async {}, async {});
    |     |   expected all arguments to be this `async` block type because they need to match the type of this parameter
    |     arguments to this function are incorrect
    |
-   = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:14}`
-              found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:24}`
+   = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:9:9: 9:14}`
+              found `async` block `{async block@$DIR/coroutine-desc.rs:9:19: 9:24}`
    = note: no two async blocks, even if identical, have the same type
    = help: consider pinning your async block and casting it to a trait object
 note: function defined here
-  --> $DIR/coroutine-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:7:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^ -                       -----  ----- this parameter needs to match the `async` block type of `f1`
@@ -22,7 +22,7 @@ LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |        `f1` and `f2` both reference this parameter `F`
 
 error[E0308]: mismatched types
-  --> $DIR/coroutine-desc.rs:12:16
+  --> $DIR/coroutine-desc.rs:11:16
    |
 LL |     fun(one(), two());
    |     --- -----  ^^^^^ expected future, found a different future
@@ -33,7 +33,7 @@ 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/coroutine-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:7:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^ -                       -----  ----- this parameter needs to match the future type of `f1`
@@ -42,7 +42,7 @@ LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |        `f1` and `f2` both reference this parameter `F`
 
 error[E0308]: mismatched types
-  --> $DIR/coroutine-desc.rs:14:26
+  --> $DIR/coroutine-desc.rs:13:26
    |
 LL |     fun((async || {})(), (async || {})());
    |     --- ---------------  ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
@@ -51,12 +51,12 @@ LL |     fun((async || {})(), (async || {})());
    |     |   expected all arguments to be this `async` closure body type because they need to match the type of this parameter
    |     arguments to this function are incorrect
    |
-   = 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: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:13:19: 13:21}`
+              found `async` closure body `{async closure body@$DIR/coroutine-desc.rs:13:36: 13:38}`
    = note: no two async blocks, even if identical, have the same type
    = help: consider pinning your async block and casting it to a trait object
 note: function defined here
-  --> $DIR/coroutine-desc.rs:8:4
+  --> $DIR/coroutine-desc.rs:7:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
    |    ^^^ -                       -----  ----- this parameter needs to match the `async` closure body type of `f1`
diff --git a/tests/ui/async-await/dyn/auxiliary/block-on.rs b/tests/ui/async-await/dyn/auxiliary/block-on.rs
new file mode 100644
index 00000000000..dcb710fc97c
--- /dev/null
+++ b/tests/ui/async-await/dyn/auxiliary/block-on.rs
@@ -0,0 +1,20 @@
+//@ edition: 2021
+
+#![feature(async_closure, noop_waker)]
+
+use std::future::Future;
+use std::pin::pin;
+use std::task::*;
+
+pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
+    let mut fut = pin!(fut);
+    // Poll loop, just to test the future...
+    let ctx = &mut Context::from_waker(Waker::noop());
+
+    loop {
+        match unsafe { fut.as_mut().poll(ctx) } {
+            Poll::Pending => {}
+            Poll::Ready(t) => break t,
+        }
+    }
+}
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.rs b/tests/ui/async-await/dyn/mut-is-pointer-like.rs
new file mode 100644
index 00000000000..93e8281164c
--- /dev/null
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.rs
@@ -0,0 +1,40 @@
+//@ aux-build:block-on.rs
+//@ edition: 2021
+//@ run-pass
+//@ check-run-results
+
+#![allow(refining_impl_trait)]
+#![feature(async_fn_in_dyn_trait)]
+//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
+
+extern crate block_on;
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait AsyncTrait {
+    type Output;
+
+    async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
+}
+
+impl<F> AsyncTrait for F
+where
+    F: Future,
+{
+    type Output = F::Output;
+
+    fn async_dispatch(self: Pin<&mut Self>) -> Pin<&mut Self> {
+        self
+    }
+}
+
+fn main() {
+    block_on::block_on(async {
+        let f = std::pin::pin!(async {
+            println!("hello, world");
+        });
+        let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
+        x.async_dispatch().await;
+    });
+}
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.run.stdout b/tests/ui/async-await/dyn/mut-is-pointer-like.run.stdout
new file mode 100644
index 00000000000..4b5fa63702d
--- /dev/null
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.run.stdout
@@ -0,0 +1 @@
+hello, world
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
new file mode 100644
index 00000000000..7c72ce43cf0
--- /dev/null
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/mut-is-pointer-like.rs:7:12
+   |
+LL | #![feature(async_fn_in_dyn_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/dyn/works.rs b/tests/ui/async-await/dyn/works.rs
new file mode 100644
index 00000000000..0732a3ee2f2
--- /dev/null
+++ b/tests/ui/async-await/dyn/works.rs
@@ -0,0 +1,32 @@
+//@ aux-build:block-on.rs
+//@ edition: 2021
+//@ run-pass
+//@ check-run-results
+
+#![allow(refining_impl_trait)]
+#![feature(async_fn_in_dyn_trait)]
+//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
+
+extern crate block_on;
+
+use std::pin::Pin;
+use std::future::Future;
+
+trait AsyncTrait {
+    async fn async_dispatch(&self);
+}
+
+impl AsyncTrait for &'static str {
+    fn async_dispatch(&self) -> Pin<Box<impl Future<Output = ()>>> {
+        Box::pin(async move {
+            println!("message from the aether: {self}");
+        })
+    }
+}
+
+fn main() {
+    block_on::block_on(async {
+        let x: &dyn AsyncTrait = &"hello, world!";
+        x.async_dispatch().await;
+    });
+}
diff --git a/tests/ui/async-await/dyn/works.run.stdout b/tests/ui/async-await/dyn/works.run.stdout
new file mode 100644
index 00000000000..7b45a504e60
--- /dev/null
+++ b/tests/ui/async-await/dyn/works.run.stdout
@@ -0,0 +1 @@
+message from the aether: hello, world!
diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr
new file mode 100644
index 00000000000..2c7db7c32f5
--- /dev/null
+++ b/tests/ui/async-await/dyn/works.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/works.rs:7:12
+   |
+LL | #![feature(async_fn_in_dyn_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/dyn/wrong-size.rs b/tests/ui/async-await/dyn/wrong-size.rs
new file mode 100644
index 00000000000..ac15dd26067
--- /dev/null
+++ b/tests/ui/async-await/dyn/wrong-size.rs
@@ -0,0 +1,23 @@
+//@ edition: 2021
+
+#![feature(async_fn_in_dyn_trait)]
+//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
+
+use std::future::Future;
+
+trait AsyncTrait {
+    async fn async_dispatch(&self);
+}
+
+impl AsyncTrait for &'static str {
+    fn async_dispatch(&self) -> impl Future<Output = ()> {
+        async move {
+            // The implementor must box the future...
+        }
+    }
+}
+
+fn main() {
+    let x: &dyn AsyncTrait = &"hello, world!";
+    //~^ ERROR `impl Future<Output = ()>` needs to have the same ABI as a pointer
+}
diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr
new file mode 100644
index 00000000000..0202b5f2409
--- /dev/null
+++ b/tests/ui/async-await/dyn/wrong-size.stderr
@@ -0,0 +1,21 @@
+warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/wrong-size.rs:3:12
+   |
+LL | #![feature(async_fn_in_dyn_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: `impl Future<Output = ()>` needs to have the same ABI as a pointer
+  --> $DIR/wrong-size.rs:21:30
+   |
+LL |     let x: &dyn AsyncTrait = &"hello, world!";
+   |                              ^^^^^^^^^^^^^^^^ `impl Future<Output = ()>` needs to be a pointer-like type
+   |
+   = help: the trait `for<'a> PointerLike` is not implemented for `impl Future<Output = ()>`
+   = note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/feature-async-closure.rs b/tests/ui/async-await/feature-async-closure.rs
deleted file mode 100644
index 15108aa5a33..00000000000
--- a/tests/ui/async-await/feature-async-closure.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ edition:2018
-// gate-test-async_closure
-
-fn f() {
-    let _ = async || {}; //~ ERROR async closures are unstable
-}
-
-fn main() {}
diff --git a/tests/ui/async-await/feature-async-closure.stderr b/tests/ui/async-await/feature-async-closure.stderr
deleted file mode 100644
index 650500b4890..00000000000
--- a/tests/ui/async-await/feature-async-closure.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: async closures are unstable
-  --> $DIR/feature-async-closure.rs:5:13
-   |
-LL |     let _ = async || {};
-   |             ^^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: to use an async block, remove the `||`: `async {`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr
index 7b7b3dbc757..a33c5f7b07d 100644
--- a/tests/ui/async-await/inference_var_self_argument.stderr
+++ b/tests/ui/async-await/inference_var_self_argument.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo`
 LL |     async fn foo(self: &dyn Foo) {
    |                        ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/inference_var_self_argument.rs:5:5
diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr
index c95ae1147df..f4db949a5f4 100644
--- a/tests/ui/async-await/issue-66312.stderr
+++ b/tests/ui/async-await/issue-66312.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T`
 LL |     fn is_some(self: T);
    |                      ^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0308]: mismatched types
   --> $DIR/issue-66312.rs:9:8
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
index 58509642b10..f6c9fdd6d68 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
@@ -1,5 +1,4 @@
 //@ edition:2018
-#![feature(async_closure)]
 use std::future::Future;
 
 // test the quality of annotations giving lifetimes names (`'1`) when async constructs are involved
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
index 9d963686dea..e1f268116fc 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:9:5
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:8:5
    |
 LL | pub async fn async_fn(x: &mut i32) -> &i32 {
    |                          - let's call the lifetime of this reference `'1`
@@ -11,7 +11,7 @@ LL |     y
    |     - returning this value requires that `*x` is borrowed for `'1`
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
    |
 LL |     (async move || {
    |                  - return type of async closure is &'1 i32
@@ -24,12 +24,12 @@ LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:13:20
    |
 LL |       (async move || {
    |  ______-------------_^
    | |      |           |
-   | |      |           return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:14:20: 20:6}` contains a lifetime `'2`
+   | |      |           return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:13:20: 19:6}` contains a lifetime `'2`
    | |      lifetime `'1` represents this closure's body
 LL | |
 LL | |
@@ -42,7 +42,7 @@ LL | |     })()
    = note: closure implements `FnMut`, so references to captured variables can't escape the closure
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:14:5
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:13:5
    |
 LL |    pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
    |                            - let's call the lifetime of this reference `'1`
@@ -60,7 +60,7 @@ LL |    }
    |    - temporary value is freed at the end of this statement
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:27:9
    |
 LL |     (async move || -> &i32 {
    |                          - return type of async closure is &'1 i32
@@ -73,12 +73,12 @@ LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:23:28
    |
 LL |       (async move || -> &i32 {
    |  ______---------------------_^
    | |      |                |
-   | |      |                return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:24:28: 30:6}` contains a lifetime `'2`
+   | |      |                return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:23:28: 29:6}` contains a lifetime `'2`
    | |      lifetime `'1` represents this closure's body
 LL | |
 LL | |
@@ -91,7 +91,7 @@ LL | |     })()
    = note: closure implements `FnMut`, so references to captured variables can't escape the closure
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:24:5
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:23:5
    |
 LL |    pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
    |                                                 - let's call the lifetime of this reference `'1`
@@ -109,7 +109,7 @@ LL |    }
    |    - temporary value is freed at the end of this statement
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:35:9
    |
 LL |     async move {
    |              - return type of async block is &'1 i32
diff --git a/tests/ui/async-await/issues/issue-62009-2.rs b/tests/ui/async-await/issues/issue-62009-2.rs
index f7cba29a747..b660d8a206c 100644
--- a/tests/ui/async-await/issues/issue-62009-2.rs
+++ b/tests/ui/async-await/issues/issue-62009-2.rs
@@ -1,7 +1,5 @@
 //@ edition:2018
 
-#![feature(async_closure)]
-
 async fn print_dur() {}
 
 fn main() {
diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr
index 0004f99f901..9377a02612b 100644
--- a/tests/ui/async-await/issues/issue-62009-2.stderr
+++ b/tests/ui/async-await/issues/issue-62009-2.stderr
@@ -1,5 +1,5 @@
 error[E0728]: `await` is only allowed inside `async` functions and blocks
-  --> $DIR/issue-62009-2.rs:8:23
+  --> $DIR/issue-62009-2.rs:6:23
    |
 LL | fn main() {
    | --------- this is not `async`
diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs
index e9e43b3484a..48651396d25 100644
--- a/tests/ui/async-await/no-params-non-move-async-closure.rs
+++ b/tests/ui/async-await/no-params-non-move-async-closure.rs
@@ -1,8 +1,6 @@
 //@ edition:2018
 //@ check-pass
 
-#![feature(async_closure)]
-
 fn main() {
     let _ = async |x: u8| {};
 }
diff --git a/tests/ui/async-await/suggest-missing-await-closure.fixed b/tests/ui/async-await/suggest-missing-await-closure.fixed
index 1ec3456a265..9ab16d34175 100644
--- a/tests/ui/async-await/suggest-missing-await-closure.fixed
+++ b/tests/ui/async-await/suggest-missing-await-closure.fixed
@@ -1,8 +1,6 @@
 //@ edition:2018
 //@ run-rustfix
 
-#![feature(async_closure)]
-
 fn take_u32(_x: u32) {}
 
 async fn make_u32() -> u32 {
diff --git a/tests/ui/async-await/suggest-missing-await-closure.rs b/tests/ui/async-await/suggest-missing-await-closure.rs
index 3a448ad411b..172132fda33 100644
--- a/tests/ui/async-await/suggest-missing-await-closure.rs
+++ b/tests/ui/async-await/suggest-missing-await-closure.rs
@@ -1,8 +1,6 @@
 //@ edition:2018
 //@ run-rustfix
 
-#![feature(async_closure)]
-
 fn take_u32(_x: u32) {}
 
 async fn make_u32() -> u32 {
diff --git a/tests/ui/async-await/suggest-missing-await-closure.stderr b/tests/ui/async-await/suggest-missing-await-closure.stderr
index 47af270a03a..002c2024f21 100644
--- a/tests/ui/async-await/suggest-missing-await-closure.stderr
+++ b/tests/ui/async-await/suggest-missing-await-closure.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/suggest-missing-await-closure.rs:16:18
+  --> $DIR/suggest-missing-await-closure.rs:14:18
    |
 LL |         take_u32(x)
    |         -------- ^ expected `u32`, found future
@@ -7,12 +7,12 @@ LL |         take_u32(x)
    |         arguments to this function are incorrect
    |
 note: calling an async function returns a future
-  --> $DIR/suggest-missing-await-closure.rs:16:18
+  --> $DIR/suggest-missing-await-closure.rs:14:18
    |
 LL |         take_u32(x)
    |                  ^
 note: function defined here
-  --> $DIR/suggest-missing-await-closure.rs:6:4
+  --> $DIR/suggest-missing-await-closure.rs:4:4
    |
 LL | fn take_u32(_x: u32) {}
    |    ^^^^^^^^ -------
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.rs b/tests/ui/async-await/track-caller/async-closure-gate.rs
index 4b88255bc36..e72ce2afa45 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.rs
+++ b/tests/ui/async-await/track-caller/async-closure-gate.rs
@@ -1,7 +1,7 @@
 //@ edition:2021
 //@ revisions: afn nofeat
 
-#![feature(async_closure, stmt_expr_attributes)]
+#![feature(stmt_expr_attributes)]
 #![cfg_attr(afn, feature(async_fn_track_caller))]
 
 fn main() {
diff --git a/tests/ui/async-await/track-caller/panic-track-caller.rs b/tests/ui/async-await/track-caller/panic-track-caller.rs
index c693a446eed..bd12bf11d6c 100644
--- a/tests/ui/async-await/track-caller/panic-track-caller.rs
+++ b/tests/ui/async-await/track-caller/panic-track-caller.rs
@@ -3,7 +3,7 @@
 //@ revisions: afn cls nofeat
 //@ needs-unwind
 // gate-test-async_fn_track_caller
-#![feature(async_closure, stmt_expr_attributes)]
+#![feature(stmt_expr_attributes)]
 #![cfg_attr(afn, feature(async_fn_track_caller))]
 #![cfg_attr(cls, feature(closure_track_caller))]
 #![allow(unused)]
diff --git a/tests/ui/async-await/try-on-option-in-async.rs b/tests/ui/async-await/try-on-option-in-async.rs
index fda848141d3..4822197bf39 100644
--- a/tests/ui/async-await/try-on-option-in-async.rs
+++ b/tests/ui/async-await/try-on-option-in-async.rs
@@ -1,4 +1,3 @@
-#![feature(async_closure)]
 //@ edition:2018
 fn main() {}
 
diff --git a/tests/ui/async-await/try-on-option-in-async.stderr b/tests/ui/async-await/try-on-option-in-async.stderr
index 65f63093728..9e0bb42a697 100644
--- a/tests/ui/async-await/try-on-option-in-async.stderr
+++ b/tests/ui/async-await/try-on-option-in-async.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/try-on-option-in-async.rs:8:10
+  --> $DIR/try-on-option-in-async.rs:7:10
    |
 LL |     async {
    |     ----- this function should return `Result` or `Option` to accept `?`
@@ -10,7 +10,7 @@ LL |         x?;
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
 
 error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/try-on-option-in-async.rs:17:10
+  --> $DIR/try-on-option-in-async.rs:16:10
    |
 LL |       let async_closure = async || {
    |  __________________________________-
@@ -24,7 +24,7 @@ LL | |     };
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/try-on-option-in-async.rs:26:6
+  --> $DIR/try-on-option-in-async.rs:25:6
    |
 LL |   async fn an_async_function() -> u32 {
    |  _____________________________________-
diff --git a/tests/ui/closures/binder/async-closure-with-binder.rs b/tests/ui/closures/binder/async-closure-with-binder.rs
index 24f4e8e4175..8f84f3074cd 100644
--- a/tests/ui/closures/binder/async-closure-with-binder.rs
+++ b/tests/ui/closures/binder/async-closure-with-binder.rs
@@ -2,7 +2,6 @@
 //@ check-pass
 
 #![feature(closure_lifetime_binder)]
-#![feature(async_closure)]
 
 fn main() {
     for<'a> async || -> () {};
diff --git a/tests/ui/closures/local-type-mix.rs b/tests/ui/closures/local-type-mix.rs
index 823ceb211a3..edcdac2a611 100644
--- a/tests/ui/closures/local-type-mix.rs
+++ b/tests/ui/closures/local-type-mix.rs
@@ -1,8 +1,6 @@
 // Check that using the parameter name in its type does not ICE.
 //@ edition:2018
 
-#![feature(async_closure)]
-
 fn main() {
     let _ = |x: x| x; //~ ERROR expected type
     let _ = |x: bool| -> x { x }; //~ ERROR expected type
diff --git a/tests/ui/closures/local-type-mix.stderr b/tests/ui/closures/local-type-mix.stderr
index 68c320a065d..f3b6a73afd5 100644
--- a/tests/ui/closures/local-type-mix.stderr
+++ b/tests/ui/closures/local-type-mix.stderr
@@ -1,47 +1,47 @@
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:7:17
+  --> $DIR/local-type-mix.rs:5:17
    |
 LL |     let _ = |x: x| x;
    |                 ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:8:26
+  --> $DIR/local-type-mix.rs:6:26
    |
 LL |     let _ = |x: bool| -> x { x };
    |                          ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:9:28
+  --> $DIR/local-type-mix.rs:7:28
    |
 LL |     let _ = async move |x: x| x;
    |                            ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:10:37
+  --> $DIR/local-type-mix.rs:8:37
    |
 LL |     let _ = async move |x: bool| -> x { x };
    |                                     ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:13:11
+  --> $DIR/local-type-mix.rs:11:11
    |
 LL | fn foo(x: x) {}
    |           ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:14:24
+  --> $DIR/local-type-mix.rs:12:24
    |
 LL | fn foo_ret(x: bool) -> x {}
    |                        ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:16:23
+  --> $DIR/local-type-mix.rs:14:23
    |
 LL | async fn async_foo(x: x) {}
    |                       ^ not a type
 
 error[E0573]: expected type, found local variable `x`
-  --> $DIR/local-type-mix.rs:17:36
+  --> $DIR/local-type-mix.rs:15:36
    |
 LL | async fn async_foo_ret(x: bool) -> x {}
    |                                    ^ not a type
diff --git a/tests/ui/codegen/alias-uninit-value.rs b/tests/ui/codegen/alias-uninit-value.rs
new file mode 100644
index 00000000000..a8aa94caaf2
--- /dev/null
+++ b/tests/ui/codegen/alias-uninit-value.rs
@@ -0,0 +1,26 @@
+//! Regression test for issue #374, where previously rustc performed conditional jumps or moves that
+//! incorrectly depended on uninitialized values.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/374>.
+
+//@ run-pass
+
+#![allow(dead_code)]
+
+enum TyS {
+    Nil,
+}
+
+struct RawT {
+    struct_: TyS,
+    cname: Option<String>,
+    hash: usize,
+}
+
+fn mk_raw_ty(st: TyS, cname: Option<String>) -> RawT {
+    return RawT { struct_: st, cname: cname, hash: 0 };
+}
+
+pub fn main() {
+    mk_raw_ty(TyS::Nil, None::<String>);
+}
diff --git a/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs b/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
index d0597fdd8e1..7d8b1a1156c 100644
--- a/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
+++ b/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
@@ -1,7 +1,6 @@
 //@ edition: 2024
 
 #![feature(gen_blocks)]
-#![feature(async_closure)]
 
 async fn async_fn() {
     break; //~ ERROR `break` inside `async` function
diff --git a/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
index bdd26d39d82..ee838fbe694 100644
--- a/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
+++ b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
@@ -1,5 +1,5 @@
 error[E0267]: `break` inside `async` function
-  --> $DIR/break-inside-coroutine-issue-124495.rs:7:5
+  --> $DIR/break-inside-coroutine-issue-124495.rs:6:5
    |
 LL | async fn async_fn() {
    | ------------------- enclosing `async` function
@@ -7,7 +7,7 @@ LL |     break;
    |     ^^^^^ cannot `break` inside `async` function
 
 error[E0267]: `break` inside `gen` function
-  --> $DIR/break-inside-coroutine-issue-124495.rs:11:5
+  --> $DIR/break-inside-coroutine-issue-124495.rs:10:5
    |
 LL | gen fn gen_fn() {
    | --------------- enclosing `gen` function
@@ -15,7 +15,7 @@ LL |     break;
    |     ^^^^^ cannot `break` inside `gen` function
 
 error[E0267]: `break` inside `async gen` function
-  --> $DIR/break-inside-coroutine-issue-124495.rs:15:5
+  --> $DIR/break-inside-coroutine-issue-124495.rs:14:5
    |
 LL | async gen fn async_gen_fn() {
    | --------------------------- enclosing `async gen` function
@@ -23,7 +23,7 @@ LL |     break;
    |     ^^^^^ cannot `break` inside `async gen` function
 
 error[E0267]: `break` inside `async` block
-  --> $DIR/break-inside-coroutine-issue-124495.rs:19:21
+  --> $DIR/break-inside-coroutine-issue-124495.rs:18:21
    |
 LL |     let _ = async { break; };
    |             -----   ^^^^^ cannot `break` inside `async` block
@@ -31,7 +31,7 @@ LL |     let _ = async { break; };
    |             enclosing `async` block
 
 error[E0267]: `break` inside `async` closure
-  --> $DIR/break-inside-coroutine-issue-124495.rs:21:24
+  --> $DIR/break-inside-coroutine-issue-124495.rs:20:24
    |
 LL |     let _ = async || { break; };
    |             --------   ^^^^^ cannot `break` inside `async` closure
@@ -39,7 +39,7 @@ LL |     let _ = async || { break; };
    |             enclosing `async` closure
 
 error[E0267]: `break` inside `gen` block
-  --> $DIR/break-inside-coroutine-issue-124495.rs:23:19
+  --> $DIR/break-inside-coroutine-issue-124495.rs:22:19
    |
 LL |     let _ = gen { break; };
    |             ---   ^^^^^ cannot `break` inside `gen` block
@@ -47,7 +47,7 @@ LL |     let _ = gen { break; };
    |             enclosing `gen` block
 
 error[E0267]: `break` inside `async gen` block
-  --> $DIR/break-inside-coroutine-issue-124495.rs:25:25
+  --> $DIR/break-inside-coroutine-issue-124495.rs:24:25
    |
 LL |     let _ = async gen { break; };
    |             ---------   ^^^^^ cannot `break` inside `async gen` block
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
new file mode 100644
index 00000000000..40b9e6536f5
--- /dev/null
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
@@ -0,0 +1,27 @@
+// ignore-tidy-linelength
+//! Check that `-A warnings` cli flag applies to non-lint warnings as well.
+//!
+//! This test tries to exercise that by checking that the "relaxing a default bound only does
+//! something for `?Sized`; all other traits are not bound by default" non-lint warning (normally
+//! warn-by-default) is suppressed if the `-A warnings` cli flag is passed.
+//!
+//! Take special note that `warnings` is a special pseudo lint group in relationship to non-lint
+//! warnings, which is somewhat special. This test does not exercise other `-A <other_lint_group>`
+//! that check that they are working in the same way, only `warnings` specifically.
+//!
+//! # Relevant context
+//!
+//! - Original impl PR: <https://github.com/rust-lang/rust/pull/21248>.
+//! - RFC 507 "Release channels":
+//!   <https://github.com/rust-lang/rfcs/blob/c017755b9bfa0421570d92ba38082302e0f3ad4f/text/0507-release-channels.md>.
+#![crate_type = "lib"]
+
+//@ revisions: without_flag with_flag
+
+//@[with_flag] compile-flags: -Awarnings
+
+//@ check-pass
+
+pub trait Trait {}
+pub fn f<T: ?Trait>() {}
+//[without_flag]~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
new file mode 100644
index 00000000000..b037847c70f
--- /dev/null
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
@@ -0,0 +1,8 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/allow-non-lint-warnings.rs:26:13
+   |
+LL | pub fn f<T: ?Trait>() {}
+   |             ^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
index c346be50856..c3dfcfb19cb 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -1,8 +1,6 @@
 //@ edition:2018
 //@ aux-build:edition-kw-macro-2015.rs
 
-#![feature(async_closure)]
-
 fn main() {}
 
 #[macro_use]
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
index aed5837abea..905e1249d97 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `async`
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:16:13
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:14:13
    |
 LL |     let mut async = 1;
    |             ^^^^^ expected identifier, found keyword
@@ -10,7 +10,7 @@ LL |     let mut r#async = 1;
    |             ++
 
 error: expected identifier, found keyword `async`
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:28:13
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13
    |
 LL |     module::async();
    |             ^^^^^ expected identifier, found keyword
@@ -21,7 +21,7 @@ LL |     module::r#async();
    |             ++
 
 error: no rules expected `r#async`
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:18:31
    |
 LL |     r#async = consumes_async!(r#async);
    |                               ^^^^^^^ no rules expected this token in macro call
@@ -33,7 +33,7 @@ LL |     (async) => (1)
    |      ^^^^^
 
 error: no rules expected keyword `async`
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:19:35
    |
 LL |     r#async = consumes_async_raw!(async);
    |                                   ^^^^^ no rules expected this token in macro call
@@ -50,19 +50,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move
 LL |     ($i: ident) => ($i)
    |                       ^ expected one of `move`, `|`, or `||`
    |
-  ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8
+  ::: $DIR/edition-keywords-2018-2015-parsing.rs:22:8
    |
 LL |     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
    |        -------------------- in this macro invocation
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:26:24
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:24:24
    |
 LL |     if passes_tt!(async) == 1 {}
    |                        ^ expected one of `move`, `|`, or `||`
 
 error[E0308]: mismatched types
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:31:33
+  --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33
    |
 LL |     let _recovery_witness: () = 0;
    |                            --   ^ expected `()`, found integer
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
index b75b68b3feb..1447c49ef71 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -1,8 +1,6 @@
 //@ edition:2018
 //@ aux-build:edition-kw-macro-2018.rs
 
-#![feature(async_closure)]
-
 fn main() {}
 
 #[macro_use]
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
index 6503e9cc73c..af5cc515bb2 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `async`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:23:13
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:21:13
    |
 LL |     let mut async = 1;
    |             ^^^^^ expected identifier, found keyword
@@ -10,7 +10,7 @@ LL |     let mut r#async = 1;
    |             ++
 
 error: expected identifier, found keyword `async`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:39:13
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:37:13
    |
 LL |     module::async();
    |             ^^^^^ expected identifier, found keyword
@@ -21,7 +21,7 @@ LL |     module::r#async();
    |             ++
 
 error: no rules expected `r#async`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:27:31
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:25:31
    |
 LL |     r#async = consumes_async!(r#async);
    |                               ^^^^^^^ no rules expected this token in macro call
@@ -33,7 +33,7 @@ LL |     (async) => (1)
    |      ^^^^^
 
 error: no rules expected keyword `async`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:28:35
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:26:35
    |
 LL |     r#async = consumes_async_raw!(async);
    |                                   ^^^^^ no rules expected this token in macro call
@@ -50,31 +50,31 @@ error: macro expansion ends with an incomplete expression: expected one of `move
 LL |     ($i: ident) => ($i)
    |                       ^ expected one of `move`, `|`, or `||`
    |
-  ::: $DIR/edition-keywords-2018-2018-parsing.rs:31:8
+  ::: $DIR/edition-keywords-2018-2018-parsing.rs:29:8
    |
 LL |     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
    |        -------------------- in this macro invocation
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:33:24
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:31:24
    |
 LL |     if passes_tt!(async) == 1 {}
    |                        ^ expected one of `move`, `|`, or `||`
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:16:23
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:14:23
    |
 LL |     ($i: ident) => ($i)
    |                       ^ expected one of `move`, `|`, or `||`
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:37:30
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:35:30
    |
 LL |     if local_passes_tt!(async) == 1 {}
    |                              ^ expected one of `move`, `|`, or `||`
 
 error[E0308]: mismatched types
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:42:33
+  --> $DIR/edition-keywords-2018-2018-parsing.rs:40:33
    |
 LL |     let _recovery_witness: () = 0;
    |                            --   ^ expected `()`, found integer
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed
index 91d30de74c7..11ec273fc4b 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed
+++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed
@@ -11,6 +11,8 @@ fn main() {
     m();
     q();
     let _ = meow();
+    let _ = fallback_return();
+    let _ = fully_apit();
 }
 
 fn m() {
@@ -49,3 +51,29 @@ fn meow() -> Result<(), ()> {
     //[e2024]~^ error: the trait bound `(): From<!>` is not satisfied
     Ok(())
 }
+
+pub fn takes_apit<T>(_y: impl Fn() -> T) -> Result<T, ()> {
+    Err(())
+}
+
+pub fn fallback_return() -> Result<(), ()> {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+    takes_apit::<()>(|| Default::default())?;
+    //[e2024]~^ error: the trait bound `!: Default` is not satisfied
+    Ok(())
+}
+
+fn mk<T>() -> Result<T, ()> {
+    Err(())
+}
+
+fn takes_apit2(_x: impl Default) {}
+
+fn fully_apit() -> Result<(), ()> {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+    takes_apit2(mk::<()>()?);
+    //[e2024]~^ error: the trait bound `!: Default` is not satisfied
+    Ok(())
+}
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
index 6fdb548c431..9009d617936 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
+++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
@@ -1,5 +1,5 @@
 warning: this function depends on never type fallback being `()`
-  --> $DIR/never-type-fallback-breaking.rs:16:1
+  --> $DIR/never-type-fallback-breaking.rs:18:1
    |
 LL | fn m() {
    | ^^^^^^
@@ -8,7 +8,7 @@ LL | fn m() {
    = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the types explicitly
 note: in edition 2024, the requirement `!: Default` will fail
-  --> $DIR/never-type-fallback-breaking.rs:20:17
+  --> $DIR/never-type-fallback-breaking.rs:22:17
    |
 LL |         true => Default::default(),
    |                 ^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     let x: () = match true {
    |          ++++
 
 warning: this function depends on never type fallback being `()`
-  --> $DIR/never-type-fallback-breaking.rs:28:1
+  --> $DIR/never-type-fallback-breaking.rs:30:1
    |
 LL | fn q() -> Option<()> {
    | ^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL | fn q() -> Option<()> {
    = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the types explicitly
 note: in edition 2024, the requirement `!: Default` will fail
-  --> $DIR/never-type-fallback-breaking.rs:35:5
+  --> $DIR/never-type-fallback-breaking.rs:37:5
    |
 LL |     deserialize()?;
    |     ^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL |     deserialize::<()>()?;
    |                ++++++
 
 warning: this function depends on never type fallback being `()`
-  --> $DIR/never-type-fallback-breaking.rs:45:1
+  --> $DIR/never-type-fallback-breaking.rs:47:1
    |
 LL | fn meow() -> Result<(), ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL | fn meow() -> Result<(), ()> {
    = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the types explicitly
 note: in edition 2024, the requirement `(): From<!>` will fail
-  --> $DIR/never-type-fallback-breaking.rs:48:5
+  --> $DIR/never-type-fallback-breaking.rs:50:5
    |
 LL |     help(1)?;
    |     ^^^^^^^
@@ -56,5 +56,43 @@ help: use `()` annotations to avoid fallback changes
 LL |     help::<(), _>(1)?;
    |         +++++++++
 
-warning: 3 warnings emitted
+warning: this function depends on never type fallback being `()`
+  --> $DIR/never-type-fallback-breaking.rs:59:1
+   |
+LL | pub fn fallback_return() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/never-type-fallback-breaking.rs:62:19
+   |
+LL |     takes_apit(|| Default::default())?;
+   |                   ^^^^^^^^^^^^^^^^^^
+help: use `()` annotations to avoid fallback changes
+   |
+LL |     takes_apit::<()>(|| Default::default())?;
+   |               ++++++
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/never-type-fallback-breaking.rs:73:1
+   |
+LL | fn fully_apit() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/never-type-fallback-breaking.rs:76:17
+   |
+LL |     takes_apit2(mk()?);
+   |                 ^^^^^
+help: use `()` annotations to avoid fallback changes
+   |
+LL |     takes_apit2(mk::<()>()?);
+   |                   ++++++
+
+warning: 5 warnings emitted
 
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
index 9d79dfb4099..2daf00f7804 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
+++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `!: Default` is not satisfied
-  --> $DIR/never-type-fallback-breaking.rs:20:17
+  --> $DIR/never-type-fallback-breaking.rs:22:17
    |
 LL |         true => Default::default(),
    |                 ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
@@ -8,7 +8,7 @@ LL |         true => Default::default(),
    = help: did you intend to use the type `()` here instead?
 
 error[E0277]: the trait bound `!: Default` is not satisfied
-  --> $DIR/never-type-fallback-breaking.rs:35:5
+  --> $DIR/never-type-fallback-breaking.rs:37:5
    |
 LL |     deserialize()?;
    |     ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
@@ -16,13 +16,13 @@ LL |     deserialize()?;
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
    = help: did you intend to use the type `()` here instead?
 note: required by a bound in `deserialize`
-  --> $DIR/never-type-fallback-breaking.rs:31:23
+  --> $DIR/never-type-fallback-breaking.rs:33:23
    |
 LL |     fn deserialize<T: Default>() -> Option<T> {
    |                       ^^^^^^^ required by this bound in `deserialize`
 
 error[E0277]: the trait bound `(): From<!>` is not satisfied
-  --> $DIR/never-type-fallback-breaking.rs:48:5
+  --> $DIR/never-type-fallback-breaking.rs:50:5
    |
 LL |     help(1)?;
    |     ^^^^^^^ the trait `From<!>` is not implemented for `()`
@@ -39,11 +39,36 @@ LL |     help(1)?;
            and 4 others
    = note: required for `!` to implement `Into<()>`
 note: required by a bound in `help`
-  --> $DIR/never-type-fallback-breaking.rs:42:20
+  --> $DIR/never-type-fallback-breaking.rs:44:20
    |
 LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result<T, ()> {
    |                    ^^^^^^^^ required by this bound in `help`
 
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `!: Default` is not satisfied
+  --> $DIR/never-type-fallback-breaking.rs:62:19
+   |
+LL |     takes_apit(|| Default::default())?;
+   |                   ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
+   |
+   = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
+   = help: did you intend to use the type `()` here instead?
+
+error[E0277]: the trait bound `!: Default` is not satisfied
+  --> $DIR/never-type-fallback-breaking.rs:76:17
+   |
+LL |     takes_apit2(mk()?);
+   |     ----------- ^^^^^ the trait `Default` is not implemented for `!`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
+   = help: did you intend to use the type `()` here instead?
+note: required by a bound in `takes_apit2`
+  --> $DIR/never-type-fallback-breaking.rs:71:25
+   |
+LL | fn takes_apit2(_x: impl Default) {}
+   |                         ^^^^^^^ required by this bound in `takes_apit2`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs
index 24e33ff6bf6..daafc526eff 100644
--- a/tests/ui/editions/never-type-fallback-breaking.rs
+++ b/tests/ui/editions/never-type-fallback-breaking.rs
@@ -11,6 +11,8 @@ fn main() {
     m();
     q();
     let _ = meow();
+    let _ = fallback_return();
+    let _ = fully_apit();
 }
 
 fn m() {
@@ -49,3 +51,29 @@ fn meow() -> Result<(), ()> {
     //[e2024]~^ error: the trait bound `(): From<!>` is not satisfied
     Ok(())
 }
+
+pub fn takes_apit<T>(_y: impl Fn() -> T) -> Result<T, ()> {
+    Err(())
+}
+
+pub fn fallback_return() -> Result<(), ()> {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+    takes_apit(|| Default::default())?;
+    //[e2024]~^ error: the trait bound `!: Default` is not satisfied
+    Ok(())
+}
+
+fn mk<T>() -> Result<T, ()> {
+    Err(())
+}
+
+fn takes_apit2(_x: impl Default) {}
+
+fn fully_apit() -> Result<(), ()> {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+    takes_apit2(mk()?);
+    //[e2024]~^ error: the trait bound `!: Default` is not satisfied
+    Ok(())
+}
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
index 3bb93cf2ea0..0c5b8a4d3b6 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: *mut Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18
@@ -29,7 +29,7 @@ LL |     fn foo(self: *const Self);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
index 7f0e02c91f8..3ffba533d63 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: Ptr<Self>) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:26:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: Box<Ptr<Self>>) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
@@ -29,7 +29,7 @@ LL |     fn foo(self: Ptr<Self>);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index 856e0595331..3eb87adb33a 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -7,7 +7,7 @@ LL |     fn foo(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
@@ -18,7 +18,7 @@ LL |     fn bar(self: *const Self) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
@@ -29,7 +29,7 @@ LL |     fn bar(self: *const Self);
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs
new file mode 100644
index 00000000000..d9ff45f57ec
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs
@@ -0,0 +1,14 @@
+//@ edition: 2021
+
+trait Foo {
+    async fn bar(&self);
+}
+
+async fn takes_dyn_trait(x: &dyn Foo) {
+    //~^ ERROR the trait `Foo` cannot be made into an object
+    x.bar().await;
+    //~^ ERROR the trait `Foo` cannot be made into an object
+    //~| ERROR the trait `Foo` cannot be made into an object
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
new file mode 100644
index 00000000000..f78fc422410
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
@@ -0,0 +1,48 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:7:30
+   |
+LL | async fn takes_dyn_trait(x: &dyn Foo) {
+   |                              ^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn bar(&self);
+   |              ^^^ ...because method `bar` is `async`
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:7
+   |
+LL |     x.bar().await;
+   |       ^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn bar(&self);
+   |              ^^^ ...because method `bar` is `async`
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:5
+   |
+LL |     x.bar().await;
+   |     ^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn bar(&self);
+   |              ^^^ ...because method `bar` is `async`
+   = help: consider moving `bar` to another trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs
index db5d7aa06d2..210ce60ef11 100644
--- a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs
+++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs
@@ -2,6 +2,5 @@
 
 fn test(_: impl async Fn()) {}
 //~^ ERROR `async` trait bounds are unstable
-//~| ERROR use of unstable library feature `async_closure`
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr
index abc7e37c45f..34727aef975 100644
--- a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr
@@ -9,16 +9,6 @@ LL | fn test(_: impl async Fn()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: use the desugared name of the async trait, such as `AsyncFn`
 
-error[E0658]: use of unstable library feature `async_closure`
-  --> $DIR/feature-gate-async-trait-bounds.rs:3:23
-   |
-LL | fn test(_: impl async Fn()) {}
-   |                       ^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
index 2150effc3b7..eb9e51a04c3 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>`
 LL |     fn cell(self: Cell<&Self>);
    |                   ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.rs b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs
index 898fe22fa23..8d8d0e71067 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.rs
+++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs
@@ -1,3 +1,9 @@
+//! Diagnostics test to check that higher-ranked lifetimes are properly named when being pretty
+//! printed in diagnostics.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/44887>
+//! PR: <https://github.com/rust-lang/rust/pull/44888>
+
 fn main() {
     f1(|_: (), _: ()| {}); //~ ERROR type mismatch
     f2(|_: (), _: ()| {}); //~ ERROR type mismatch
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr
index c28d856ad55..7e0cdba6ff2 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr
@@ -1,5 +1,5 @@
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     f1(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -10,7 +10,7 @@ LL |     f1(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:22:25
    |
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
    |                         ^^^^^^^^^^^^ required by this bound in `f1`
@@ -20,7 +20,7 @@ LL |     f1(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     f2(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -31,7 +31,7 @@ LL |     f2(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25
    |
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
@@ -41,7 +41,7 @@ LL |     f2(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     f3(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -52,7 +52,7 @@ LL |     f3(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:24:29
    |
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
    |                             ^^^^^^^^^^^^^^^ required by this bound in `f3`
@@ -62,7 +62,7 @@ LL |     f3(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
    |
 LL |     f4(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -73,7 +73,7 @@ LL |     f4(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25
    |
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
@@ -83,7 +83,7 @@ LL |     f4(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
    |
 LL |     f5(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -94,7 +94,7 @@ LL |     f5(|_: (), _: ()| {});
    = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f5`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:20:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25
    |
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
@@ -104,7 +104,7 @@ LL |     f5(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5
    |
 LL |     g1(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -115,7 +115,7 @@ LL |     g1(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25
    |
 LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1`
@@ -125,7 +125,7 @@ LL |     g1(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
    |
 LL |     g2(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -136,7 +136,7 @@ LL |     g2(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
    |
 LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
    |                         ^^^^^^^^^^^^^^^^ required by this bound in `g2`
@@ -146,7 +146,7 @@ LL |     g2(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5
    |
 LL |     g3(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -157,7 +157,7 @@ LL |     g3(|_: (), _: ()| {});
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:25
    |
 LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
@@ -167,7 +167,7 @@ LL |     g3(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
    |
 LL |     g4(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -178,7 +178,7 @@ LL |     g4(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:32:25
    |
 LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4`
@@ -188,7 +188,7 @@ LL |     g4(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5
    |
 LL |     h1(|_: (), _: (), _: (), _: ()| {});
    |     ^^^----------------------------^^^^
@@ -199,7 +199,7 @@ LL |     h1(|_: (), _: (), _: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
               found closure signature `fn((), (), (), ()) -> _`
 note: required by a bound in `h1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:25
    |
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
@@ -209,7 +209,7 @@ LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
    |            +              +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
    |
 LL |     h2(|_: (), _: (), _: (), _: ()| {});
    |     ^^^----------------------------^^^^
@@ -220,7 +220,7 @@ LL |     h2(|_: (), _: (), _: (), _: ()| {});
    = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
               found closure signature `fn((), (), (), ()) -> _`
 note: required by a bound in `h2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:25
    |
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
diff --git a/tests/ui/impl-trait/in-trait/sized-rpits-dont-need-pointer-like.rs b/tests/ui/impl-trait/in-trait/sized-rpits-dont-need-pointer-like.rs
new file mode 100644
index 00000000000..80850a2639f
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/sized-rpits-dont-need-pointer-like.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+// Make sure that we don't enforce that an RPIT that has `where Self: Sized` is pointer-like.
+
+trait Foo {
+    fn foo() -> impl Sized where Self: Sized {}
+}
+
+impl Foo for () {}
+
+fn main() {
+    let x: &dyn Foo = &();
+}
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
index 1eb88c71d54..ef8dd055a8a 100644
--- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
@@ -42,4 +42,8 @@ async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {}
 //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
 //~| WARN this changes meaning in Rust 2024
 
+pub fn parens(x: &i32) -> &(impl Clone + use<>) { x }
+//~^ ERROR `impl Clone` will capture more lifetimes than possibly intended in edition 2024
+//~| WARN this changes meaning in Rust 2024
+
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
index 6f1ef6a472f..ce1cfe1246f 100644
--- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
@@ -42,4 +42,8 @@ async fn async_fn<'a>(x: &'a ()) -> impl Sized {}
 //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
 //~| WARN this changes meaning in Rust 2024
 
+pub fn parens(x: &i32) -> &impl Clone { x }
+//~^ ERROR `impl Clone` will capture more lifetimes than possibly intended in edition 2024
+//~| WARN this changes meaning in Rust 2024
+
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
index 63c87cd46c8..965f8e7b672 100644
--- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
@@ -146,5 +146,24 @@ help: use the precise capturing `use<...>` syntax to make the captures explicit
 LL | async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {}
    |                                                +++++++
 
-error: aborting due to 7 previous errors
+error: `impl Clone` will capture more lifetimes than possibly intended in edition 2024
+  --> $DIR/overcaptures-2024.rs:45:28
+   |
+LL | pub fn parens(x: &i32) -> &impl Clone { x }
+   |                            ^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>
+note: specifically, this lifetime is in scope but not mentioned in the type's bounds
+  --> $DIR/overcaptures-2024.rs:45:18
+   |
+LL | pub fn parens(x: &i32) -> &impl Clone { x }
+   |                  ^
+   = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | pub fn parens(x: &i32) -> &(impl Clone + use<>) { x }
+   |                            +           ++++++++
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/issues/auxiliary/issue-111011.rs b/tests/ui/issues/auxiliary/issue-111011.rs
index 7130234f41e..0c1a8ce1cf6 100644
--- a/tests/ui/issues/auxiliary/issue-111011.rs
+++ b/tests/ui/issues/auxiliary/issue-111011.rs
@@ -1,5 +1,3 @@
-#![feature(async_closure)]
-
 //@ edition:2021
 
 fn foo<X>(x: impl FnOnce() -> Box<X>) {}
diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr
index ec50d863758..4b0a59fe12d 100644
--- a/tests/ui/issues/issue-56806.stderr
+++ b/tests/ui/issues/issue-56806.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>`
 LL |     fn dyn_instead_of_self(self: Box<dyn Trait>);
    |                                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs
index 2159dee7463..2daac12d7ac 100644
--- a/tests/ui/layout/post-mono-layout-cycle-2.rs
+++ b/tests/ui/layout/post-mono-layout-cycle-2.rs
@@ -1,8 +1,6 @@
 //@ build-fail
 //@ edition: 2021
 
-#![feature(async_closure)]
-
 use std::future::Future;
 use std::pin::pin;
 use std::task::*;
diff --git a/tests/ui/layout/post-mono-layout-cycle-2.stderr b/tests/ui/layout/post-mono-layout-cycle-2.stderr
index 2e8d237844e..d8c51deffe3 100644
--- a/tests/ui/layout/post-mono-layout-cycle-2.stderr
+++ b/tests/ui/layout/post-mono-layout-cycle-2.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in an async fn requires boxing
-  --> $DIR/post-mono-layout-cycle-2.rs:30:5
+  --> $DIR/post-mono-layout-cycle-2.rs:28:5
    |
 LL | /     async fn iter<T>(&mut self, iterator: T)
 LL | |
@@ -13,7 +13,7 @@ LL |           Blah::iter(self, iterator).await
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
 
 note: the above error was encountered while instantiating `fn Wrap::<()>::ice`
-  --> $DIR/post-mono-layout-cycle-2.rs:56:9
+  --> $DIR/post-mono-layout-cycle-2.rs:54:9
    |
 LL |         t.ice();
    |         ^^^^^^^
diff --git a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
index 3babf63347c..46804642af8 100644
--- a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
+++ b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr
@@ -7,7 +7,7 @@ LL |     async fn box_ref_Struct(self: Box<Self, impl FnMut(&mut Self)>) -> &u32
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs
index bc38af9867c..0467e87ce22 100644
--- a/tests/ui/lint/unused/lint-unused-mut-variables.rs
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs
@@ -3,7 +3,6 @@
 // Exercise the unused_mut attribute in some positive and negative cases
 
 #![warn(unused_mut)]
-#![feature(async_closure)]
 
 async fn baz_async(
     mut a: i32,
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
index dcda1e5306f..a16b6a378e9 100644
--- a/tests/ui/lint/unused/lint-unused-mut-variables.stderr
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
@@ -1,5 +1,5 @@
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:9:5
+  --> $DIR/lint-unused-mut-variables.rs:8:5
    |
 LL |     mut a: i32,
    |     ----^
@@ -13,7 +13,7 @@ LL | #![warn(unused_mut)]
    |         ^^^^^^^^^^
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:23:9
+  --> $DIR/lint-unused-mut-variables.rs:22:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -21,7 +21,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:14:5
+  --> $DIR/lint-unused-mut-variables.rs:13:5
    |
 LL |     mut a: i32,
    |     ----^
@@ -29,7 +29,7 @@ LL |     mut a: i32,
    |     help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:29:9
+  --> $DIR/lint-unused-mut-variables.rs:28:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -37,7 +37,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:39:9
+  --> $DIR/lint-unused-mut-variables.rs:38:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -45,7 +45,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:48:9
+  --> $DIR/lint-unused-mut-variables.rs:47:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -53,7 +53,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:57:9
+  --> $DIR/lint-unused-mut-variables.rs:56:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -61,7 +61,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:62:9
+  --> $DIR/lint-unused-mut-variables.rs:61:9
    |
 LL |         mut a: i32,
    |         ----^
@@ -69,7 +69,7 @@ LL |         mut a: i32,
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:107:14
+  --> $DIR/lint-unused-mut-variables.rs:106:14
    |
 LL |     let x = |mut y: isize| 10;
    |              ----^
@@ -77,7 +77,7 @@ LL |     let x = |mut y: isize| 10;
    |              help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:69:9
+  --> $DIR/lint-unused-mut-variables.rs:68:9
    |
 LL |     let mut a = 3;
    |         ----^
@@ -85,7 +85,7 @@ LL |     let mut a = 3;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:71:9
+  --> $DIR/lint-unused-mut-variables.rs:70:9
    |
 LL |     let mut a = 2;
    |         ----^
@@ -93,7 +93,7 @@ LL |     let mut a = 2;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:73:9
+  --> $DIR/lint-unused-mut-variables.rs:72:9
    |
 LL |     let mut b = 3;
    |         ----^
@@ -101,7 +101,7 @@ LL |     let mut b = 3;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:75:9
+  --> $DIR/lint-unused-mut-variables.rs:74:9
    |
 LL |     let mut a = vec![3];
    |         ----^
@@ -109,7 +109,7 @@ LL |     let mut a = vec![3];
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:77:10
+  --> $DIR/lint-unused-mut-variables.rs:76:10
    |
 LL |     let (mut a, b) = (1, 2);
    |          ----^
@@ -117,7 +117,7 @@ LL |     let (mut a, b) = (1, 2);
    |          help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:79:9
+  --> $DIR/lint-unused-mut-variables.rs:78:9
    |
 LL |     let mut a;
    |         ----^
@@ -125,7 +125,7 @@ LL |     let mut a;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:83:9
+  --> $DIR/lint-unused-mut-variables.rs:82:9
    |
 LL |     let mut b;
    |         ----^
@@ -133,7 +133,7 @@ LL |     let mut b;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:92:9
+  --> $DIR/lint-unused-mut-variables.rs:91:9
    |
 LL |         mut x => {}
    |         ----^
@@ -141,7 +141,7 @@ LL |         mut x => {}
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:99:10
+  --> $DIR/lint-unused-mut-variables.rs:98:10
    |
 LL |         (mut x, 1) |
    |          ----^
@@ -149,7 +149,7 @@ LL |         (mut x, 1) |
    |          help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:112:9
+  --> $DIR/lint-unused-mut-variables.rs:111:9
    |
 LL |     let mut a = &mut 5;
    |         ----^
@@ -157,7 +157,7 @@ LL |     let mut a = &mut 5;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:117:9
+  --> $DIR/lint-unused-mut-variables.rs:116:9
    |
 LL |     let mut b = (&mut a,);
    |         ----^
@@ -165,7 +165,7 @@ LL |     let mut b = (&mut a,);
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:120:9
+  --> $DIR/lint-unused-mut-variables.rs:119:9
    |
 LL |     let mut x = &mut 1;
    |         ----^
@@ -173,7 +173,7 @@ LL |     let mut x = &mut 1;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:132:9
+  --> $DIR/lint-unused-mut-variables.rs:131:9
    |
 LL |     let mut v : &mut Vec<()> = &mut vec![];
    |         ----^
@@ -181,7 +181,7 @@ LL |     let mut v : &mut Vec<()> = &mut vec![];
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:187:9
+  --> $DIR/lint-unused-mut-variables.rs:186:9
    |
 LL |     let mut raw_address_of_const = 1;
    |         ----^^^^^^^^^^^^^^^^^^^^
@@ -189,7 +189,7 @@ LL |     let mut raw_address_of_const = 1;
    |         help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:109:13
+  --> $DIR/lint-unused-mut-variables.rs:108:13
    |
 LL |     fn what(mut foo: isize) {}
    |             ----^^^
@@ -197,7 +197,7 @@ LL |     fn what(mut foo: isize) {}
    |             help: remove this `mut`
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:127:20
+  --> $DIR/lint-unused-mut-variables.rs:126:20
    |
 LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    ----^^^
@@ -205,7 +205,7 @@ LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:205:9
+  --> $DIR/lint-unused-mut-variables.rs:204:9
    |
 LL |     let mut b = vec![2];
    |         ----^
@@ -213,13 +213,13 @@ LL |     let mut b = vec![2];
    |         help: remove this `mut`
    |
 note: the lint level is defined here
-  --> $DIR/lint-unused-mut-variables.rs:201:8
+  --> $DIR/lint-unused-mut-variables.rs:200:8
    |
 LL | #[deny(unused_mut)]
    |        ^^^^^^^^^^
 
 warning: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:212:28
+  --> $DIR/lint-unused-mut-variables.rs:211:28
    |
 LL | fn write_through_reference(mut arg: &mut Arg) {
    |                            ----^^^
diff --git a/tests/ui/lint/unused/lint-unused-variables.rs b/tests/ui/lint/unused/lint-unused-variables.rs
index 84c26c334f0..e0035d6d725 100644
--- a/tests/ui/lint/unused/lint-unused-variables.rs
+++ b/tests/ui/lint/unused/lint-unused-variables.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: --cfg something
 //@ edition:2018
 
-#![feature(async_closure)]
 #![deny(unused_variables)]
 
 async fn foo_async(
diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr
index ef590d85aef..6106d4cd1bf 100644
--- a/tests/ui/lint/unused/lint-unused-variables.stderr
+++ b/tests/ui/lint/unused/lint-unused-variables.stderr
@@ -1,71 +1,71 @@
 error: unused variable: `a`
-  --> $DIR/lint-unused-variables.rs:8:5
+  --> $DIR/lint-unused-variables.rs:7:5
    |
 LL |     a: i32,
    |     ^ help: if this is intentional, prefix it with an underscore: `_a`
    |
 note: the lint level is defined here
-  --> $DIR/lint-unused-variables.rs:5:9
+  --> $DIR/lint-unused-variables.rs:4:9
    |
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unused variable: `a`
-  --> $DIR/lint-unused-variables.rs:22:9
+  --> $DIR/lint-unused-variables.rs:21:9
    |
 LL |         a: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_a`
 
 error: unused variable: `a`
-  --> $DIR/lint-unused-variables.rs:68:9
+  --> $DIR/lint-unused-variables.rs:67:9
    |
 LL |         a: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_a`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:14:5
+  --> $DIR/lint-unused-variables.rs:13:5
    |
 LL |     b: i32,
    |     ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:29:9
+  --> $DIR/lint-unused-variables.rs:28:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:34:9
+  --> $DIR/lint-unused-variables.rs:33:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:42:9
+  --> $DIR/lint-unused-variables.rs:41:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:47:9
+  --> $DIR/lint-unused-variables.rs:46:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:55:9
+  --> $DIR/lint-unused-variables.rs:54:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:60:9
+  --> $DIR/lint-unused-variables.rs:59:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:74:9
+  --> $DIR/lint-unused-variables.rs:73:9
    |
 LL |         b: i32,
    |         ^ help: if this is intentional, prefix it with an underscore: `_b`
diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs
index 4633038cc9b..1f98cdfb21f 100644
--- a/tests/ui/lint/unused/unused-closure.rs
+++ b/tests/ui/lint/unused/unused-closure.rs
@@ -1,7 +1,6 @@
 // Test that closures and coroutines are "must use" types.
 //@ edition:2018
 
-#![feature(async_closure)]
 #![feature(coroutines, stmt_expr_attributes)]
 #![deny(unused_must_use)]
 
diff --git a/tests/ui/lint/unused/unused-closure.stderr b/tests/ui/lint/unused/unused-closure.stderr
index c3a82402e0a..bc0e5173c33 100644
--- a/tests/ui/lint/unused/unused-closure.stderr
+++ b/tests/ui/lint/unused/unused-closure.stderr
@@ -1,5 +1,5 @@
 error: unused closure that must be used
-  --> $DIR/unused-closure.rs:9:5
+  --> $DIR/unused-closure.rs:8:5
    |
 LL | /     || {
 LL | |         println!("Hello!");
@@ -8,13 +8,13 @@ LL | |     };
    |
    = note: closures are lazy and do nothing unless called
 note: the lint level is defined here
-  --> $DIR/unused-closure.rs:6:9
+  --> $DIR/unused-closure.rs:5:9
    |
 LL | #![deny(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
 error: unused implementer of `Future` that must be used
-  --> $DIR/unused-closure.rs:13:5
+  --> $DIR/unused-closure.rs:12:5
    |
 LL |     async {};
    |     ^^^^^^^^
@@ -22,7 +22,7 @@ LL |     async {};
    = note: futures do nothing unless you `.await` or poll them
 
 error: unused closure that must be used
-  --> $DIR/unused-closure.rs:14:5
+  --> $DIR/unused-closure.rs:13:5
    |
 LL |     || async {};
    |     ^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL |     || async {};
    = note: closures are lazy and do nothing unless called
 
 error: unused closure that must be used
-  --> $DIR/unused-closure.rs:15:5
+  --> $DIR/unused-closure.rs:14:5
    |
 LL |     async || {};
    |     ^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL |     async || {};
    = note: closures are lazy and do nothing unless called
 
 error: unused array of boxed arrays of closures that must be used
-  --> $DIR/unused-closure.rs:18:5
+  --> $DIR/unused-closure.rs:17:5
    |
 LL |     [Box::new([|| {}; 10]); 1];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL |     [Box::new([|| {}; 10]); 1];
    = note: closures are lazy and do nothing unless called
 
 error: unused closure that must be used
-  --> $DIR/unused-closure.rs:20:5
+  --> $DIR/unused-closure.rs:19:5
    |
 LL |     vec![|| "a"].pop().unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |     vec![|| "a"].pop().unwrap();
    = note: closures are lazy and do nothing unless called
 
 error: unused closure that must be used
-  --> $DIR/unused-closure.rs:23:9
+  --> $DIR/unused-closure.rs:22:9
    |
 LL |         || true;
    |         ^^^^^^^
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index f405cd253de..a560bf4c6ef 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -3,7 +3,6 @@
 //@ compile-flags: --test
 
 #![allow(incomplete_features)]
-#![feature(async_closure)]
 #![feature(auto_traits)]
 #![feature(box_patterns)]
 #![feature(const_trait_impl)]
diff --git a/tests/ui/methods/call_method_unknown_referent.rs b/tests/ui/methods/call_method_unknown_referent.rs
new file mode 100644
index 00000000000..b01e2d80f7f
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent.rs
@@ -0,0 +1,48 @@
+//@ edition: 2018
+
+#![feature(arbitrary_self_types)]
+
+// tests that the referent type of a reference must be known to call methods on it
+
+struct SmartPtr<T>(T);
+
+impl<T> core::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+impl<T> SmartPtr<T> {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let val = 1_u32;
+    let ptr = &val;
+    let _a: i32 = (ptr as &_).read();
+    //~^ ERROR type annotations needed
+
+    // Same again, but with a smart pointer type
+    let val2 = 1_u32;
+    let rc = std::rc::Rc::new(val2);
+    let _b = (rc as std::rc::Rc<_>).read();
+    //~^ ERROR type annotations needed
+
+    // Same again, but with a smart pointer type
+    let ptr = SmartPtr(val);
+
+    // We can call unambiguous outer-type methods on this
+    (ptr as SmartPtr<_>).foo();
+    // ... but we can't follow the Receiver chain to the inner type
+    // because we end up with _.
+
+    // Because SmartPtr implements Receiver, it's arguable which of the
+    // following two diagnostics we'd want in this case:
+    // (a) "type annotations needed" (because the inner type is _)
+    // (b) "no method named `read` found for struct `SmartPtr`"
+    //     (ignoring the fact that there might have been methods on the
+    //      inner type, had it not been _)
+    // At present we produce error type (b), which is necessary because
+    // our resolution logic needs to be able to call methods such as foo()
+    // on the outer type even if the inner type is ambiguous.
+    let _c = (ptr as SmartPtr<_>).read();
+    //~^ ERROR no method named `read` found for struct `SmartPtr`
+}
diff --git a/tests/ui/methods/call_method_unknown_referent.stderr b/tests/ui/methods/call_method_unknown_referent.stderr
new file mode 100644
index 00000000000..748b02b52b5
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent.stderr
@@ -0,0 +1,29 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_unknown_referent.rs:20:31
+   |
+LL |     let _a: i32 = (ptr as &_).read();
+   |                               ^^^^ cannot infer type
+
+error[E0282]: type annotations needed
+  --> $DIR/call_method_unknown_referent.rs:26:37
+   |
+LL |     let _b = (rc as std::rc::Rc<_>).read();
+   |                                     ^^^^ cannot infer type
+
+error[E0599]: no method named `read` found for struct `SmartPtr` in the current scope
+  --> $DIR/call_method_unknown_referent.rs:46:35
+   |
+LL | struct SmartPtr<T>(T);
+   | ------------------ method `read` not found for this struct
+...
+LL |     let _c = (ptr as SmartPtr<_>).read();
+   |                                   ^^^^ method not found in `SmartPtr<_>`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `read`, perhaps you need to implement it:
+           candidate #1: `std::io::Read`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0599.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/methods/call_method_unknown_referent2.rs b/tests/ui/methods/call_method_unknown_referent2.rs
new file mode 100644
index 00000000000..b1615bd8d44
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_referent2.rs
@@ -0,0 +1,24 @@
+//@ edition: 2018
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+// tests that the referent type of a reference must be known to call methods on it
+
+struct SmartPtr<T>(T);
+
+impl<T> core::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+impl<T> SmartPtr<T> {
+    fn foo(&self) -> usize { 3 }
+}
+
+fn main() {
+    let val = 1_u32;
+    let ptr = SmartPtr(val);
+    // Ensure calls to outer methods work even if inner methods can't be
+    // resolved due to the type variable
+    assert_eq!((ptr as SmartPtr<_>).foo(), 3);
+}
diff --git a/tests/ui/mir/issue-68841.rs b/tests/ui/mir/issue-68841.rs
index 5638449b684..0eed46eb6ca 100644
--- a/tests/ui/mir/issue-68841.rs
+++ b/tests/ui/mir/issue-68841.rs
@@ -2,8 +2,6 @@
 //@ edition:2018
 //@ build-pass
 
-#![feature(async_closure)]
-
 use std::future::Future;
 
 fn async_closure() -> impl Future<Output = u8> {
diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
index b5b5d87e7dd..8d08fb7f2a8 100644
--- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
+++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
@@ -15,8 +15,8 @@ LL |     foo(|| panic!());
    = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
 help: use `()` annotations to avoid fallback changes
    |
-LL |     foo::<(), _>(|| panic!());
-   |        +++++++++
+LL |     foo::<()>(|| panic!());
+   |        ++++++
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/parser/as-precedence.rs b/tests/ui/parser/as-precedence.rs
new file mode 100644
index 00000000000..ca8328adb0e
--- /dev/null
+++ b/tests/ui/parser/as-precedence.rs
@@ -0,0 +1,18 @@
+//! Parser precedence test to help with [RFC 87 "Trait Bounds with Plus"][rfc-87], to check the
+//! precedence of the `as` operator in relation to some arithmetic bin-ops and parentheses.
+//!
+//! Editor's note: this test seems quite incomplete compared to what's possible nowadays. Maybe
+//! there's another set of tests whose coverage overshadows this test?
+//!
+//! [rfc-87]: https://rust-lang.github.io/rfcs/0087-trait-bounds-with-plus.html
+
+//@ run-pass
+
+#[allow(unused_parens)]
+fn main() {
+    assert_eq!(3 as usize * 3, 9);
+    assert_eq!(3 as (usize) * 3, 9);
+    assert_eq!(3 as (usize) / 3, 1);
+    assert_eq!(3 as usize + 3, 6);
+    assert_eq!(3 as (usize) + 3, 6);
+}
diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr
index a336923f4fd..112fdcad336 100644
--- a/tests/ui/parser/bad-name.stderr
+++ b/tests/ui/parser/bad-name.stderr
@@ -1,9 +1,3 @@
-error: field expressions cannot have generic arguments
-  --> $DIR/bad-name.rs:2:12
-   |
-LL |   let x.y::<isize>.z foo;
-   |            ^^^^^^^
-
 error: expected a pattern, found an expression
   --> $DIR/bad-name.rs:2:7
    |
@@ -18,5 +12,11 @@ error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator,
 LL |   let x.y::<isize>.z foo;
    |                      ^^^ expected one of 9 possible tokens
 
+error: field expressions cannot have generic arguments
+  --> $DIR/bad-name.rs:2:12
+   |
+LL |   let x.y::<isize>.z foo;
+   |            ^^^^^^^
+
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr
index 2de70789358..e1780fe9fd9 100644
--- a/tests/ui/parser/circular_modules_main.stderr
+++ b/tests/ui/parser/circular_modules_main.stderr
@@ -4,22 +4,5 @@ error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_
 LL | mod circular_modules_main;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0425]: cannot find function `hi_str` in module `circular_modules_main`
-  --> $DIR/circular_modules_hello.rs:7:43
-   |
-LL |     println!("{}", circular_modules_main::hi_str());
-   |                                           ^^^^^^ not found in `circular_modules_main`
-   |
-help: consider importing this function
-   |
-LL + use hi_str;
-   |
-help: if you import `hi_str`, refer to it directly
-   |
-LL -     println!("{}", circular_modules_main::hi_str());
-LL +     println!("{}", hi_str());
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/reachable/artificial-block.rs b/tests/ui/reachable/artificial-block.rs
new file mode 100644
index 00000000000..6d73ba1a972
--- /dev/null
+++ b/tests/ui/reachable/artificial-block.rs
@@ -0,0 +1,30 @@
+//! Check that we don't get compile errors on unreachable code after the `{ return 3; }` artificial
+//! block below. This test is run-pass to also exercise the codegen, but it might be possible to
+//! reduce to build-pass or even check-pass.
+//!
+//! This test was introduced as part of commit `a833f152baa17460e8414355e832d30d5161f8e8` which
+//! removes an "artificial block". See also commit `3d738e9e0634a4cd6239d1317bd7dad53be68dc8` for
+//! more elaboration, reproduced below (this is outdated for *today*'s rustc as of 2024-12-10, but
+//! is helpful to understand the original intention):
+//!
+//! > Return a fresh, unreachable context after ret, break, and cont
+//! >
+//! > This ensures we don't get compile errors on unreachable code (see
+//! > test/run-pass/artificial-block.rs for an example of sane code that wasn't compiling). In the
+//! > future, we might want to warn about non-trivial code appearing in an unreachable context,
+//! > and/or avoid generating unreachable code altogether (though I'm sure LLVM will weed it out as
+//! > well).
+//!
+//! Since then, `ret` became `return`, `int` became `isize` and `assert` became a macro.
+
+//@ run-pass
+
+fn f() -> isize {
+    {
+        return 3;
+    }
+}
+
+fn main() {
+    assert_eq!(f(), 3);
+}
diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs
new file mode 100644
index 00000000000..1e0772648af
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.rs
@@ -0,0 +1,7 @@
+mod parse_error;
+use parse_error::Canonical; // ok, `parse_error.rs` had parse errors
+
+fn main() {
+    let _ = "" + 1; //~ ERROR E0369
+    parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors
+}
diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr
new file mode 100644
index 00000000000..30475aa0ee6
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.stderr
@@ -0,0 +1,22 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+  --> $DIR/parse_error.rs:2:46
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {
+   |                                              ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical {
+   |                                             +
+
+error[E0369]: cannot add `{integer}` to `&str`
+  --> $DIR/parse-error-resolve.rs:5:16
+   |
+LL |     let _ = "" + 1;
+   |             -- ^ - {integer}
+   |             |
+   |             &str
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/resolve/parse_error.rs b/tests/ui/resolve/parse_error.rs
new file mode 100644
index 00000000000..4cd025e1edf
--- /dev/null
+++ b/tests/ui/resolve/parse_error.rs
@@ -0,0 +1,5 @@
+struct Canonical;
+impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical { //~ ERROR expected
+    fn foo() {}
+}
+fn bar() {}
diff --git a/tests/ui/resolve/parse_error.stderr b/tests/ui/resolve/parse_error.stderr
new file mode 100644
index 00000000000..f764f08875f
--- /dev/null
+++ b/tests/ui/resolve/parse_error.stderr
@@ -0,0 +1,13 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+  --> $DIR/parse_error.rs:2:46
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {
+   |                                              ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical {
+   |                                             +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs
index e7a5d59958b..15d2a2f5ebc 100644
--- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: --cfg something --check-cfg=cfg(nothing,something)
 //@ edition:2018
 
-#![feature(async_closure)]
 #![deny(unused_variables)]
 
 extern "C" {
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr
index 9b92166bcb7..ba92bc4a71d 100644
--- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr
@@ -1,119 +1,119 @@
 error: unused variable: `a`
-  --> $DIR/param-attrs-cfg.rs:24:23
+  --> $DIR/param-attrs-cfg.rs:23:23
    |
 LL |     #[cfg(something)] a: i32,
    |                       ^ help: if this is intentional, prefix it with an underscore: `_a`
    |
 note: the lint level is defined here
-  --> $DIR/param-attrs-cfg.rs:5:9
+  --> $DIR/param-attrs-cfg.rs:4:9
    |
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unused variable: `a`
-  --> $DIR/param-attrs-cfg.rs:41:27
+  --> $DIR/param-attrs-cfg.rs:40:27
    |
 LL |         #[cfg(something)] a: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_a`
 
 error: unused variable: `a`
-  --> $DIR/param-attrs-cfg.rs:107:27
+  --> $DIR/param-attrs-cfg.rs:106:27
    |
 LL |         #[cfg(something)] a: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_a`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:30:23
+  --> $DIR/param-attrs-cfg.rs:29:23
    |
 LL |     #[cfg(something)] b: i32,
    |                       ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:32:40
+  --> $DIR/param-attrs-cfg.rs:31:40
    |
 LL |     #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                        ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:48:27
+  --> $DIR/param-attrs-cfg.rs:47:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:50:44
+  --> $DIR/param-attrs-cfg.rs:49:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:56:27
+  --> $DIR/param-attrs-cfg.rs:55:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:58:44
+  --> $DIR/param-attrs-cfg.rs:57:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:67:27
+  --> $DIR/param-attrs-cfg.rs:66:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:69:44
+  --> $DIR/param-attrs-cfg.rs:68:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:75:27
+  --> $DIR/param-attrs-cfg.rs:74:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:77:44
+  --> $DIR/param-attrs-cfg.rs:76:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:86:27
+  --> $DIR/param-attrs-cfg.rs:85:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:88:44
+  --> $DIR/param-attrs-cfg.rs:87:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:94:27
+  --> $DIR/param-attrs-cfg.rs:93:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:96:44
+  --> $DIR/param-attrs-cfg.rs:95:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:113:27
+  --> $DIR/param-attrs-cfg.rs:112:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: if this is intentional, prefix it with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:115:44
+  --> $DIR/param-attrs-cfg.rs:114:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: if this is intentional, prefix it with an underscore: `_c`
diff --git a/tests/ui/sanitizer/cfi/async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs
index 4eaa44cfa3f..351853ab1a7 100644
--- a/tests/ui/sanitizer/cfi/async-closures.rs
+++ b/tests/ui/sanitizer/cfi/async-closures.rs
@@ -13,7 +13,6 @@
 //@ [kcfi] compile-flags: -C panic=abort -Z panic-abort-tests -C prefer-dynamic=off
 //@ run-pass
 
-#![feature(async_closure)]
 #![feature(async_fn_traits)]
 
 use std::ops::AsyncFn;
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs
new file mode 100644
index 00000000000..495d261c549
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs
@@ -0,0 +1,64 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::{Receiver, Deref};
+
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        self.0
+    }
+}
+
+impl<'a, T: ?Sized> Clone for SmartPtr<'a, T> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+}
+
+impl<'a, T: ?Sized> Copy for SmartPtr<'a, T> {
+}
+
+struct Foo(u32);
+impl Foo {
+    fn a<R: Receiver<Target=Self>>(self: R) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `R`
+        2
+    }
+    fn b<R: Deref<Target=Self>>(self: R) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `R`
+        self.0
+    }
+    fn c(self: impl Receiver<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+        3
+    }
+    fn d(self: impl Deref<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Deref<Target = Self>`
+        self.0
+    }
+}
+
+fn main() {
+    let foo = Foo(1);
+    assert_eq!((&foo).a::<&Foo>(), 2);
+    assert_eq!((&foo).b::<&Foo>(), 1);
+    assert_eq!((&foo).a(), 2);
+    assert_eq!((&foo).b(), 1);
+    assert_eq!((&foo).c(), 3);
+    assert_eq!((&foo).d(), 1);
+    assert_eq!(foo.a::<&Foo>(), 2);
+    //~^ ERROR mismatched types
+    assert_eq!(foo.b::<&Foo>(), 1);
+    //~^ ERROR mismatched types
+    let smart_ptr = SmartPtr(&foo);
+    assert_eq!(smart_ptr.a(), 2);
+    assert_eq!(smart_ptr.b(), 1);
+    assert_eq!(smart_ptr.c(), 3);
+    assert_eq!(smart_ptr.d(), 1);
+    assert_eq!(smart_ptr.a::<&Foo>(), 2);
+    //~^ ERROR mismatched types
+    assert_eq!(smart_ptr.b::<&Foo>(), 1);
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr
new file mode 100644
index 00000000000..9af2a08f371
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr
@@ -0,0 +1,70 @@
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:25:42
+   |
+LL |     fn a<R: Receiver<Target=Self>>(self: R) -> u32 {
+   |                                          ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:29:39
+   |
+LL |     fn b<R: Deref<Target=Self>>(self: R) -> u32 {
+   |                                       ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:33:16
+   |
+LL |     fn c(self: impl Receiver<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Deref<Target = Self>`
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:37:16
+   |
+LL |     fn d(self: impl Deref<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:51:16
+   |
+LL |     assert_eq!(foo.a::<&Foo>(), 2);
+   |                ^^^ expected `&Foo`, found `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:53:16
+   |
+LL |     assert_eq!(foo.b::<&Foo>(), 1);
+   |                ^^^ expected `&Foo`, found `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:60:16
+   |
+LL |     assert_eq!(smart_ptr.a::<&Foo>(), 2);
+   |                ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16
+   |
+LL |     assert_eq!(smart_ptr.b::<&Foo>(), 1);
+   |                ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0801.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
index 5dc3a0b0234..7cf9c9a3afd 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
@@ -61,7 +61,7 @@ LL |     fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/arbitrary-self-from-method-substs.rs:61:18
@@ -72,7 +72,7 @@ LL |     fn get(self: R) {}
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
   --> $DIR/arbitrary-self-from-method-substs.rs:92:9
diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr
index c75165d9f8e..0469aca27dc 100644
--- a/tests/ui/self/arbitrary-self-opaque.stderr
+++ b/tests/ui/self/arbitrary-self-opaque.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar`
 LL |     fn foo(self: Bar) {}
    |                  ^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
   --> $DIR/arbitrary-self-opaque.rs:7:8
diff --git a/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs b/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs
new file mode 100644
index 00000000000..de4db1b9afe
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs
@@ -0,0 +1,69 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(dead_code)]
+
+// With arbitrary self types v2, we show an error if there are
+// multiple contenders for a method call in an inner and outer type.
+// The goal is to avoid any possibility of confusion by a new
+// 'shadowing' method calling a 'shadowed' method.
+// However, there are niche circumstances where this
+// algorithm doesn't quite work, due to reborrows to get a different
+// lifetime. The test below explicitly tests those circumstances to ensure
+// the behavior is as expected, even if it's not 100% desirable. They're
+// very niche circumstances.
+
+#[derive(Debug, PartialEq)]
+enum Callee {
+    INNER,
+    OUTER
+}
+
+struct MyNonNull<T>(T);
+
+impl<T> std::ops::Receiver for MyNonNull<T> {
+    type Target = T;
+}
+
+struct A;
+impl A {
+    fn foo(self: MyNonNull<A>) -> Callee {
+        Callee::INNER
+    }
+
+    fn bar(self: &MyNonNull<A>) -> Callee {
+        Callee::INNER
+    }
+
+    fn baz(self: &&MyNonNull<A>) -> Callee {
+        // note this is by DOUBLE reference
+        Callee::INNER
+    }
+}
+
+impl<T> MyNonNull<T> {
+    fn foo(&self) -> Callee{
+        Callee::OUTER
+    }
+
+    fn bar(&self) -> Callee{
+        Callee::OUTER
+    }
+
+    fn baz(&self) -> Callee{
+        Callee::OUTER
+    }
+}
+
+fn main() {
+    // The normal deshadowing case. Does not compile.
+    // assert_eq!(MyNonNull(A).foo(), Callee::INNER);
+
+    // Similarly, does not compile.
+    //assert_eq!(MyNonNull(A).bar(), Callee::INNER);
+
+    // The double-reference case.
+    // We call the newly-added outer type method.
+    // Not ideal but very niche so we accept it.
+    assert_eq!(MyNonNull(A).baz(), Callee::OUTER);
+}
diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs
new file mode 100644
index 00000000000..8ccda9368ad
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs
@@ -0,0 +1,23 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::{Receiver, Deref};
+
+struct Foo(u32);
+impl Foo {
+    fn a(self: impl Receiver<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+        3
+    }
+    fn b(self: impl Deref<Target=Self>) -> u32 {
+        //~^ ERROR invalid generic `self` parameter type: `impl Deref<Target = Self>`
+        self.0
+    }
+}
+
+fn main() {
+    let foo = Foo(1);
+    foo.a();
+    //~^ ERROR the trait bound
+    foo.b();
+    //~^ ERROR the trait bound
+}
diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr
new file mode 100644
index 00000000000..2da3925341e
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr
@@ -0,0 +1,59 @@
+error[E0801]: invalid generic `self` parameter type: `impl Receiver<Target = Self>`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:16
+   |
+LL |     fn a(self: impl Receiver<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl Deref<Target = Self>`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:16
+   |
+LL |     fn b(self: impl Deref<Target=Self>) -> u32 {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0277]: the trait bound `Foo: std::ops::Receiver` is not satisfied
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:19:9
+   |
+LL |     foo.a();
+   |         ^ the trait `std::ops::Receiver` is not implemented for `Foo`
+   |
+   = note: required for `Foo` to implement `std::ops::Receiver`
+note: required by a bound in `Foo::a`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:21
+   |
+LL |     fn a(self: impl Receiver<Target=Self>) -> u32 {
+   |                     ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::a`
+help: consider borrowing here
+   |
+LL |     &foo.a();
+   |     +
+LL |     &mut foo.a();
+   |     ++++
+
+error[E0277]: the trait bound `Foo: Deref` is not satisfied
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:21:9
+   |
+LL |     foo.b();
+   |         ^ the trait `Deref` is not implemented for `Foo`
+   |
+note: required by a bound in `Foo::b`
+  --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:21
+   |
+LL |     fn b(self: impl Deref<Target=Self>) -> u32 {
+   |                     ^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider borrowing here
+   |
+LL |     &foo.b();
+   |     +
+LL |     &mut foo.b();
+   |     ++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0801.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/self/arbitrary_self_types_generic_receiver.rs b/tests/ui/self/arbitrary_self_types_generic_receiver.rs
new file mode 100644
index 00000000000..0739fb778b6
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_receiver.rs
@@ -0,0 +1,50 @@
+#![feature(arbitrary_self_types)]
+
+struct PtrA<T>(T);
+
+impl<T> core::ops::Receiver for PtrA<T> {
+    type Target = T;
+}
+
+struct PtrB<T>(T);
+
+trait SomePtr: core::ops::Receiver<Target=<Self as SomePtr>::SomeTarget> {
+    type SomeTarget;
+}
+
+impl<T> SomePtr for PtrB<T> {
+    type SomeTarget = T;
+}
+
+impl<T> core::ops::Receiver for PtrB<T> {
+    type Target = T;
+}
+
+struct Content;
+
+impl Content {
+    fn a<R: core::ops::Receiver<Target=Self>>(self: &R) {}
+    //~^ ERROR invalid generic
+    fn b<R: core::ops::Receiver<Target=Self>>(self: &mut R) {}
+    //~^ ERROR invalid generic
+    fn c<R: core::ops::Receiver<Target=Self>>(self: R) {}
+    //~^ ERROR invalid generic
+    fn d<R: SomePtr<SomeTarget=Self>>(self: R) {}
+    //~^ ERROR invalid generic
+    fn e(self: impl SomePtr<SomeTarget=Self>) {}
+    //~^ ERROR invalid generic
+}
+
+fn main() {
+    PtrA(Content).a();
+    PtrA(Content).b();
+    PtrA(Content).c();
+    std::rc::Rc::new(Content).a();
+    std::rc::Rc::new(Content).b();
+    std::rc::Rc::new(Content).c();
+    PtrB(Content).a();
+    PtrB(Content).b();
+    PtrB(Content).c();
+    PtrB(Content).d();
+    PtrB(Content).e();
+}
diff --git a/tests/ui/self/arbitrary_self_types_generic_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_receiver.stderr
new file mode 100644
index 00000000000..788c55ea2f1
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_generic_receiver.stderr
@@ -0,0 +1,48 @@
+error[E0801]: invalid generic `self` parameter type: `&R`
+  --> $DIR/arbitrary_self_types_generic_receiver.rs:26:53
+   |
+LL |     fn a<R: core::ops::Receiver<Target=Self>>(self: &R) {}
+   |                                                     ^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&mut R`
+  --> $DIR/arbitrary_self_types_generic_receiver.rs:28:53
+   |
+LL |     fn b<R: core::ops::Receiver<Target=Self>>(self: &mut R) {}
+   |                                                     ^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary_self_types_generic_receiver.rs:30:53
+   |
+LL |     fn c<R: core::ops::Receiver<Target=Self>>(self: R) {}
+   |                                                     ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary_self_types_generic_receiver.rs:32:45
+   |
+LL |     fn d<R: SomePtr<SomeTarget=Self>>(self: R) {}
+   |                                             ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `impl SomePtr<SomeTarget = Self>`
+  --> $DIR/arbitrary_self_types_generic_receiver.rs:34:16
+   |
+LL |     fn e(self: impl SomePtr<SomeTarget=Self>) {}
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0801`.
diff --git a/tests/ui/self/arbitrary_self_types_lifetime_elision.rs b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs
new file mode 100644
index 00000000000..fd645c1013b
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs
@@ -0,0 +1,27 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+#[derive(Clone)]
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> std::ops::Receiver for SmartPtr<'a, T> {
+    type Target = T;
+}
+
+#[derive(Clone)]
+struct MyType;
+
+impl MyType {
+    fn m(self: SmartPtr<Self>) {}
+    fn n(self: SmartPtr<'_, Self>) {}
+    fn o<'a>(self: SmartPtr<'a, Self>) {}
+}
+
+fn main() {
+    let a = MyType;
+    let ptr = SmartPtr(&a);
+    ptr.clone().m();
+    ptr.clone().n();
+    ptr.o();
+}
diff --git a/tests/ui/self/arbitrary_self_types_no_generics.rs b/tests/ui/self/arbitrary_self_types_no_generics.rs
new file mode 100644
index 00000000000..8a6f5741882
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_no_generics.rs
@@ -0,0 +1,32 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+
+pub struct A;
+
+impl A {
+    pub fn f(self: B) -> i32 { 1 }
+}
+
+pub struct B(A);
+
+impl core::ops::Receiver for B {
+    type Target = A;
+}
+
+struct C;
+
+struct D;
+
+impl C {
+    fn weird(self: D) -> i32 { 3 }
+}
+
+impl core::ops::Receiver for D {
+    type Target = C;
+}
+
+fn main() {
+    assert_eq!(B(A).f(), 1);
+    assert_eq!(D.weird(), 3);
+}
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs
new file mode 100644
index 00000000000..26e48f69d23
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs
@@ -0,0 +1,38 @@
+#![feature(arbitrary_self_types)]
+
+use std::rc::Rc;
+
+struct Foo;
+
+struct CppRef<T>(T);
+
+impl<T> std::ops::Receiver for CppRef<T> {
+    type Target = T;
+}
+
+impl Foo{
+    fn frobnicate_self(self) {}
+    fn frobnicate_ref(&self) {}
+    fn frobnicate_cpp_ref(self: CppRef<Self>) {}
+}
+
+fn main() {
+    let foo_rc = Rc::new(Foo);
+
+    // this compiles fine, and desugars to `Foo::frobnicate_ref(&*foo_rc)`
+    foo_rc.frobnicate_ref();
+
+    let foo_cpp_ref = CppRef(Foo);
+
+    // should not compile because it would desugar to `Foo::frobnicate_ref(&*foo_cpp_ref)`
+    // and you can't deref a CppRef
+    foo_cpp_ref.frobnicate_ref();
+    //~^ ERROR no method named
+
+    foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+    //~^ ERROR no method named
+
+    // should compile, because we're not dereffing the CppRef
+    // desugars to `Foo::frobnicate_cpp_ref(foo_cpp_ref)`
+    foo_cpp_ref.frobnicate_cpp_ref();
+}
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
new file mode 100644
index 00000000000..4c0ab88493e
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
@@ -0,0 +1,39 @@
+error[E0599]: no method named `frobnicate_ref` found for struct `CppRef` in the current scope
+  --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:29:17
+   |
+LL | struct CppRef<T>(T);
+   | ---------------- method `frobnicate_ref` not found for this struct
+...
+LL |     foo_cpp_ref.frobnicate_ref();
+   |                 ^^^^^^^^^^^^^^
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     foo_cpp_ref.0.frobnicate_ref();
+   |                 ++
+help: there is a method `frobnicate_cpp_ref` with a similar name
+   |
+LL |     foo_cpp_ref.frobnicate_cpp_ref();
+   |                 ~~~~~~~~~~~~~~~~~~
+
+error[E0599]: no method named `frobnicate_self` found for struct `CppRef` in the current scope
+  --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:32:17
+   |
+LL | struct CppRef<T>(T);
+   | ---------------- method `frobnicate_self` not found for this struct
+...
+LL |     foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ^^^^^^^^^^^^^^^
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     foo_cpp_ref.0.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ++
+help: there is a method `frobnicate_cpp_ref` with a similar name
+   |
+LL |     foo_cpp_ref.frobnicate_cpp_ref(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)`
+   |                 ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
new file mode 100644
index 00000000000..f3e7f96d7c4
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
@@ -0,0 +1,32 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+
+struct MyNonNull<T>(*const T);
+
+impl<T> std::ops::Receiver for MyNonNull<T> {
+    type Target = T;
+}
+
+#[allow(dead_code)]
+impl<T> MyNonNull<T> {
+    fn foo<U>(&self) -> *const U {
+        self.cast::<U>().bar()
+    }
+    fn cast<U>(&self) -> MyNonNull<U> {
+        MyNonNull(self.0 as *const U)
+    }
+    fn bar(&self) -> *const T {
+        self.0
+    }
+}
+
+#[repr(transparent)]
+struct Foo(usize);
+#[repr(transparent)]
+struct Bar(usize);
+
+fn main() {
+    let a = Foo(3);
+    let ptr = MyNonNull(&a);
+    let _bar_ptr: *const Bar = ptr.foo();
+}
diff --git a/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs b/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs
new file mode 100644
index 00000000000..2b718cb0454
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs
@@ -0,0 +1,33 @@
+//@ run-pass
+
+#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
+
+pub struct A;
+
+impl A {
+    pub fn f(self: *const MyNonNull<Self>) -> i32 { 1 }
+}
+
+pub struct MyNonNull<T>(T);
+
+impl<T> core::ops::Receiver for MyNonNull<T> {
+    type Target = T;
+}
+
+impl<T> MyNonNull<T> {
+    // Imagine this a NEW method in B<T> shadowing an EXISTING
+    // method in A.
+    pub fn f(self: *mut Self) -> i32 {
+        2
+    }
+}
+
+fn main() {
+    let mut b = MyNonNull(A);
+    let b = &mut b;
+    let b = b as *mut MyNonNull<A>;
+    // We actually allow the shadowing in the case of const vs mut raw
+    // pointer receivers.
+    assert_eq!(b.f(), 2);
+}
diff --git a/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs
new file mode 100644
index 00000000000..cebf0ea7cba
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs
@@ -0,0 +1,31 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+
+use std::ops::Receiver;
+
+struct SmartPtr<T>(T);
+
+impl<T> Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+struct Foo {
+    x: i32,
+    y: i32,
+}
+
+impl Foo {
+    fn x(self: &SmartPtr<Self>) -> i32 {
+        self.0.x
+    }
+
+    fn y(self: SmartPtr<Self>) -> i32 {
+        self.0.y
+    }
+}
+
+fn main() {
+    let foo = SmartPtr(Foo {x: 3, y: 4});
+    assert_eq!(3, foo.x());
+    assert_eq!(4, foo.y());
+}
diff --git a/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs
new file mode 100644
index 00000000000..9c0402da0be
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs
@@ -0,0 +1,25 @@
+//@ run-pass
+#![feature(arbitrary_self_types)]
+#![allow(unused_allocation)]
+
+struct SmartPtr<T: ?Sized>(T);
+
+impl<T: ?Sized> std::ops::Receiver for SmartPtr<T> {
+    type Target = T;
+}
+
+trait Trait {
+    fn trait_method<'a>(self: &'a Box<SmartPtr<Self>>) -> &'a [i32];
+}
+
+impl Trait for Vec<i32> {
+    fn trait_method<'a>(self: &'a Box<SmartPtr<Self>>) -> &'a [i32] {
+        &(**self).0
+    }
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+
+    assert_eq!(&[1, 2, 3], Box::new(SmartPtr(v)).trait_method());
+}
diff --git a/tests/ui/self/arbitrary_self_types_unshadowing.rs b/tests/ui/self/arbitrary_self_types_unshadowing.rs
new file mode 100644
index 00000000000..cd195654cc1
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_unshadowing.rs
@@ -0,0 +1,55 @@
+#![feature(arbitrary_self_types)]
+
+pub struct A;
+
+// The receiver of the potentially shadowed method
+// precisely matches that of the shadower
+impl A {
+    pub fn f(self: Wrapper<Self>) -> i32 { 1 }
+    pub fn g(self: &Wrapper<Self>) -> i32 { 2 }
+    pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 }
+}
+
+// The receiver of the potentially shadowed method is a reference
+pub struct B;
+
+impl B {
+    pub fn f(self: &Wrapper<Self>) -> i32 { 9 }
+}
+
+// The receiver of the potentially shadowed method is a mut reference
+
+pub struct C;
+
+impl C {
+    pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 }
+    pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 }
+}
+
+pub struct Wrapper<T>(T);
+
+impl<T> core::ops::Receiver for Wrapper<T> {
+    type Target = T;
+}
+
+impl<T> Wrapper<T> {
+    pub fn f(self) -> i32 { 5 }
+    pub fn g(&self) -> i32 { 6 }
+    pub fn h(&mut self) -> i32 { 7 }
+}
+
+fn main() {
+    assert_eq!(Wrapper(A).f(), 1);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(A).g(), 2);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(A).h(), 3);
+    //~^ ERROR: multiple applicable items in scope
+    let a = Wrapper(A);
+    assert_eq!(Wrapper(B).f(), 9);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(C).f(), 10);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(C).g(), 11);
+    //~^ ERROR: multiple applicable items in scope
+}
diff --git a/tests/ui/self/arbitrary_self_types_unshadowing.stderr b/tests/ui/self/arbitrary_self_types_unshadowing.stderr
new file mode 100644
index 00000000000..3a126c495c9
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_unshadowing.stderr
@@ -0,0 +1,105 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:42:27
+   |
+LL |     assert_eq!(Wrapper(A).f(), 1);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:8:5
+   |
+LL |     pub fn f(self: Wrapper<Self>) -> i32 { 1 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:36:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:44:27
+   |
+LL |     assert_eq!(Wrapper(A).g(), 2);
+   |                           ^ multiple `g` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:9:5
+   |
+LL |     pub fn g(self: &Wrapper<Self>) -> i32 { 2 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:37:5
+   |
+LL |     pub fn g(&self) -> i32 { 6 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:46:27
+   |
+LL |     assert_eq!(Wrapper(A).h(), 3);
+   |                           ^ multiple `h` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:10:5
+   |
+LL |     pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:38:5
+   |
+LL |     pub fn h(&mut self) -> i32 { 7 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:49:27
+   |
+LL |     assert_eq!(Wrapper(B).f(), 9);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `B`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:17:5
+   |
+LL |     pub fn f(self: &Wrapper<Self>) -> i32 { 9 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:36:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:51:27
+   |
+LL |     assert_eq!(Wrapper(C).f(), 10);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `C`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:25:5
+   |
+LL |     pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:36:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing.rs:53:27
+   |
+LL |     assert_eq!(Wrapper(C).g(), 11);
+   |                           ^ multiple `g` found
+   |
+note: candidate #1 is defined in an impl for the type `C`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:26:5
+   |
+LL |     pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing.rs:37:5
+   |
+LL |     pub fn g(&self) -> i32 { 6 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs
new file mode 100644
index 00000000000..62553c2622a
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs
@@ -0,0 +1,61 @@
+#![feature(arbitrary_self_types_pointers)]
+#![feature(arbitrary_self_types)]
+
+pub struct A;
+
+// The receiver of the potentially shadowed method
+// precisely matches that of the shadower
+impl A {
+    pub fn f(self: Wrapper<Self>) -> i32 { 1 }
+    pub fn g(self: &Wrapper<Self>) -> i32 { 2 }
+    pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 }
+    pub fn i(self: *const Wrapper<Self>) -> i32 { 4 }
+}
+
+// The receiver of the potentially shadowed method is a reference
+pub struct B;
+
+impl B {
+    pub fn f(self: &Wrapper<Self>) -> i32 { 9 }
+}
+
+// The receiver of the potentially shadowed method is a mut reference
+
+pub struct C;
+
+impl C {
+    pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 }
+    pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 }
+}
+
+pub struct Wrapper<T>(T);
+
+impl<T> core::ops::Receiver for Wrapper<T> {
+    type Target = T;
+}
+
+impl<T> Wrapper<T> {
+    pub fn f(self) -> i32 { 5 }
+    pub fn g(&self) -> i32 { 6 }
+    pub fn h(&mut self) -> i32 { 7 }
+    pub fn i(self: *const Self) -> i32 { 8 }
+}
+
+fn main() {
+    assert_eq!(Wrapper(A).f(), 1);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(A).g(), 2);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(A).h(), 3);
+    //~^ ERROR: multiple applicable items in scope
+    let a = Wrapper(A);
+    let a_ptr = &a as *const Wrapper<A>;
+    assert_eq!(a_ptr.i(), 4);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(B).f(), 9);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(C).f(), 10);
+    //~^ ERROR: multiple applicable items in scope
+    assert_eq!(Wrapper(C).g(), 11);
+    //~^ ERROR: multiple applicable items in scope
+}
diff --git a/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr
new file mode 100644
index 00000000000..6d453aed0f0
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr
@@ -0,0 +1,122 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:45:27
+   |
+LL |     assert_eq!(Wrapper(A).f(), 1);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:9:5
+   |
+LL |     pub fn f(self: Wrapper<Self>) -> i32 { 1 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:47:27
+   |
+LL |     assert_eq!(Wrapper(A).g(), 2);
+   |                           ^ multiple `g` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:10:5
+   |
+LL |     pub fn g(self: &Wrapper<Self>) -> i32 { 2 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:39:5
+   |
+LL |     pub fn g(&self) -> i32 { 6 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:49:27
+   |
+LL |     assert_eq!(Wrapper(A).h(), 3);
+   |                           ^ multiple `h` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:11:5
+   |
+LL |     pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:40:5
+   |
+LL |     pub fn h(&mut self) -> i32 { 7 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:53:22
+   |
+LL |     assert_eq!(a_ptr.i(), 4);
+   |                      ^ multiple `i` found
+   |
+note: candidate #1 is defined in an impl for the type `A`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:12:5
+   |
+LL |     pub fn i(self: *const Wrapper<Self>) -> i32 { 4 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:41:5
+   |
+LL |     pub fn i(self: *const Self) -> i32 { 8 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:55:27
+   |
+LL |     assert_eq!(Wrapper(B).f(), 9);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `B`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:19:5
+   |
+LL |     pub fn f(self: &Wrapper<Self>) -> i32 { 9 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:57:27
+   |
+LL |     assert_eq!(Wrapper(C).f(), 10);
+   |                           ^ multiple `f` found
+   |
+note: candidate #1 is defined in an impl for the type `C`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:27:5
+   |
+LL |     pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5
+   |
+LL |     pub fn f(self) -> i32 { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:59:27
+   |
+LL |     assert_eq!(Wrapper(C).g(), 11);
+   |                           ^ multiple `g` found
+   |
+note: candidate #1 is defined in an impl for the type `C`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:28:5
+   |
+LL |     pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<T>`
+  --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:39:5
+   |
+LL |     pub fn g(&self) -> i32 { 6 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/self/conflicting_inner.rs b/tests/ui/self/conflicting_inner.rs
new file mode 100644
index 00000000000..1a7037dce73
--- /dev/null
+++ b/tests/ui/self/conflicting_inner.rs
@@ -0,0 +1,38 @@
+//@ run-pass
+//@ revisions: default feature
+#![cfg_attr(feature, feature(arbitrary_self_types))]
+
+// This test aims to be like the IndexVec within rustc, and conflicts
+// over its into_iter().
+
+#[allow(dead_code)]
+trait Foo {
+    fn foo(self) -> usize;
+}
+
+struct IndexVec<T>(T);
+
+impl<T> std::ops::Deref for IndexVec<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<'a, T> Foo for &'a IndexVec<T> {
+    fn foo(self) -> usize {
+        2
+    }
+}
+
+impl<T> IndexVec<T> {
+    fn foo(self) -> usize {
+        1
+    }
+}
+
+fn main() {
+    let ivec = IndexVec(0usize);
+    assert_eq!(ivec.foo(), 1);
+}
diff --git a/tests/ui/self/conflicting_inner2.rs b/tests/ui/self/conflicting_inner2.rs
new file mode 100644
index 00000000000..e6a6b5ef793
--- /dev/null
+++ b/tests/ui/self/conflicting_inner2.rs
@@ -0,0 +1,63 @@
+//@ run-pass
+//@ revisions: default feature
+#![cfg_attr(feature, feature(arbitrary_self_types))]
+
+use std::pin::Pin;
+use std::ops::DerefMut;
+use std::marker::Unpin;
+
+struct TryChunks;
+
+impl TryChunks {
+    #[allow(dead_code)]
+    fn take(self: std::pin::Pin<&mut Self>) -> usize {
+        1
+    }
+}
+
+#[allow(dead_code)]
+trait Stream {
+    fn poll_next(self: std::pin::Pin<&mut Self>);
+}
+
+#[allow(dead_code)]
+trait StreamExt: Stream {
+    #[allow(dead_code)]
+    fn take(self) -> usize where Self: Sized
+    {
+        2
+    }
+}
+
+impl<T: ?Sized> StreamExt for T where T: Stream {}
+
+impl Stream for TryChunks {
+    fn poll_next(self: std::pin::Pin<&mut Self>) {
+        assert_eq!(self.take(), 1);
+    }
+}
+
+#[allow(dead_code)]
+impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
+    #[allow(dead_code)]
+    fn poll_next(mut self: Pin<&mut Self>)  {
+        S::poll_next(Pin::new(&mut **self))
+    }
+}
+
+#[allow(dead_code)]
+impl<P> Stream for Pin<P>
+where
+    P: DerefMut + Unpin,
+    P::Target: Stream,
+{
+    #[allow(dead_code)]
+    fn poll_next(self: Pin<&mut Self>) {
+        self.get_mut().as_mut().poll_next()
+    }
+}
+
+fn main() {
+    let mut item = Box::pin(TryChunks);
+    item.as_mut().poll_next();
+}
diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr
index c57a100bbe2..04904b0ddc1 100644
--- a/tests/ui/span/issue-27522.stderr
+++ b/tests/ui/span/issue-27522.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType`
 LL |     fn handler(self: &SomeType);
    |                      ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/structs/default-field-values-support.rs b/tests/ui/structs/default-field-values-support.rs
index da0379af94b..8209d6dd4a0 100644
--- a/tests/ui/structs/default-field-values-support.rs
+++ b/tests/ui/structs/default-field-values-support.rs
@@ -1,18 +1,23 @@
+// Exercise the `default_field_values` feature to confirm it interacts correctly with other nightly
+// features. In particular, we want to verify that interaction with consts coming from different
+// contexts are usable as a default field value.
 //@ run-pass
 //@ aux-build:struct_field_default.rs
-#![feature(default_field_values, generic_const_exprs)]
+#![feature(const_trait_impl, default_field_values, generic_const_exprs)]
 #![allow(unused_variables, dead_code, incomplete_features)]
 
 extern crate struct_field_default as xc;
 
 pub struct S;
 
+// Basic expressions and `Default` expansion
 #[derive(Default)]
 pub struct Foo {
     pub bar: S = S,
     pub baz: i32 = 42 + 3,
 }
 
+// Enum support for deriving `Default` when all fields have default values
 #[derive(Default)]
 pub enum Bar {
     #[default]
@@ -22,17 +27,27 @@ pub enum Bar {
     }
 }
 
-#[derive(Default)]
-pub struct Qux<A, const C: i32> {
-    bar: S = Qux::<A, C>::S,
-    baz: i32 = foo(),
-    bat: i32 = <Qux<A, C> as T>::K,
-    baq: i32 = Self::K,
-    bay: i32 = C,
-    bak: Vec<A> = Vec::new(),
+#[const_trait] pub trait ConstDefault {
+    fn value() -> Self;
+}
+
+impl const ConstDefault for i32 {
+    fn value() -> i32 {
+        101
+    }
+}
+
+pub struct Qux<A, const C: i32, X: const ConstDefault> {
+    bar: S = Qux::<A, C, X>::S, // Associated constant from inherent impl
+    baz: i32 = foo(), // Constant function
+    bat: i32 = <Qux<A, C, X> as T>::K, // Associated constant from explicit trait
+    baq: i32 = Self::K, // Associated constant from implicit trait
+    bay: i32 = C, // `const` parameter
+    bak: Vec<A> = Vec::new(), // Associated constant function
+    ban: X = X::value(), // Associated constant function from `const` trait parameter
 }
 
-impl<A, const C: i32> Qux<A, C> {
+impl<A, const C: i32, X: const ConstDefault> Qux<A, C, X> {
     const S: S = S;
 }
 
@@ -40,7 +55,7 @@ trait T {
     const K: i32;
 }
 
-impl<A, const C: i32> T for Qux<A, C> {
+impl<A, const C: i32, X: const ConstDefault> T for Qux<A, C, X> {
     const K: i32 = 2;
 }
 
@@ -65,8 +80,19 @@ fn main () {
     assert!(matches!(Bar::Foo { bar: S, baz: 45 }, y));
     assert!(matches!(Bar::Foo { bar: S, baz: 1 }, z));
 
-    let x = Qux::<i32, 4> { .. };
-    assert!(matches!(Qux::<i32, 4> { bar: S, baz: 42, bat: 2, baq: 2, bay: 4, .. }, x));
+    let x = Qux::<i32, 4, i32> { .. };
+    assert!(matches!(
+        Qux::<i32, 4, i32> {
+            bar: S,
+            baz: 42,
+            bat: 2,
+            baq: 2,
+            bay: 4,
+            ban: 101,
+            ..
+        },
+        x,
+    ));
     assert!(x.bak.is_empty());
 
     let x = xc::A { .. };
diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
index 11ed167b44a..8e67f4e7398 100644
--- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
@@ -1,5 +1,4 @@
 //@ edition:2018
-#![feature(async_closure)]
 use std::future::Future;
 
 async fn foo() {}
diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index a040e71cf3b..696b156d5a5 100644
--- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future
-  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9
+  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:9:9
    |
 LL |     bar(foo);
    |     --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future
@@ -8,7 +8,7 @@ LL |     bar(foo);
    |
    = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
 note: required by a bound in `bar`
-  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
+  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:6:16
    |
 LL | fn bar(f: impl Future<Output=()>) {}
    |                ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
@@ -17,17 +17,17 @@ help: use parentheses to call this function
 LL |     bar(foo());
    |            ++
 
-error[E0277]: `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
-  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
+error[E0277]: `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:25: 10:33}` is not a future
+  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:9
    |
 LL |     bar(async_closure);
-   |     --- ^^^^^^^^^^^^^ `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
+   |     --- ^^^^^^^^^^^^^ `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:25: 10:33}` is not a future
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
+   = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:25: 10:33}`
 note: required by a bound in `bar`
-  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
+  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:6:16
    |
 LL | fn bar(f: impl Future<Output=()>) {}
    |                ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
index beafd7c2ab0..eb9f9196a72 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
@@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()`
 LL |     fn bar(self: ()) {}
    |                  ^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/method-missing-parentheses.rs b/tests/ui/suggestions/method-missing-parentheses.rs
index f10bfb56d2e..bc576b71f0d 100644
--- a/tests/ui/suggestions/method-missing-parentheses.rs
+++ b/tests/ui/suggestions/method-missing-parentheses.rs
@@ -1,5 +1,4 @@
 fn main() {
     let _ = vec![].into_iter().collect::<usize>;
     //~^ ERROR attempted to take value of method `collect` on type `std::vec::IntoIter<_>`
-    //~| ERROR field expressions cannot have generic arguments
 }
diff --git a/tests/ui/suggestions/method-missing-parentheses.stderr b/tests/ui/suggestions/method-missing-parentheses.stderr
index 1bfff56a6a9..f0ff1f0334a 100644
--- a/tests/ui/suggestions/method-missing-parentheses.stderr
+++ b/tests/ui/suggestions/method-missing-parentheses.stderr
@@ -1,9 +1,3 @@
-error: field expressions cannot have generic arguments
-  --> $DIR/method-missing-parentheses.rs:2:41
-   |
-LL |     let _ = vec![].into_iter().collect::<usize>;
-   |                                         ^^^^^^^
-
 error[E0615]: attempted to take value of method `collect` on type `std::vec::IntoIter<_>`
   --> $DIR/method-missing-parentheses.rs:2:32
    |
@@ -15,6 +9,6 @@ help: use parentheses to call the method
 LL |     let _ = vec![].into_iter().collect::<usize>();
    |                                                ++
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0615`.
diff --git a/tests/ui/suggestions/suggest-boxed-empty-block.fixed b/tests/ui/suggestions/suggest-boxed-empty-block.fixed
index 25cb4dc74b1..a43e4405a76 100644
--- a/tests/ui/suggestions/suggest-boxed-empty-block.fixed
+++ b/tests/ui/suggestions/suggest-boxed-empty-block.fixed
@@ -1,5 +1,3 @@
-#![feature(async_closure)]
-
 //@ edition:2021
 //@ run-rustfix
 
diff --git a/tests/ui/suggestions/suggest-boxed-empty-block.rs b/tests/ui/suggestions/suggest-boxed-empty-block.rs
index 9a8d6498fb1..47fb08e4d11 100644
--- a/tests/ui/suggestions/suggest-boxed-empty-block.rs
+++ b/tests/ui/suggestions/suggest-boxed-empty-block.rs
@@ -1,5 +1,3 @@
-#![feature(async_closure)]
-
 //@ edition:2021
 //@ run-rustfix
 
diff --git a/tests/ui/suggestions/suggest-boxed-empty-block.stderr b/tests/ui/suggestions/suggest-boxed-empty-block.stderr
index 474a37b888f..e4602341c1f 100644
--- a/tests/ui/suggestions/suggest-boxed-empty-block.stderr
+++ b/tests/ui/suggestions/suggest-boxed-empty-block.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/suggest-boxed-empty-block.rs:10:9
+  --> $DIR/suggest-boxed-empty-block.rs:8:9
    |
 LL |     foo({});
    |         ^^ expected `Box<_>`, found `()`
@@ -14,7 +14,7 @@ LL +     foo(Box::new(()));
    |
 
 error[E0308]: mismatched types
-  --> $DIR/suggest-boxed-empty-block.rs:11:12
+  --> $DIR/suggest-boxed-empty-block.rs:9:12
    |
 LL |     bar(|| {});
    |            ^^ expected `Box<_>`, found `()`
diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.rs b/tests/ui/suggestions/suggest-on-bare-closure-call.rs
index 046fe4803ec..1e6b422de5e 100644
--- a/tests/ui/suggestions/suggest-on-bare-closure-call.rs
+++ b/tests/ui/suggestions/suggest-on-bare-closure-call.rs
@@ -1,7 +1,5 @@
 //@ edition:2021
 
-#![feature(async_closure)]
-
 fn main() {
     let _ = ||{}();
     //~^ ERROR expected function, found `()`
diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
index e65a6eb4939..7bbb24aa622 100644
--- a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
+++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
@@ -1,5 +1,5 @@
 error[E0618]: expected function, found `()`
-  --> $DIR/suggest-on-bare-closure-call.rs:6:15
+  --> $DIR/suggest-on-bare-closure-call.rs:4:15
    |
 LL |     let _ = ||{}();
    |               ^^--
@@ -12,7 +12,7 @@ LL |     let _ = (||{})();
    |             +    +
 
 error[E0618]: expected function, found `()`
-  --> $DIR/suggest-on-bare-closure-call.rs:9:21
+  --> $DIR/suggest-on-bare-closure-call.rs:7:21
    |
 LL |     let _ = async ||{}();
    |                     ^^--
diff --git a/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs b/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs
new file mode 100644
index 00000000000..2295c2c3857
--- /dev/null
+++ b/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs
@@ -0,0 +1,22 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/133526>.
+
+// Ensures we don't ICE when we encounter a `HostEffectPredicate` when computing
+// the "item super predicates" for `Assoc`.
+
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Trait {
+    type Assoc: const Trait;
+}
+
+const fn needs_trait<T: ~const Trait>() {}
+
+fn test<T: Trait>() {
+    const { needs_trait::<T::Assoc>() };
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
index aaa61e21155..e606d896e93 100644
--- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
+++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
@@ -110,6 +110,16 @@ impl<T: ?Sized> LegacyReceiver for &T {}
 
 impl<T: ?Sized> LegacyReceiver for &mut T {}
 
+#[lang = "receiver"]
+pub trait Receiver {
+    #[lang = "receiver_target"]
+    type Target: ?Sized;
+}
+
+impl<T: Deref + ?Sized> Receiver for T {
+    type Target = <T as Deref>::Target;
+}
+
 #[lang = "destruct"]
 #[const_trait]
 pub trait Destruct {}
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 86234d15a5d..1c58915111f 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht<Self, T>`
 LL |     fn foo(self: Smaht<Self, T>);
    |                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
   --> $DIR/issue-78372.rs:3:1
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
index 09efd7a9e7e..c6aa0e811f3 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<u32>`
 LL |     fn bar(self: Bar<u32>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<u32>`
   --> $DIR/method_resolution3.rs:20:18
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<u32>`
 LL |     fn baz(self: &Bar<u32>) {
    |                  ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
index 09efd7a9e7e..c6aa0e811f3 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<u32>`
 LL |     fn bar(self: Bar<u32>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<u32>`
   --> $DIR/method_resolution3.rs:20:18
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<u32>`
 LL |     fn baz(self: &Bar<u32>) {
    |                  ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
index 8ffdb21f251..e4c4d121733 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<Foo>`
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
   --> $DIR/method_resolution4.rs:31:20
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
index 8ffdb21f251..e4c4d121733 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar<Foo>`
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
   --> $DIR/method_resolution4.rs:31:20
@@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
index 2a8c4edbdb5..36bdc714e05 100644
--- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize`
 LL |     fn foo(self: isize, x: isize) -> isize {
    |                  ^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `Bar<isize>`
   --> $DIR/ufcs-explicit-self-bad.rs:19:18
@@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar<isize>`
 LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
    |                  ^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<usize>`
   --> $DIR/ufcs-explicit-self-bad.rs:23:18
@@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<usize>`
 LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
    |                  ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or a type that dereferences to it
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:37:21
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 9af57fe4c3c..98fe05cf7c8 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -2,7 +2,6 @@
 //@ edition:2024
 //@ check-pass
 
-#![feature(async_closure)]
 #![feature(auto_traits)]
 #![feature(box_patterns)]
 #![feature(builtin_syntax)]
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 14a274415ca..452c06dd7e4 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -3,7 +3,6 @@
 //@ edition:2024
 //@ check-pass
 
-#![feature(async_closure)]
 #![feature(auto_traits)]
 #![feature(box_patterns)]
 #![feature(builtin_syntax)]
diff --git a/triagebot.toml b/triagebot.toml
index 6eb4cb50d0d..214fc2a21c4 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -991,12 +991,21 @@ https://github.com/rust-lang/reference/blob/HEAD/src/identifiers.md.
 cc = ["@ehuss"]
 
 [assign]
-warn_non_default_branch = true
+warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "jyn514",
+    "celinval",
 ]
 
+[[assign.warn_non_default_branch.exceptions]]
+title = "[beta"
+branch = "beta"
+
+[[assign.warn_non_default_branch.exceptions]]
+title = "[stable"
+branch = "stable"
+
 [assign.adhoc_groups]
 compiler = [
     "@BoxyUwU",